4 ms·
> First, your dark mode is implemented wrong in the lazy corner-cutting way of doing JS post-load ... I agree with your whole comment, but the media query appr
by nickelpro 3y ago
> First, your dark mode is implemented wrong in the lazy corner-cutting way of doing JS post-load ...
I agree with your whole comment, but the media query approach is also tricky.
You typically still want to offer a toggle while respecting prefers-color-scheme, and you may want to give priority to whatever choice the user has made with that toggle if they've used it on your site before. This still requires JS and localstorage.
So what to do? My preferred choice is having an inline style element of:
body {visibility: hidden; opacity: 0;}
This will maintain the previous page until DOMContentLoaded, at which point you can query prefers-color-element and localstorage, set the body class correctly, and let the page paint.
- onion2k 3y agoThis still requires JS and localstorage. I've been considering this recently for my site and I settled on having prefers-color-scheme on the root domain with dark. and light. subdomains. If the user chooses a color they just get bumped to a subdomain that sets a cookie with their preference. If they come to the site from an external link and they have a preference cookie they get redirected to the subdomain again. Absolutely no clientside JS is needed anywhere, no FOUC issues, and it's trivially simple to code because it's literally just a redirect in the server config based on a cookie value. I really should spend the time to actually build it, but Diablo 4 came along and I got sidetracked.
- gwern 3y agoI don't know whether to be fascinated or horrified by this proposal, but I admire the novelty - I can definitely say that in all the dark-mode proposals/implementations I've looked at over the years we've been fiddling with ours, I've never seen that suggested.
- porridgeraisin 3y agoWouldn't the following be a better version of the above. Use css variables everywhere, and have a defs-dark.css and a defs-light.css that define the colors. Then, on nginx, serve the correct stylesheet based on cookie value. Better than subdomains for dark and light, no?
- onion2k 3y agoMy idea has the benefit that users can block the cookie if they want to and still use whatever mode they want, although they'd lose the redirection 'functionality' if they do that.
- account42 3y agoThis sounds like it would have the same problem as redirects to mobile subdomains - users will share links to light. and dark. subdomains, unknowingly forcing their preference onto the recipient. The proper solution is to only implement the media queries and yell at browser vendors to make this easier to toggle either for all websites or for specific websites. Implementing a light/dark mode switch in every website is absurd.
- onion2k 3y agounknowingly forcing their preference onto the recipient I'd suggest knowingly rather than unknowingly. It's a link to a website after all. It should link to the same thing that the person who shared it was viewing. That's the point of a URL - when you share one the recipient should see what you were seeing. FWIW I would also like browser vendors to do a better job at enabling users to manage their preferences on a per site basis though.
- theallan 3y agoDoesn't that make the page completely unreadable for those few who have Javascript disabled though?
- jeroenhd 3y agoYou can also swap out the CSS file for one that explicitly sets/unsets light/dark mode. This allows for a website that works in any browser even if your Javascript breaks or doesn't load. Or you could use cookies. No need to mess with localStorage. Just set a cookie "prefersDarkMode" to true or false and have the backend send the right file. No need for an interactive backend, nginx can handle serving files based on cookie contents. No need for cookie popups/walls either.
- nickelpro 3y ago> This allows for a website that works in any browser even if your Javascript breaks or doesn't load. I just use <noscript> for this. If you don't have Javascript you're just going to get whatever your prefers-color-scheme is set to. Users without JS don't expect things like a dark-mode toggle to work anyway.
- djbusby 3y agoPrometheus Modern UI has a pretty good system/dark/light toggle - and picks the system one first.
- gwern 3y agoThe nuts-and-bolts implementation of inlined-CSS to avoid flash-of-white is separate from the UX toggle question, which is why I listed them as separate criticisms. The former is just wrong of OP: no user wants the FOUC flash-of-white, end of story; similarly for some of the other solutions proposed here (block the entire page, really? talk about burning down the village to save it). The latter has more leeway for design: we settled on a tri-toggle to use the media-query but allow users to override and hardwire light/dark mode, and that seems to work most naturally. But there may be other contexts where something else would be better. Indeed, for toggles, you could even try not having a toggle at all and relying on the system setting through the media-query. (However, as appealing as this is - why have separate controls when the user already has a global control and can enable/disable it? - we found this confused & angered users: https://gwern.net/design-graveyard#automatic-dark-mode https://gwern.net/design-graveyard#automatic-dark-mode So, gotta have a toggle. At least for now; maybe as dark-mode becomes universal, at some point users will become educated enough that you can afford to use only the system setting?)
- nickelpro 3y ago> block the entire page, really? talk about burning down the village to save it I'm curious for what the other approach is. Users find it annoying to refresh the page and have their dark-mode setting change, or have their dark-mode setting change while navigating the site. So I have to block paint until I can query local storage in order to avoid flashing, what's the alternative? Below someone suggested using cookies and only serving CSS that does the desired styling, which I guess is doable but requires a non-trivial infrastructural change.
- hw 3y agoAs long as you have a good reason for your decision. Some things you just have to make tradeoffs and can’t please everyone. Enter key to submit or enter key for newline in a chat context? You’ll go crazy trying to solve for all - sometimes it is just not possible
- gwern 3y agoYou don't need to hide the entire page until fully rendered. You inline in the head just the bits of CSS/JS you need and set styles from there, so if you are in dark mode, it's set to dark before anything has rendered, without needing to block a huge amount of time. You can see how it works on my site https://gwern.net/ https://gwern.net/ - set dark mode in the toggle (assuming it is not your system setting already), and refresh or force-refresh; note that there is no flash of white nor is the page hidden until rendering is fully finished.