How to implement dark mode in tailwindcss with device preference.
Fazail Alam Mon Jul 04 2022

How to implement dark mode in tailwindcss with device preference.

Setup

I assume that you have already installed and configured tailwindcss for your project or framework. Now lets start by adding darkMode property to class in tailwind.config.js. We are using class based mode because it give user more control.

module.exports = {
    darkMode: "class",
	...
}

This will insure that whatever class you prefix with dark: utility it will apply that class in dark mode. So for example if i add dark:bg-gray-800 class then it will add bg-gray-800 class in dark mode. Lets see it in live example. After enabling darkMode in tailwind.config.js, add dark:bg-gray-800 class to your element and turn on dark mode of your device. You will see that it will trigger bg-gray-800 class in dark mode on that element.

Making mode switcher

Now that our dark mode is working, we can move to next step i.e, making mode switcher. Lets create a button that will switch between dark and light mode. Give it an id of mode-switcher. Then we can attach click EventListener and toggle mode depending on the current mode.

<html>
    ...
    <body class="bg-white dark:bg-gray-800">
        <button id="mode-switcher">Switch Mode</button>
    </body>
</html>
var switcher = document.getElementById("mode-switcher");
switcher.addEventListener("click", function () {
    // below code add or remove dark class in html element depending on current mode
    // if dark mode is enabled then disable it
    if (document.documentElement.classList.contains("dark")) {
        document.documentElement.classList.remove("dark");
    } else {
        // else enable it
        document.documentElement.classList.add("dark");
    }
});

Device preference

Our dark mode is working and user can toggle it, but what about when user refresh page or visit for the first time? To solve this problem we need three things to be done.

  1. Get user’s device preference.
  2. Persist the user preference and save it to local storage.
  3. Apply user preference on page load.

First of all make sure to add user preference code in head tag. Below code check if the theme is set to dark or theme property doesn’t exits in local storage and user preference is dark then add dark class to html element else just remove it. Our 1st and 3rd task are done.

<head>
    <script>
		// checks mode is set to dark || (theme property not exists && user preference is dark)) 
        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>

For 2nd task we need to add theme value to localStorage. In our button click listener set theme light or dark depending on current mode.


switcher.addEventListener("click", function () {
    // below code add or remove dark class in html element depending on current mode
    // if dark mode is enabled then disable it
    if (document.documentElement.classList.contains("dark")) {
        document.documentElement.classList.remove("dark");
		localStorage.theme = 'light'
    } else {
		// else enable it
        document.documentElement.classList.add("dark");
		localStorage.theme = 'dark'
    }
});

Bonus

If you want to make it again device preference. Then remove theme property from localStorage.

localStorage.removeItem('theme')

Want frameworks news and updates?

Sign up for our newsletter to stay up to date.