This is a Sass mixin to handle a 3-way dark mode. It relies on a data-theme
attribute on your <html>
element with a value of light
or dark
. If data-theme
is absent (i.e. it's neither light
nor dark
), the system's preferred mode is used.
body {
// matches data-theme="light" or data-theme="auto" with system instructing light mode
@include light {
background: white;
color: black;
}
// matches data-theme="dark" or data-theme="auto" with system instructing dark mode
@include dark {
background: black;
color: white;
}
}
See the example above on sassed
Caveat: This mixin targets modern browsers which support the :where()
pseudo selector. There is an older revision of this Gist with more caveats, but also with support for older browsers, which you can find here.
@wonsuc Because I changed from nesting to appending. 😁 See the latest revision.
Why do this?
Well, let's say I have a selector
.foo
where I want to use the mixin:This previously generated a selector like
:root.is-dark-mode .foo
, usingselector-nest
. (This selector is not what it actually generated, which was a little more complex, but it shows what nesting a selector does.)However, this approach created issues when the
.foo
selector itself already included the:root
, e.g. if you wanted to style something based on a modifier class on the root element, e.g.That would generate
:root.is-dark-mode :root.loading.foo
, which would obviously never match as:root
cannot be found inside:root
.Therefore, I switched the selector generation over to using the
:where
. pseudo class. That feature was not available in browsers when I originally published the gist, that's why I didn't use it in the first place.Now using
selector-append
and:where
, the first code sample would generate the selector.foo:where(:root.is-dark-mode *)
, and the second one would generate:root.loading .foo:where(:root.is-dark-mode *)
– which do both work.