DEV Community

Cover image for 🎩 JavaScript Enhanced SCSS mixins! 🎩 - Making CSS scopes with CSS variables.
Adam Crockett
Adam Crockett

Posted on

🎩 JavaScript Enhanced SCSS mixins! 🎩 - Making CSS scopes with CSS variables.

reposted due to improved code

This is a very small implementation of css scopes, the approach is unique because it compiles the scope through a mixin in scss, this is shared with JavaScript by a teeny tiny IFFE function. The scss does most of the heavy lifting.

How to use?

1 include the 15 lines mixin in your codebase
2 include the 43 lines of JavaScript
3 Do this:

.some-stuff {
  @include scoped {
    background: red;
  };
}
Enter fullscreen mode Exit fullscreen mode

So there is something really nice about seemingly styling with scss and JavaScript filling in the gaps.

How does it work?

The mixin captures the selector that it is used within, then it generates a GUID per compile and per instance of the mixin call.
The probability of a clash in this GUID is something like 1 in 32429858953958, I will take those odds, frankly you're more likely to win the lottery.
The mixin then uses @at-root :root to escape from its block and assign a generated css variable to the :root mainly because we will know where the unique variables live, the variable name contains a guid class and the captured elements class.

Now enter JavaScript, the variable we just set is now available to JavaScript, I wanted a plugin-and-play feeling so the function is an IFFE.
There is a catch, because at the time of writing, there is no way to get a list of variables on an element directly so with no idea of the keys we have to resort to functionally scraping the vars from any stylesheets that have the same origin as this webpage. This amounted to 1 stylesheet in most cases, and its pretty fast in truth. Now we have a lovely array of css variables ['--guid-12345', '--guid-98765']. If getPropertyValue within a loop, we can now get the guid class to assign and the captured target element. The only thing left to do is assign the class as well, something like --guid-12345: .scope-12345,.target-selector.

-Gotcha, livereload doesn't work very well due to not re-compiling the scss and therefore a mismatched guid, but if your happy to just refresh the page like we did in the good old days then you will find everything is going to work in prod-

What else can we do with this technique?

Discussion (0)