Dark mode toggle without the flash of default theme. Important bits:

  • CSS variables for color theming
  • Put data-theme attribute on <html>, not <body>, so we can run the JS before the DOM finishes rendering
  • Run local storage check in the <head>
  • JS for toggle button click handler can come after render

HTML

<html lang="en" data-theme="light">
  <head>
    <script>
      const localStorageTheme = localStorage.getItem('theme');
      if (localStorageTheme) {
        document.documentElement.setAttribute('data-theme', localStorageTheme);
      }
    </script>
  </head>
  <body>
    <div class="theme-toggle">
      <button class="js-theme-toggle" aria-label="Activate dark mode">Toggle</button>
    </div>
  </body>
</html>

CSS Variables

:root {
  --bg: #ffffff;
  --text: #000000;
}

[data-theme='dark'] {
  --bg: #000000;
  --text: #ffffff;
}

Resources