While building a dark theme for my React App, I've found myself escaping the nesting a lot in order to make styles for the dark theme .
Then, this mixin was born.
Show me the code!
@mixin atDarkTheme {
$selector: #{&};
@at-root body.dark-theme #{$selector} {
@content
}
}
It's worth mentioning, this will work in any kind of project that uses Sass, not just React.
And even though styled components can tackle theming easily too, I'm a fan of Scss and having my components styled with their own Scss file.
Breakdown
When dark mode is enabled, <body>
receives the class dark-theme
. So in order to prepend the body.dark-theme
selector the mixin works like this:
-
$selector: parses our current selector making use of
&
(parent selector) and#{}
, and then stores it for later use. -
@at-root: moves the next selector to the root of the document, escaping the current nesting.
-
body.dark-theme: the class that will be responsible for our dark-mode styles.
-
#{selector}: adding our previous selector back again.
-
@content: everything we add between the brackets
{}
in our@include
goes here.
-
@content: everything we add between the brackets
-
#{selector}: adding our previous selector back again.
-
body.dark-theme: the class that will be responsible for our dark-mode styles.
Usage
.just-a-box {
background: white; // ☀
color: black; // ☀
width: 100px;
height: 100px;
// Dark Theme styles
@include atDarkTheme {
background: black; // 🌙
color: white; // 🌙
}
}
After compiling this code into CSS, it will look like this:
.just-a-box {
background: white;
color: black;
width: 100px;
height: 100px;
}
body.dark-theme .just-a-box {
background: black;
color: white;
}
🧬Evolving the mixin: Multiple Themes
Why conform with dark mode, let's create themes with one mixin to rule'em all!
@mixin atTheme($theme: "default") {
$selector: #{&};
@at-root body.#{$theme}-theme #{$selector} {
@content
}
}
Usage
Now we can pass an argument to the mixin to dinamically add styles to the themes we create.
.amazing-navbar {
background: white;
color: black;
width: 100%;
height: 52px;
// Theme styles
@include atTheme("red") {
background: red; // 🟥
}
@include atTheme("green") {
background: green; // 🟩
}
@include atTheme("blue") {
background: blue; // 🟦
}
@include atTheme("halloween") {
background: purple; // 👻
}
}
After compiling this code into CSS, it will look like this:
.amazing-navbar {
background: white;
color: black;
width: 100%;
height: 52px;
}
body.red-theme .amazing-navbar {
background: red;
}
body.blue-theme .amazing-navbar {
background: blue;
}
body.green-theme .amazing-navbar {
background: green;
}
body.halloween-theme .amazing-navbar {
background: purple;
}
💡A few more ideas
To keep the post simple I'll just give you a few hints to where you can improve upon on your project:
- CSS Variables
- Predefined $themes variable to check if the argument passed to the atTheme mixin is valid.
- "Automatic" dark-theming with the invert filter.
Conclusion
Using @at-root
directive in mixins will save us a lot of time, creating theme-specific selectors for our elements we are working on in a breeze, relying only in CSS' powerful specificity.
If this post was any help or do you think this can be improved upon, let me know in the comments!
If you are still hungry for more sassy knowledge, I've written another post about it and the Bulma framework.
Highlighting awesome SASS snippets from Bulma
Lucas G. Terracino ・ Oct 15 '20 ・ 4 min read
Until next time 👋!
Top comments (1)
Thanks for this awesome lines!!!