9 ms·
The Quest for the Perfect Dark Mode (Gatsby/React)
- WiseWeasel 7y agoPerfect dark mode doesn’t have a toggle; it uses the prefers-color-scheme CSS media query to key off your OS theme preference. At that point, there's no problem with Gatsby or Next.
- elliebike 7y agoIt's definitely simpler to not have a toggle, but I like having the choice. Some websites I frequent often have a dark mode I don't like much, so I switch to light - and vice-versa. Just because a user generally prefers dark mode, doesn't mean they do everywhere!
- noisem4ker 7y agoI think a per-site override switch should also belong to the browser.
- elliebike 7y agoOh I definitely agree there! I don't know if any implement that at the moment though :(
- cercatrova 6y agoYou can use extensions like Dark Reader
- chrismorgan 7y agoOn the contrary, this feature has existed for decades. It’s called user-selectable alternative stylesheets: https://developer.mozilla.org/en-US/docs/Web/CSS/Alternative_style_sheets https://developer.mozilla.org/en-US/docs/Web/CSS/Alternative.... But because no one used it, the feature has not been better positioned in more recent browser UI redesigns, so it’s close to inaccessible in most browsers now. No idea if Chrome and related browsers expose it at all, or even if they’ve ripped the functionality out altogether somewhere along the way.
- saagarjha 7y agoThere’s nothing wrong with having a toggle; it just needs to default to a “system” mode. Unfortunately this site doesn’t seem to implement this correctly, as changing the OS theme doesn’t update the site’s theme.
- sdegutis 7y agoThe best UI for this IMO is a toggle with three choices: light, dark, and same-as-OS.
- barrowclift 7y agoNot necessarily true, I'd argue the "perfect" dark mode uses the system's theme by default like you said, but still allows visitors to manually set light or dark should they wish to view the site a particular way (perhaps they prefer the light mode, etc.)
- asiachick 7y agoAgreed. S.O. recently added dark mode and for some reason my eyes couldn't focus on it. No idea why. I run my editors and my terminal in dark themes. Maybe they didn't have enough contrast. Maybe the fonts are too small or too thin. I have my browser set to "prefer dark mode" but I'm really happy S.O. let me opt out.
- WiseWeasel 7y agoI think the only reason someone who likes dark theme would opt out of your dark mode is because it's not as nice/readable as your light theme, or vice-versa. You should fix that instead. Once your dark mode support is perfect, or at least as good as your light theme, then the toggle serves no purpose.
- sneak 7y agoReading this site reminded me of this: https://motherfuckingwebsite.com/ https://motherfuckingwebsite.com/ It's also worth mentioning that TFA's webpage is broken. Despite all his dozens of lines of javascript for his "dark background" feature, it totally fails to render (resulting in a blindingly white blank page, ha!) if you have cookies off (it's a static Gatsby site, which does not need and cannot use cookies). For all his hard work, his site is a blank page. (Here's why, if you care: https://sneak.berlin/20200211/your-website/ https://sneak.berlin/20200211/your-website/)
- edhelas 7y agoDamn React is complicated. I added Dark mode in my app in a few lines of CSS (https://github.com/movim/movim/blob/master/public/theme/css/color.css#L13 https://github.com/movim/movim/blob/master/public/theme/css/...) and used the variables across the whole code. I just have to toggle a class on the body and boom, it works. Guys, you don't need all that JS, seriously. It's slow, it's useless most of the time. And in the end you have to spend hours for something so simple. Theming the colors of your website is the role of one tech: CSS. That's it, you don't needs layers and layers of Javascript to change that. Let's go back to server side rendering, a bit of HTML + CSS and JS and we're done.
- sdegutis 7y agoCSS variables are the best way to do dark mode, just use the variable everywhere, set it on html or :root, and change it either in .darkmode or a @media for dark mode. They're pretty much supported everywhere dark mode is. Surprisingly simple dark mode support for greenfield sites.
- saagarjha 7y agoIf you don't have much styling, then even :root { color-scheme: light dark; } can get you quite far.
- ldd 7y agoI agree with you partially. Dark Mode is pretty easy to do in CSS. I purposely picked jekyll with no javascript for my static site, and despite contributing a plugin for Gatsby, I do not use it these days. Yet, there is at least some modern applications that can be made thanks to javascript, and React. We do not need to go back, but it is perfectly acceptable to say that not everything is a nail and you do not need a hammer for every single task.
- eyelidlessness 7y agoIf you read the article, the complexity did not come from React, it came from meeting the author's specific requirements, which are not achievable with CSS alone.
- animalgonzales 7y agothis is way too complicated and convoluted. just use global css selectors.
- saagarjha 7y agoCSS selectors don't actually solve the problem the author had.
- mirthflat83 7y agoWow. What a beautiful website!
- darepublic 7y agoDark mode shouldn't be harder with SSR apps, you would just send back the dark mode CSS in the initial GET response. Complexity around this might be related to trying to work with out of the box framework settings, but comparing this problem to some advanced image recognition, while admittedly a joke.. is just over-representing the problem imo. I'm sorry gatsby didn't give you an easy way to do this, but if you understand the principles of web applications this should not be an epic quest.
- saagarjha 7y agoThe problem is that the question of whether dark mode CSS should be applied is only known once JavaScript can be executed on the page.
- deleted 7y ago[deleted]
- darepublic 7y agoThat's the thing with SSR... (i.e. with Next) or with pre-rendering apps before hand. In the initial GET request to the page, you also send a cookie with user preference. Depending on their dark mode preference you can style the page to be in dark mode as part of the server or pre-rendered markup -- no JS required :o. Now.. how difficult that is to do with Gatsby I don't know. But the fact that someone shot themselves in the foot with Gatsby, then learned to hobble along on one foot isn't a cause for celebration imo.
- saagarjha 7y agoI don't see how you could do that with a static site.
- robertoandred 7y agoThis has nothing to do with Gatsby or SSR. It has to do with storing the user's preference locally and applying it before the page renders. Don't think you understand the principles here.
- artursapek 7y agoWe have had color schemes on Cryptowatch (https://cryptowat.ch https://cryptowat.ch) for years, and since a year ago we even let users create custom color schemes within the web app [1] We use CSS variables for this. The stylesheet doesn't have any hard-coded colors, it only references a set of several variables and many blends of these variables. This way, you can let a user adjust a variable using a color picker and the entire website adjusts dynamically as they do it. It also lets you render any color scheme properly in your SSR (unlike the approach in this article). [1] https://guides.cryptowat.ch/real-time-charting-interface/custom-theming https://guides.cryptowat.ch/real-time-charting-interface/cus...
- bobbydreamer 7y agoNice design
- memco 7y agoThe theme toggle button plays a sound when you click it. So not only does this require state for the theme, but also the sound. Also curious is that clicking the button to mute sound plays a sound. I believe every OS defaults to silent actions for every button. Games, on the other hand, often have sounds for hover/focus and click. I'm not sure what's the better option, but if we're going to default to the OS for theme choice shouldn't we also default to the OS for UI sound choice? I don't know if there's any way to check that via CSS or JS. But I hope that if sites are going to start implementing this more often that browsers at least expose an API with a user preference if not the OS.
- danappelxx 7y agosee: https://www.joshwcomeau.com/react/announcing-use-sound-react-hook/ https://www.joshwcomeau.com/react/announcing-use-sound-react...
- memco 7y agoThanks! I did see this before. Didn't realize it was the same dev. They don't address that Desktop OSes don't do sound for most things and also, I'm not really sure I see sound used a lot in mobile apps, but maybe that's just the apps I use? I think I would personally want more research and discussion on this before I ventured down this path, but it is an interesting idea.
- joshwcomeau 7y agoHey thread, author here. I don't have the energy to debunk some of these replies, but let me quickly say: 1. The reason that this is a hard problem has nothing to do with React, or Gatsby. It has to do with the strategy of precompiling HTML and not having a runtime server, an approach with many many benefits (described here: https://joshwcomeau.com/gatsby/a-static-future/ https://joshwcomeau.com/gatsby/a-static-future/). If you're wondering why anyone would put up with all this tomfoolery for a dark mode, please read that so you can understand the benefits to this approach. 2. "React is overkill for static sites" is a debate I am not trying to have, but I can say that for my blog (the site that this post is about), React has allowed me to do lots of cool things that would have been much harder otherwise. And using Gatsby means that I have first-meaningful-paint performance that beats a PHP template with no JS, since my site doesn't have to do any database lookups or real-time HTML generation. I am not saying that this is the right approach for every website, but it was 100% the right choice for this one. 4. Many of these replies are making suggestions that are discussed in the article itself. CSS variables are not an alternative to this solution, they _are_ the solution (my solution wouldn't work without them!). Please read the post before forming an opinion about it. I hope that helps clarify some things! Hope you're all doing alright and staying home.
- edhelas 7y ago> When you run gatsby build (or whatever your command is to build your site for production), the build system will make all the API calls needed to fetch the data necessary to generate every possible HTML page. It'll use React server-rendering APIs to turn a tree of React components into a big HTML document. That's what we're calling "cache" in good ol' backend-code applications. It's used for at least 15 years in e-commerce, blogs and many other "outdated because now we have react-angular-vue.npm.io" CMS. With "cache" you can store precompiled HTML pages server side, even only parts of it (if you have 50.000 articles like you're explaining in your article). You can even do that in front of your PHP/Ruby/Python app using HTTP caching proxies such as Squid. Here it's even beyond "blistering fast", it's "ultra blistering fast". Do a static website, add a little bit of vanilla JS, want to refresh parts of the pages ? It's called Ajax. The moment I saw ReactJS redering moving server side to "pre-render" stuff I saw that we we just looping again and again. And again once your HTML is delivered, no one is stopping you to do a few line of JS to add a simple class on top of your page to toggle the Night Mode. Want to do it before the JS is executed (and don't have this ugly delay) ? Use a cookie and set it on render time. If the user is forbidding cookies, well then it's because he don't want to be tracked and don't want all those fancy features. You can fallback to prefers-color-scheme. Things were done simple, no need to reinvent everything each time :)
- swlkr 7y agoWow this website is really creative. Not sure about the dark mode implementation, since it rendered a white screen for me with no content on iOS, but on desktop it worked. Also the general feel of the website is really nice, a lot of nice little touches from the sounds to the "nonstop confetti party" when you sign up for the newsletter.
- noisem4ker 7y agoI'd rather stick with static web pages, thanks.
- dgellow 7y agoHow does the “shining stars effect” for the sentence “the perfect dark mode” works? That’s really neat. (I’m on mobile so cannot reverse)
- mirthflat83 7y agoLooks like the author is generating span elements with random absolute positioning
- dgellow 7y agoThanks!
- chrismorgan 7y agoI like my dark theme implementation which supports the same operations, but a tad lighter, more flexible and not-Reacty: a toggle, falling back to the prefers-color-scheme value if it hasn’t been toggled or if JavaScript is disabled (and I don’t think Josh’s does that), and avoiding a flash of unstyled content. I wrote about it at https://chrismorgan.info/blog/dark-theme-implementation/ https://chrismorgan.info/blog/dark-theme-implementation/. The problem as a whole is definitely a tad fiddly, but I still think that trying to do things in React is a substantial part of what’s making it complicated here. I instead used regular stylesheets and the media attribute to control the toggling, and I think that’s the best solution, because it’s what makes it work perfectly with and without JavaScript. (I used external stylesheets, but you could inline them if you wanted; the media attribute works on <style> as well as <link>.) Josh, I’d be interested in your opinion on it. It took me several iterations to end up where I did (definitely didn’t occur to me to alter the media attribute at first!), and I think it’d apply cleanly to such sites as yours, and be better for the toggling.
- pcr910303 7y agoSeriously! Should every Gatsby blog post on HN have this useless 'React is overkill for static sites' talk? Gatsby is a static site generator! Running Gatsby does NOT make the whole website run on React. It makes a bunch of HTML pages that are statically served - and some JS progressively enhances it. The complexity in this blog post has nothing to do with React, it's due to the author's complex requirements that are very beneficial to the user. Yes, the web is full of bloated pages. No, that's not the topic here. It's so frustrating for people to complain about React on this great post - comment about the post, people!
- kimjongman 7y agothis is over over engineering. nobody got time for this complex solution. You can achieve this with simple code https://www.w3schools.com/howto/howto_js_toggle_dark_mode.asp https://www.w3schools.com/howto/howto_js_toggle_dark_mode.as...
- welcometomiami 7y agoDid anyone else happen to read this and think of https://en.wikipedia.org/wiki/Perfect_Dark https://en.wikipedia.org/wiki/Perfect_Dark?
- sneilan1 7y agoYes, I played that game thoroughly and I could not separate the project from the game.