Why does prefers-color-scheme need duplication of styles?

I was watching KP's video on using dark / light themes: https://www.youtube.com/watch?v=zFFuV_vXNhY&t=36s And it works nicely, but it bothers me that the styles are duplicated in :root definitions as well as the theme switcher ":has" definition. Why is the duplication needed if I have selected the theme using color-scheme: [dark|light] declaration? It seems to override behaviour for system styles, but not anything I've defined. G
Kevin Powell
YouTube
A simple mistake that can screw up your light/dark theme (and how t...
Looking to step up your CSS game? I have free & premium courses 👉 https://kevinpowell.co/courses?utm_campaign=general&utm_source=youtube&utm_medium=lightdarkfix 🔗 Links ✅ Finished example: https://codepen.io/kevinpowell/pen/KKEevOp ✅ More in-depth video on creating a light/dark toggle: https://youtu.be/QtuLN0lNb-Y ⌚ Timestamps 00:00 - Introduc...
7 Replies
Joao
Joao4mo ago
Because the media query "prefers-color-scheme: dark" doesn't actually mean anything. It has semantic meaning to us humans but in reality is just a on/off switch like anything else, and if it's enabled then some styles will take effect as defined in there. If you think about it, how else could the browser possibly know that it needs to switch colors? Even if it did, which one should it pick as dark, is #222 ok? too dark? not dark enough? "prefers-color-scheme: dark" only tells the browser that if a dark scheme is available, use it, but you still need to define what dark means. Note that you can define whatever CSS rules in there, even if they have nothing to do with colors, like padding, position or display to show or hide elements.
gaiuscoffey
gaiuscoffey4mo ago
Watch the video! (Or read the code.) It’s not using prefers to change theme, it’s using a :has selector to select a style based on select value.
Joao
Joao4mo ago
You shared a link with a timestamp, was that a mistake? I assumed that's the specific part of the video you were referring to. The :has selector is not used in the video at all, so I didn't address it.
gaiuscoffey
gaiuscoffey4mo ago
Yes, timestamp is a mistake. But has is used for the css only theme changer. :has([value=“valForDark”) { color-scheme: dark; }
Joao
Joao4mo ago
I'm not sure why 😕 I think it may be because you need to have an initial definition but even changing the checked value on the html it behaves oddly
gaiuscoffey
gaiuscoffey4mo ago
It seems like a subset of styling is applied. I’ve been playing with it to persist theme preference using local storage, and it seems I can almost do away with the prefers-color-scheme media query if I use a tiny bit of JS, which is sort of ok, but I feel it should be possible to do all except the local storage without reverting to JS and not sure it is. Or at least… not without duplication of styles in the media query and :has selectors.
Joao
Joao4mo ago
I've always used a bit of JS precisely because of that, otherwise on a multi-page site the theme may change if it's not saved properly so it's almost necessary. But yeah, not sure how the CSS only works in this case.