TechLead
Lección 6 de 9
5 min de lectura
Tailwind CSS

Modo Oscuro

Implementa modo oscuro en tus proyectos Tailwind usando el modificador dark y diferentes estrategias.

Modo Oscuro en Tailwind

Tailwind CSS incluye soporte integrado para modo oscuro que te permite estilizar tu sitio de forma diferente cuando el modo oscuro está habilitado.

Habilitar Modo Oscuro

Configura la estrategia de modo oscuro en tu configuración:

// tailwind.config.js
module.exports = {
  darkMode: 'class', // o 'media'
  // ...
}

Estrategias de Modo Oscuro

  • media - Usa la media query prefers-color-scheme (preferencia del sistema)
  • class - Control manual con una clase 'dark' en el elemento html

Usando el Modificador Dark

<!-- Estilo básico de modo oscuro -->
<div class="bg-white dark:bg-gray-900">
  <h1 class="text-gray-900 dark:text-white">Hello World</h1>
  <p class="text-gray-600 dark:text-gray-400">Some text content</p>
</div>

<!-- Card con modo oscuro -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg dark:shadow-gray-900/50 p-6">
  <h2 class="text-xl font-bold text-gray-900 dark:text-white mb-2">
    Card Title
  </h2>
  <p class="text-gray-600 dark:text-gray-300">
    This card adapts to dark mode.
  </p>
</div>

Modo Oscuro con Estrategia de Clase

<!-- Alterna modo oscuro agregando/quitar la clase 'dark' en html -->
<html class="dark">
  <body class="bg-white dark:bg-gray-900">
    <!-- Contenido -->
  </body>
</html>
// JavaScript para alternar modo oscuro
function toggleDarkMode() {
  document.documentElement.classList.toggle('dark');
}

// O con persistencia en localStorage
function toggleDarkMode() {
  const isDark = document.documentElement.classList.toggle('dark');
  localStorage.setItem('darkMode', isDark ? 'dark' : 'light');
}

// Al cargar la página, revisar preferencia
if (localStorage.getItem('darkMode') === 'dark' ||
    (!localStorage.getItem('darkMode') &&
     window.matchMedia('(prefers-color-scheme: dark)').matches)) {
  document.documentElement.classList.add('dark');
}

Toggle de Modo Oscuro en React

import { useState, useEffect } from 'react';

function DarkModeToggle() {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    // Check initial preference
    const darkMode = localStorage.getItem('darkMode') === 'dark' ||
      (!localStorage.getItem('darkMode') &&
       window.matchMedia('(prefers-color-scheme: dark)').matches);
    setIsDark(darkMode);
    document.documentElement.classList.toggle('dark', darkMode);
  }, []);

  const toggle = () => {
    const newValue = !isDark;
    setIsDark(newValue);
    document.documentElement.classList.toggle('dark', newValue);
    localStorage.setItem('darkMode', newValue ? 'dark' : 'light');
  };

  return (
    <button
      onClick={toggle}
      className="p-2 rounded-lg bg-gray-200 dark:bg-gray-700 transition-colors"
    >
      {isDark ? '☀️' : '🌙'}
    </button>
  );
}

Patrones Comunes de Modo Oscuro

<!-- Navegación -->
<nav class="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700">
  <a href="#" class="text-gray-700 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400">
    Link
  </a>
</nav>

<!-- Inputs de formulario -->
<input
  type="text"
  class="
    bg-white dark:bg-gray-800
    border border-gray-300 dark:border-gray-600
    text-gray-900 dark:text-white
    placeholder-gray-400 dark:placeholder-gray-500
    focus:ring-blue-500 dark:focus:ring-blue-400
    focus:border-blue-500 dark:focus:border-blue-400
    rounded-lg px-4 py-2
  "
  placeholder="Enter text..."
>

<!-- Botón -->
<button class="
  bg-blue-600 dark:bg-blue-500
  hover:bg-blue-700 dark:hover:bg-blue-600
  text-white
  px-4 py-2 rounded-lg
">
  Submit
</button>

<!-- Bloque de código -->
<pre class="bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 p-4 rounded-lg overflow-x-auto">
  <code>const hello = "world";</code>
</pre>

Paleta de Colores para Modo Oscuro

<!-- Mapeos recomendados de color -->
<!--
Modo claro           Modo oscuro
bg-white         → bg-gray-900 or bg-gray-950
bg-gray-50       → bg-gray-800
bg-gray-100      → bg-gray-700
text-gray-900    → text-white or text-gray-100
text-gray-700    → text-gray-200
text-gray-600    → text-gray-300
text-gray-500    → text-gray-400
border-gray-200  → border-gray-700
border-gray-300  → border-gray-600
-->

<!-- Ejemplo de página completa -->
<div class="min-h-screen bg-gray-50 dark:bg-gray-900 transition-colors">
  <header class="bg-white dark:bg-gray-800 shadow">
    <nav class="max-w-7xl mx-auto px-4 py-4">
      <span class="text-xl font-bold text-gray-900 dark:text-white">
        My App
      </span>
    </nav>
  </header>

  <main class="max-w-7xl mx-auto px-4 py-8">
    <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
      <h1 class="text-2xl font-bold text-gray-900 dark:text-white mb-4">
        Welcome
      </h1>
      <p class="text-gray-600 dark:text-gray-300">
        This page supports dark mode.
      </p>
    </div>
  </main>
</div>

Modo Oscuro con Otros Estados

<!-- Modo oscuro combinado con hover -->
<button class="
  bg-gray-100 hover:bg-gray-200
  dark:bg-gray-800 dark:hover:bg-gray-700
  text-gray-900 dark:text-white
">
  Button
</button>

<!-- Modo oscuro con responsive -->
<div class="
  bg-white dark:bg-gray-900
  md:bg-gray-50 md:dark:bg-gray-800
">
  Responsive dark mode
</div>

Continuar Aprendiendo