DEV Community

Ayc0
Ayc0

Posted on • Updated on

Light/dark mode: avoid flickering on reload

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.body.className = theme;
  </script>

  <!-- rest of your html -->
</body>
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (3)

Collapse
jonrandy profile image
Jon Randy

Or use cookies and do it server side

Collapse
ayc0 profile image
Ayc0 Author

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.

Collapse
jonrandy profile image
Jon Randy

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!