How to Add a Dark Theme in Astro with Tailwind

6 April / 2 min read

You want to add a light/dark theme to your Astro project with Tailwind? It’s quite easy and all you need is a plain Javascript script. I will describe a Tailwind’s theming approach through a class, but you can adjust the code for other use cases too.

Apply theme without FOUC

Flash of Unstyled Content is a common problem in theming. Sometimes you can see how the default theme applies firsly, usually a light theme, switching to a dark theme, blinking, and making the UI to look ugly for a moment. In Astro, you can implement a script in <head> which checks, if the theme has been applied previously. This website applies this script in the main layout.

---
---
<html class="dark">
  <head>
    <script>
      if (
        localStorage.theme === 'dark' ||
        (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
      ) {
        document.documentElement.classList.add('dark');
      } else {
        document.documentElement.classList.remove('dark');
      }
    </script>
  </head>
  <body>
  </body>
</html>

Since Astro transpiles scripts that you put in script tags, we won’t be bothered by checking Can I Use.

Implement a theme switcher button

Next, we’re going to implement a button for switching themes. As you may guess you only need to save a newly selected theme to a local storage and switch the class of the <html> element.

---
---
<button type="button" id="theme-selector">
  <span class="sr-only">Enable <span class="dark:hidden">light</span><span class="hidden dark:inline">dark</span> mode</span>
  <svg class="hidden dark:inline">
    <-- dark icon -->
  <svg class="dark:hidden">
    <-- light icon -->
  </svg>
</button>

<script>
  document.getElementById('theme-selector')?.addEventListener('click', () => {
    if (localStorage.theme === 'dark') {
      localStorage.theme = 'light';
      document.documentElement.classList.remove('dark');
    } else {
      localStorage.theme = 'dark';
      document.documentElement.classList.add('dark');
    }
  });
</script>

If you want to modify UI to show a block in the light mode only use this class:

<span class="dark:hidden"></span>

And vice-versa, if you want to show an element only in the dark mode use this class:

<span class="hidden dark:inline"></span>

That’s it! Check the source code of my website to see implementation. If you want to see it in action, just switch a theme.