Posts Learn Snippets Categories Tags About
/
How to Implement Light and Dark Mode with AlpineJs and TailwindCSS cover

How to Implement Light and Dark Mode with AlpineJs and TailwindCSS

Learn how to create a Light and Dark theme with AlpineJS and TailwindCSS to make your website more accessible for everyone.

3 weeks ago

10 mins read

510 views

In this post, you'll learn how to implement a Light and Dark theme with AlpineJS and TailwindCSS. The modes can be toggled on and off and the state will be persisted locally on the browser local storage.

Install AlpineJS and Tailwind CSS
Let's start by installing the library and here you can use "npm" or "yarn" package manager.
//alpine js
npm install alpinejs

// tailwind css
npm install -D [email protected] [email protected] [email protected]

If you are working on a Laravel project, you can refer to my other tutorial for the full guide to Setting Up Apline Js for the Laravel 8 project. Do note that you can't use TailwindCSS CDN since some additional configuration is needed for the dark mode customization.

Enable Tailwind CSS Dark Mode Variant
To enable the dark mode variant, update the tailwind config file and add "darkMode" settings and set it to have "class" as the value.
// tailwind.config.js

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

Create a Card Component
For this example let's create a card component and apply the light and dark modes for it but the concepts are the same to theme an entire page, so let's get started.
<div class="h-screen flex justify-center items-center bg-gray-50">
    <div class="w-full sm:w-8/12 md:w-6/12 p-4">
        <div class="p-4 rounded-lg shadow bg-white">
            <h1 class="font-semibold text-lg">
                Card Heading
            </h1>
            <p class="mt-2">
                This is the content of the card
            </p>
            <button class="mt-2 px-3 py-2 bg-pink-400 rounded-lg font-semibold text-white">
                Toggle Modes
            </button>
        </div>
    </div>
</div>

The preview of the card component will look like below.
Card Component Preview


Card Component Dark Variant
To add the dark variant for the card component, you can use the "dark:" to style the corresponding light theme. Refer to the example below.

Before (only light variant)
<div class="p-4 rounded-lg shadow bg-white"></div>

After (now contain dark variant)
<div class="p-4 rounded-lg shadow bg-white dark:bg-gray-700"></div>

The full code of the dark variant will look like below.
<div class="h-screen flex justify-center items-center bg-gray-50">
    <div class="w-full sm:w-8/12 md:w-6/12 p-4">
        <div class="p-4 rounded-lg shadow bg-white dark:bg-gray-700">
            <h1 class="font-semibold text-lg dark:text-gray-200">
                Card Heading
            </h1>
            <p class="mt-2 dark:text-gray-200">
                This is the content of the card
            </p>
            <button class="mt-2 px-3 py-2 bg-pink-400 rounded-lg font-semibold text-white">
                Toggle Modes
            </button>
        </div>
    </div>
</div>

Card Component Dark Mode Preview


Bind the Toggle with Alpine JS
Now since we have the light and dark mode variant set up, let's bind the button with Alpine JS. The full code can be referred from below.
<div class="h-screen flex justify-center items-center bg-gray-50">
    <div class="w-full sm:w-8/12 md:w-6/12 p-4">
        <div class="p-4 rounded-lg shadow bg-white dark:bg-gray-700">
            <h1 class="font-semibold text-lg dark:text-gray-200">
                Card Heading
            </h1>
            <p class="mt-2 dark:text-gray-200">
                This is the content of the card
            </p>
            <button
                x-data="{
                    toggle: () => {
                        if (localStorage.theme === 'dark') {
                            localStorage.theme = 'light';
                            document.documentElement.classList.remove('dark');
                        } else {
                            localStorage.theme = 'dark';
                            document.documentElement.classList.add('dark');
                        }
                    },
                }"
                class="mt-2 px-3 py-2 bg-pink-400 rounded-lg font-semibold text-white focus:outline-none"
                @click="toggle"
            >
                Toggle Modes
            </button>
        </div>
    </div>
</div>

How the toggle work is that every time it's clicked, the local storage is checked to see if there's a "theme" with a "dark" value. If the value is present then the theme is set to light and remove any existing class from the document "HTML" tag.
localStorage.theme = 'light';
document.documentElement.classList.remove('dark');

Otherwise, if the value is already "light", then add the "dark" theme and set the "HTML" tag to have the class.
localStorage.theme = 'dark';
document.documentElement.classList.add('dark');

Respect Operating System Color Preference
If by default you want the page to respect the operating system color preference, you can add the code below. So if by default the user operating system is using dark mode, the page will set the page to dark otherwise it will be light.
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
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')
}

// Whenever the user explicitly chooses light mode
localStorage.theme = 'light'

// Whenever the user explicitly chooses dark mode
localStorage.theme = 'dark'

// Whenever the user explicitly chooses to respect the OS preference
localStorage.removeItem('theme')