<div class='some-stuff'>
<p class='child'>
I am scoped
</p>
</div>
<div class='some-stuff'>
<p class='child'>
I am not scoped
</p>
</div>
@mixin scoped() {
$target: &;
@at-root {
$uuid: "#{unique-id()}-#{unique-id()}-#{unique-id()}-#{unique-id()}";
$pointer: '.scoped-#{$uuid}';
:root {
--guid-#{$uuid}: '#{$target},#{$pointer}';
}
& {
&#{$pointer} {
@content
}
}
}
}
// Usage
// Scoped
.some-stuff {
@include scoped {
.child {
background: red;
}
};
}
// Global
.some-stuff {
.child {
padding: 20px;
color: #fff;
background: blue;
width: 400px;
border-radius: 4px;
margin: 20px auto;
}
}
View Compiled
// Just drop this code in and your golden
// scans local stylesheets for variables
const getCssVars = (selector = ":root") => Array.from(document.styleSheets)
.filter(
sheet =>
sheet.href === null || sheet.href.startsWith(window.location.origin)
)
.reduce(
(acc, sheet) =>
(acc = [
...acc,
...Array.from(sheet.cssRules).reduce(
(def, rule) => ( def = rule.selectorText === selector ? [
...def,
...Array.from(rule.style).filter(name =>
name.startsWith("--")
)
]
: def
),
[]
)
]),
[]
);
;(() => {
// Which elemenet has the varibles
const variableScope = ":root";
const computedRootStyle = getComputedStyle(document.querySelector(variableScope));
const cssRootVars = getCssVars().filter(rule => rule);
// get the target elemenets and assign the classes
for (const guid of cssRootVars) {
const REMOVE_DOT = 1;
const [target, scopeClass] = computedRootStyle.getPropertyValue(guid)
.split(',')
.map(string => string.replace('"', ''));
console.log(target, scopeClass)
document.querySelector(target).classList.add(scopeClass.substring(REMOVE_DOT));
}
})();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.