Skip to content

Dark Mode

En Tailwind CSS contamos con una clase que nos permite cambiar el tema de nuestra página web, esta clase es dark y se puede aplicar a cualquier elemento de nuestra página web.

Activar el modo oscuro

Para activar el modo oscuro en nuestra página web, debemos agregar la clase dark a nuestro elemento raíz, en este caso, el elemento html.

html
<html class="dark">
    ...
</html>

Variante de color

Para que esto sea lo más fácil posible, Tailwind CSS nos ofrece una variante de color que nos permite cambiar el color de un elemento en modo oscuro, esta variante se llama dark: y se puede aplicar a cualquier clase de color.

html
<div class="bg-gray-100 dark:bg-gray-800">...</div>

Prefers color && LocalStorage

utils/darkMode.js

js
// si existe el modo oscuro en el localStorage
// o si el sistema operativo tiene el modo oscuro activado pero no se ha guardado en el localStorage
if (
    localStorage.theme === "dark" ||
    (!("theme" in localStorage) &&
        window.matchMedia("(prefers-color-scheme: dark)").matches)
) {
    // agregamos la clase dark al elemento html
    document.documentElement.classList.add("dark");
    // guardamos el modo oscuro en el localStorage
    localStorage.theme = "dark";
} else {
    // si no existe el modo oscuro en el localStorage
    // o si el sistema operativo tiene el modo oscuro desactivado
    // removemos la clase dark del elemento html
    document.documentElement.classList.remove("dark");
    // guardamos el modo claro en el localStorage
    localStorage.theme = "light";
}

En React

jsx
// es importante llamar al script antes que App.jsx
import "./utils/darkMode";

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")).render(
    <React.StrictMode>
        <App />
    </React.StrictMode>
);

Ej: Header.jsx

jsx
import { useEffect, useState } from "react";
import IconMoon from "./icons/IconMoon";
import IconSun from "./icons/IconSun";

const initialDarkToggle = document.documentElement.className.includes("dark");

const Header = () => {
    const [darkToggle, setDarkToggle] = useState(initialDarkToggle);

    useEffect(() => {
        if (darkToggle) {
            document.documentElement.classList.add("dark");
            localStorage.theme = "dark";
        } else {
            document.documentElement.classList.remove("dark");
            localStorage.theme = "light";
        }
    }, [darkToggle]);

    return (
        <header className="container mx-auto px-4 pt-8">
            <div className="flex justify-between">
                <h1 className="text-3xl font-semibold uppercase tracking-[0.3em] text-white">
                    Todo
                </h1>
                <button onClick={() => setDarkToggle(!darkToggle)}>
                    {darkToggle ? <IconSun /> : <IconMoon />}
                </button>
            </div>
        </header>
    );
};

export default Header;