Dark mode / dark theme implementation in SASS

Hi, i'm trying to upgrade my portfolio step by step and right now, i'd like to implement a dark mode. I'm using a custom SASS framework which defines color variables, and uses them through the website. So, as SASS is generated once at build time, how is it possible to have a "simple" solution to implement a toggle which would allow to change color rendering on my website when dark/light mode is checked ? The JS part is ok, but i can't quite figure out the SASS/CSS part. What i mean by that is, i'm looking for a solution in which i don't have to go specific on each component that requires dark mode, but rather throw a .dark-mode class on the body tag and rely on the cascade to do the work. Is it illusionary, or even possible in SASS ? Will it be generating a much big css file of unused/duplicated styles ? Is this possible with CSS variables only ?
14 Replies
Wolle
Wolle14mo ago
One CSS solution would be to set custom properties and override those you need to change in .dark-mode. you could set those CPs with the variables from your framework. With SASS you probably have to ship all dark mode related rules twice.
Joao
Joao14mo ago
Just to add to what Wolle said, you may want to consider a bit of JavaScript logic later to decide which theme to apply by default based on the user's prefers-color-scheme media query. https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
emeric_owczarz
emeric_owczarz14mo ago
i came across this solution and i think it's a robust one, as you can declare almost any property in a single line. I tested it out using system preferences, it seems OK. I will implement a toggle using JS too 👍
Fabrizio Duroni
Add dark mode support on your website with SASS and prefers-color-s...
Add dark mode support on your website with SASS and prefers-color-scheme media query
Joao
Joao14mo ago
🤔 Seems a bit complex to be honest...
Augustos
Augustos14mo ago
@media (prefers-color-scheme: dark) and it's all you need, for that 1% scenario, you may want js, but css is all you need these days. also, if u wanna a button that changes it, you gonna need JS as far as my knowledge goes
Wolle
Wolle14mo ago
You could go with :has(#darkmode-switch:checked) Except for Firefox... narf. https://caniuse.com/?search=has
Joao
Joao14mo ago
Neat trick! But it doesn't account for the user navigating the site, and styles would revert to whatever browser default uses and not what the user selected, on every page.
Wolle
Wolle14mo ago
Yeah you would have to persists that. And for the love of god do not use cookies for something like that, theres lokal storage for those occasions.
Joao
Joao14mo ago
But I love cookies 🍪 😍
Wolle
Wolle14mo ago
But they always leave your visitors machine and thus you would have to mention them in your cookie-banner, for example
Joao
Joao14mo ago
I know, I know I was just kidding
emeric_owczarz
emeric_owczarz14mo ago
Thank you all for your replies, but that's quite not what i asked initially. Basically i want to link this to a mixin, a function or whatever :
$light: (
$background-color: lightgrey,
$text-color: blue,
);
$dark: (
$background-color: black,
$text-color: red,
);
$light: (
$background-color: lightgrey,
$text-color: blue,
);
$dark: (
$background-color: black,
$text-color: red,
);
So when i call my variables in my stylesheets, i can get one value for the color, like this
.container{
background-color:$background-color;
color:$color;
}
.container{
background-color:$background-color;
color:$color;
}
No matter if a call @mixin background-coloror background-color:myColorName() Important thing is i only call ONE variable in the css
Joao
Joao14mo ago
The problem with using SASS variables is that they won't update when you change themes. A CSS variable would:
@use 'sass:map';

$light: (
background-color: lightgrey,
text-color: blue
);

$dark: (
background-color: black,
text-color: red
);

:root {
--background-color: #{map.get($light, background-color)};
--text-color: #{map.get($light, text-color)};
}

body.dark {
--background-color: #{map.get($dark, background-color)};
--text-color: #{map.get($dark, text-color)};
}

.container {
background-color: var(--background-color);
color: var(--text-color);
}
@use 'sass:map';

$light: (
background-color: lightgrey,
text-color: blue
);

$dark: (
background-color: black,
text-color: red
);

:root {
--background-color: #{map.get($light, background-color)};
--text-color: #{map.get($light, text-color)};
}

body.dark {
--background-color: #{map.get($dark, background-color)};
--text-color: #{map.get($dark, text-color)};
}

.container {
background-color: var(--background-color);
color: var(--text-color);
}
https://codepen.io/D10f/pen/GRPraMW
ἔρως
ἔρως14mo ago
or put the input at the top of the page, and target the container right after. this way, you dont need :has and works even on ie
Want results from more Discord servers?
Add your server