Presentation of the issue
If you already added a dark mode to your website, and if you are allowing your users to pick the mode they prefer, you may already save their preferences so that they don't have to pick it again the next time they visit your website.
But now, you have to restore their preference on page load. And if this is done within your application, you cannot guarantee that this will be the 1st action done by the browser when loading the JS (specially if you lazy loaded the javascript code).
This can result in a flicker when users visit your website: they picked the dark mode, but when loading the website, for a fragment of seconds, a white background can be displayed.
Here is an example of this magnified:
The fix
The way the browsers work is that if there is a <script>
tag in your head or at the very beginning of your body, this script will block the rendering of the page until it hasn't completed.
In general you want to avoid this, as you add unnecessary burden on the rendering of the page, and it will delay everything else.
But for critical rendering like this one, this is okay.
All you have to do is add something like the following in your HTML:
<body>
<script>
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.dataset.theme = theme;
</script>
<!-- rest of your html -->
</body>
Drawback
Now the logic for handling the theme gets duplicated: in this script tag and in your main JS.
My advice would be to either:
- if your logic is really simple, to put everything in this script tag,
- if you logic is more complex - like handled by a framework like React (you can call it a library if you want), or if you need to fetch it from a database, or else - only put the critical logic in this blocking script tag.
Conclusion
In my opinion, when dealing with themes, avoiding flickering on load is one of the most important things to care about. Otherwise you'll irritate your users fairly quickly.
This is why I considered earlier this code snippet as critical.
If you want to read about how to implement a light/dark mode for your users, you can read the other articles from this series.
Top comments (6)
First of all. I did'nt know this website, nice discovery. Then, I tried many scripts and dark mode solution since yesterday. Yours is the one who worked well without this white flash on load. Thank you so much.
Is it possible to add attribute data-theme in the HTML instead data-applied-mode ?
Thanks
Forget my question. I used AI to optimize your code and I asked it how to change the attribute name ! 🙂
Or use cookies and do it server side
Even with cookies and server rendering, you might still have to do something similar if you aim to support a "system" mode that depends on users' os settings.
The only way to query it is with a media query in the front-end.
This is true for a 'system' mode. Unless browsers send maybe a 'prefers' header relating to dark mode in their intial request, which I don't think they do. That would actually be a great thing for browsers to add!
thank's that was usefull