I've done a LOT of dark mode work, to the point where I'd consider myself an expert here[1].
I'm not a fan of this. This solves one tiny aspect of the larger problem in a non-scalable way that will inevitably lead to bloat and inflexibility. It's a really a naive approach that hasn't taken into account design at scale, nor the future of where design is heading.
Typically when doing theming, you have two axes - a visual mode axis (i.e. light/dark/high contrast/colorblind modes/etc) and a theme axis (i.e. docs/sheets/slides, each with a different brand color). While this does solve an aspect of the visual mode axis, as soon as you add either a new theme or a visual accessibility mode, you'll be forced to refactor. I see that as codesmell.
I also don't think this helps drive a better future of theming support. If we think about the future of theming, what we see today is a convergence of design patterns. Nearly everyone is doing theming at scale in at least roughly the same way (a semantic token layer that points to different primitive colors depending on the theme), and the differences between implementations continues to diminish over time. The convergence of patterns is a good thing - it means more code can be shared.
If you wanted to actually solve theming, what you should work for is not a constrained helper function like light-dark(), but instead a shared token schema. Today nearly every company has their own token schema and different ways of naming things in the semantic token layer. If we had a shard language here, not only would it be trivial to add light/dark theming (just redefine a few variables that are already provided for you), code could be shared between sites and inherit the theming/branding.
[1] Most recently leading Figma's dark mode stream, and currently leading their variables feature work to enable others to easily do light/dark/etc. I've consulted with 50+ enterprise tier companies on their theming. Also contributed to the W3C design token proposal for theme/mode support: https://github.com/design-tokens/community-group/issues/210. Previously worked on Jira's dark mode + a few other projects.
> This solves one tiny aspect of the larger problem in a non-scalable way that will inevitably lead to bloat and inflexibility. It's a really a naive approach that hasn't taken into account design at scale, nor the future of where design is heading.
Note that `light-dark()` isn’t the end goal here. As discussed within the CSS WG, the end goal is to have a generic function `schemed-value()` to give you what you want.
FWIW, I added a comment here around a simple but more flexible proposal, that allows for easy light/dark theming via this approach, but would at least scale (and would allow for color-scheme's custom identifier support to be useful): https://github.com/w3c/csswg-drafts/issues/7561#issuecomment...
Very true! Nonetheless this approach would also break compatibility with `color-scheme`'s custom identifiers, which is just bad in general for CSS even for these small projects. The alternative proposal I put together here would allow this to scale and still provide a helper function for small projects to use: https://github.com/w3c/csswg-drafts/issues/7561#issuecomment...
Even if you never need to scale, Having light/dark & high contrast is just having basic features and complying to the law. If your site has 50 users it should have these, and this new light/dark switch is still inappropriate for even this basic use case.
What law? The U.S.'s Section 508 and other laws and regulations based on WCAG, don't require that sites honor `prefers-color-scheme` or to work correctly when `forced-colors` is active.
Nevertheless, it's a good idea to do so (though if a site honors `prefers-color-scheme` it should also have a setting so the user can choose to have that site not match their system's color scheme setting).
> If you wanted to actually solve theming, what you should work for is not a constrained helper function like light-dark(), but instead a shared token schema. Today nearly every company has their own token schema and different ways of naming things in the semantic token layer. If we had a shard language here, not only would it be trivial to add light/dark theming (just redefine a few variables that are already provided for you), code could be shared between sites and inherit the theming/branding.
I think it's a great idea, but hampered by the lack of adoption incentives for the very people that need to adopt it for it to become successful (design system/component library authors). It introduces constraints, but the promised interoperability is not really beneficial to the people who need to work within those constraints.
That link goes deep. I agree about the tokenizing.
I hate that we've picked off all the easy work on web design and now we're into problems we never even imagined 10 years ago, e.g. multiple visual modes, differing color spaces etc. This stuff is getting really, really hard to do well and do it right -- it is very easy to make things worse for a lot of users, rather than better.
I agree this looks like it will be of questionable use at scale. That said I don’t see a shared token schema ever achieving much. Those sorts of efforts usually flounder because there’s little incentive for adoption until a critical mass is achieved
Oof. Unless I’m missing something, this is a convenience that doesn’t enable anything new and uses syntax/terms that don’t naturally generalize for future applications. It just embeds one recent trend in very specific, very rigid terms.
Yes, `light-dark()` is very specific in what it can do … but it’s not the end goal. The end goal is to have a generic function – something like `schemed-value()` – that can respond to a plentitude of `color-scheme` values and return more than just `<color>` values.
Reality is, though, that browsers don’t have support for custom `color-scheme` values (it’s explicitly forbidden in the spec, for now) [^1] and that CSS parsers need to know ahead of time what they are about to parse [^2].
By narrowing things down in feature scope, you can use this convenience method now, instead of needing to wait a few months/years until the rest is figured out.
Once `schemed-value()` becomes a thing, `light-dark()` can become syntactic sugar for it:
```
light-dark(<color>, <color>); = schemed-value(light <color>, dark <color>);
```
You can have both. But good tool design looks at the horizon, not just at your feet.
You could deliver the same convenience in a way that’s set up to be repurposable (fullcolor /rgcolorblind) or extensible (light / grey / dark / …n) with as little difference as choosing a more mindful name.
I agree with the previous comment that the current approach lacks flexibility in achieving high contrast. It might be beneficial to consider a more general and adaptable method that can accommodate different styles or even introduce primitives for different styles in the future
Remember when UIs were customisable to the point that you could choose any colour for all the elements?
Now it's "you can have any colour you want, as long as it's light or dark", and all of a sudden "dark mode" is heralded as something revolutionary and new.
CSS3 even deprecated the "system colors" feature that was meant to allow the same degree of UI customisation we had before for websites too.
It's nothing but a really sad regression in empowerment, the continuing trend of treating users like cattle.
Set your browser to always use reader mode, on desktop and mobile. It solves all the problems of modern web browsing. Web sites do not deserve to use any of their own CSS or layout by default.
How is this better than using CSS variables for light/dark mode? With CSS variables you have better isolation for consistency with your entire color scheme, and you can extend it to supporting multiple themes (e.g. light, dark, blue).
I have everything set to dark mode, but I wouldn't want the images altered. Unless these are just navigational images on your site and you don't have any photos?
Images with a full dynamic range look too bright in the dark mode. I set them to 0.9 as well on my resources, otherwise the eyes are bleeding deep in the night.
There are multiple reasons for a user to want "dark mode":
* I just want everything to be dark on my screen because I like it.
* I am trying to use this device in a dark place.
* I want a dark, low-contrast background that doesn't compete with image colors.
The solutions to these three problems are all some kind of "dark mode" but each one needs a different solution. Sometimes one "dark mode" might work in conjunction with the user manually changing their brightness settings depending on the lighting in the environment, but not many people seem to design for that.
How does this deal with the ternary of light/dark/high-contrast that a lot of sites are now using?
I wish they would just enable features that are already in the browser that they've not put live, like grid-template-rows: masonry. All three major engines have the damned thing in there but it's not in release branch.
There's also the light/dark/system (auto) ternary approach, which this seems to encourage the designer to ignore in favor of a binary toggle. It seems to beg the developer to treat the mode as a negation of whatever it currently is, which leads to bad results and time-dependency of setting.
if browsers have support for a feature such as masonry, but it is not enabled in css spec does that mean it cannot be used? I recall seeing masonry in a tailwind talk, very neat!
Well, most people implement it using JavaScript if you want everything to be in the correct order. I use a pure CSS variant as I'm trying to go near-zero JS on my projects these days, but it means things are out-of-order. Depends on your use case.
I also check for CSS support in the browser using the "supports" feature and utilize the native support if it is enabled (e.g. Firefox behind a flag, and Safari behind a switch).
I’m consistently amazed at how much energy has been put into the light/dark UI pattern for web and mobile apps. Way way more than was ever put into dealing with colorblindness or any other form of color adjustment imo.
It’s nice to have the choice but I also wonder what else might have been done with all that UX/UI design and SWE time.
Right? This whole affair seems very disproportionate. My bank recently announced a redesign of their online web app, and one of the major points they said they focused on was ... dark mode? Really?
That seems to be linked to the spreading belief that this is a health issue instead of an aesthetic preference. Those who now believe this option somehow hurts their healthy eyes might already outnumber the actually colorblind.
I guess it's better than nothing, but this does not feel like a very CSS way of solving this problem. I think I'd rather write a separate block of styles for dark mode, the way you do for other media queries. Happy to hear why that's wrong though.
It's "only" colors ? So far from 100% of your css (especially if you use something like tailwind where css class for shape and color are clearly separated)
Also I m not a css expert but can't you also simplify it by using css variables so that you can further reduce the scope of change by having only the css variables that change value ? Your --primary-color-500 etc.
I may turn down the brightness on images, generally, in dark mode. (Using a filter).
And have some classes that mean “don’t alter the brightness of this image, in dark mode”
And there may be other images which I will invert the color of. For example any image that is basically black text on a white background — it’s better to invert it completely rather than just lower the brightness.
I can't believe stuff like this is still difficult.
In the late 00s I wrote a frontend for a very popular open-source web project that many here would have encountered. Unlike many web projects these days, it is considered de rigueur for each instance to implement its own stylesheet. Most instances will also allow each user to select their own stylesheet.
This is trivial because the frontend was written HTML first. The HTML contains absolutely no hint at how the style should be. The navigation is just the navigation, the content is the content etc. The nav could be at the top, bottom, side, whatever you can come up. And people did all of them.
And, of course, some of those stylesheets were dark mode.
Print stylesheets were also common, which would hide all the web nav stuff when printing the document.
How did all the layers of crap added since then seem to forget this and make this quite simple concept difficult? You can't tell me it's difficult to build two stylesheets, one dark, one light, and have them both as options. And what about other accessibility options? Low contrast? High contrast? It's not just about dark and light...
Dark mode is a weird phenomenon, I think. It kind of came out of nowhere and suddenly everything in existence started adding a dark mode and prominently listing it as a top features. That is not a complaint or anything like that, just an observation that dark mode seems to have spread in an unusual way compared to other technologies. But might of course also be just my perception.
I actually remember from my software ergonomics course at university that black on white is better than white on black. I guess it stuck because it surprised my, I always considered the MS-DOS console easier to read. I do not remember any details, but I guess it must have been about working in a well lit office or something like that. Dark mode is probably only advantageous because we nowadays use screens in a lot of situations with all but ideal lighting.
A genuinely useful behaviour of a function like this would be to return the colour with most contrast over the background of its container element, rather than a predefined colour scheme.
Even though that’s a kind of strange and unworkable idea — it’s interesting to think about.
Unworkable in the sense that, for example, some elements are not physically positioned inside their container elements, and sometimes even in light dark mode you might use elements to create subtle layering etc, where you’d want the least contrast.
It wouldn’t be too difficult to write a gimmick webpage though, that implements the idea, to see what kind of fun would ensue.
I’ve got some sample code here that uses the little known but very powerful “tree Walker” to change elements 1 by 1.
If people envisioned that web would become an application platform, maybe we wouldn't have CSS and HTML but instead some sort of lower level bytecode (ala WASM) and the actual higher level document and styling tools would be separate and compile to this bytecode. It makes me shutter every time I imagine how much you have to cover from CSS and HTML alone for a function web browser.
This method is pretty much ternary operator and it requires a browser support to be used, insanity.
(Hi, author of the post here) `grey` is no accepted value for `color-scheme`, so that would make no sense.
Note that `light-dark()` is not the end station here, it’s a step towards a future function that (1) would be able to respond to any value for `color-scheme` and (2) can return any type of value.
What would be neater is a `media()` CSS function, similar to `var()`, `env()` or `calc()` that allowed you to conditionally switch values based on arbitrary media queries, for example:
Often I want "a bit darker" just to take the edge off blinding white light. This HN page for example, I use the Stylus browser extension to reduce the background white of page and this text box to a medium grey. Same for Wikipedia. I tried making a Stylus entry that worked on any website, but couldn't do it.
I'm not a fan of this. This solves one tiny aspect of the larger problem in a non-scalable way that will inevitably lead to bloat and inflexibility. It's a really a naive approach that hasn't taken into account design at scale, nor the future of where design is heading.
Typically when doing theming, you have two axes - a visual mode axis (i.e. light/dark/high contrast/colorblind modes/etc) and a theme axis (i.e. docs/sheets/slides, each with a different brand color). While this does solve an aspect of the visual mode axis, as soon as you add either a new theme or a visual accessibility mode, you'll be forced to refactor. I see that as codesmell.
I also don't think this helps drive a better future of theming support. If we think about the future of theming, what we see today is a convergence of design patterns. Nearly everyone is doing theming at scale in at least roughly the same way (a semantic token layer that points to different primitive colors depending on the theme), and the differences between implementations continues to diminish over time. The convergence of patterns is a good thing - it means more code can be shared.
If you wanted to actually solve theming, what you should work for is not a constrained helper function like light-dark(), but instead a shared token schema. Today nearly every company has their own token schema and different ways of naming things in the semantic token layer. If we had a shard language here, not only would it be trivial to add light/dark theming (just redefine a few variables that are already provided for you), code could be shared between sites and inherit the theming/branding.
[1] Most recently leading Figma's dark mode stream, and currently leading their variables feature work to enable others to easily do light/dark/etc. I've consulted with 50+ enterprise tier companies on their theming. Also contributed to the W3C design token proposal for theme/mode support: https://github.com/design-tokens/community-group/issues/210. Previously worked on Jira's dark mode + a few other projects.