Dark Mode Toggle: Cómo añadirlo a tu web paso a paso

Crea un modo oscuro profesional con CSS Variables, JavaScript y localStorage - tu portfolio lo agradecerá

¿Has visto esas webs que tienen un botoncito para cambiar entre modo claro y oscuro? Eso que parece magia es más fácil de lo que piensas. En este tutorial vamos a crear uno completamente funcional desde cero.

🎯 Lo que vas a lograr hoy:

  • Un botón que cambia entre modo claro y oscuro
  • Transiciones suaves entre temas
  • La preferencia del usuario se guarda (con localStorage)
  • Código 100% reutilizable para tus proyectos

👀 El resultado final

Antes de empezar, mira lo que vamos a construir:

Mi Sitio Web

Este es un ejemplo de contenido. Haz clic en el botón para cambiar entre modo claro y oscuro.

👆 ¡Haz clic en el botón para probar!

¿Viste la transición suave? Eso es lo que vamos a crear. Y no solo eso, también haremos que la preferencia del usuario se guarde para la próxima vez que visite tu web.

🤔 ¿Qué necesitas antes de empezar?

📦 Requisitos:

Un editor de código (VS Code recomendado - aquí la guía de instalación)
Saber crear un archivo HTML básico
Conocimiento básico de CSS (selectores, propiedades)
Haber trabajado con JavaScript antes (aunque sea un botón simple)

📝 Paso 1: El HTML - La estructura base

Vamos a crear un archivo index.html. Abre VS Code (el programa que instalaste), presiona Ctrl+N para crear un archivo nuevo, y copia este código exactamente:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mi Web con Dark Mode</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header>
        <nav>
            <h1>Mi Portfolio</h1>
            <button id="theme-toggle" class="theme-toggle">
                <span class="icon">🌙</span>
                <span class="text">Modo Oscuro</span>
            </button>
        </nav>
    </header>

    <main>
        <section class="hero">
            <h2>Hola, soy [Tu Nombre]</h2>
            <p>Desarrollador Web Frontend</p>
        </section>

        <section class="projects">
            <h3>Mis Proyectos</h3>
            <div class="project-card">
                <h4>Proyecto 1</h4>
                <p>Descripción del proyecto</p>
            </div>
            <div class="project-card">
                <h4>Proyecto 2</h4>
                <p>Descripción del proyecto</p>
            </div>
        </section>
    </main>

    <script src="script.js"></script>
</body>
</html>

Guarda el archivo con el nombre index.html (Ctrl+S en VS Code).

💡 ¿Qué acabamos de hacer?

  • Línea 7: Enlazamos nuestro archivo CSS (que crearemos ahora)
  • Líneas 11-14: Nuestro botón de toggle con un emoji de luna 🌙
  • Línea 33: Enlazamos el JavaScript que hará la magia

🎨 Paso 2: El CSS - Variables y estilos

Ahora crea un nuevo archivo llamado style.css en la misma carpeta donde guardaste el HTML. Este es el secreto del Dark Mode: CSS Variables.

/* ✅ Variables CSS: El corazón del Dark Mode */
:root {
    /* Colores para modo claro */
    --bg-primary: #ffffff;
    --bg-secondary: #f8fafc;
    --text-primary: #1a202c;
    --text-secondary: #4a5568;
    --border-color: #e2e8f0;
    --button-bg: #3b82f6;
    --button-hover: #2563eb;
}

/* ✅ Colores para modo oscuro */
:root.dark {
    --bg-primary: #1a202c;
    --bg-secondary: #2d3748;
    --text-primary: #f7fafc;
    --text-secondary: #cbd5e0;
    --border-color: #4a5568;
    --button-bg: #fbbf24;
    --button-hover: #f59e0b;
}

/* Reset y estilos base */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: var(--bg-primary);
    color: var(--text-primary);
    transition: background-color 0.3s ease, color 0.3s ease;
    line-height: 1.6;
}

/* Header y navegación */
header {
    background-color: var(--bg-secondary);
    border-bottom: 1px solid var(--border-color);
    padding: 1rem 2rem;
    transition: background-color 0.3s ease, border-color 0.3s ease;
}

nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: 1200px;
    margin: 0 auto;
}

/* Botón de toggle - La estrella del show */
.theme-toggle {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background-color: var(--button-bg);
    color: white;
    border: none;
    padding: 0.75rem 1.5rem;
    border-radius: 8px;
    font-size: 1rem;
    cursor: pointer;
    transition: all 0.3s ease;
}

.theme-toggle:hover {
    background-color: var(--button-hover);
    transform: translateY(-2px);
}

.theme-toggle .icon {
    font-size: 1.25rem;
}

/* Contenido principal */
main {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem;
}

.hero {
    text-align: center;
    padding: 4rem 0;
}

.hero h2 {
    font-size: 2.5rem;
    margin-bottom: 0.5rem;
}

.hero p {
    font-size: 1.25rem;
    color: var(--text-secondary);
}

.projects {
    margin-top: 3rem;
}

.projects h3 {
    font-size: 2rem;
    margin-bottom: 1.5rem;
}

.project-card {
    background-color: var(--bg-secondary);
    border: 1px solid var(--border-color);
    padding: 1.5rem;
    border-radius: 8px;
    margin-bottom: 1rem;
    transition: all 0.3s ease;
}

.project-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.project-card h4 {
    margin-bottom: 0.5rem;
}

.project-card p {
    color: var(--text-secondary);
}

🔍 Entiende las CSS Variables:

  • :root define variables globales que puedes usar en todo tu CSS
  • :root.dark sobrescribe las variables cuando añadimos la clase "dark"
  • var(--nombre) es cómo usamos esas variables
  • Transiciones hacen que los cambios sean suaves, no bruscos

⚡ Paso 3: El JavaScript - La magia interactiva

Ahora viene la parte divertida. Crea un archivo script.js y añade este código:

// 1️⃣ Seleccionamos los elementos del DOM
const themeToggle = document.getElementById('theme-toggle');
const icon = themeToggle.querySelector('.icon');
const text = themeToggle.querySelector('.text');

// 2️⃣ Función para cambiar el tema
function toggleTheme() {
    // Añadimos o quitamos la clase 'dark' del elemento raíz
    document.documentElement.classList.toggle('dark');
    
    // Verificamos si el modo oscuro está activo
    const isDark = document.documentElement.classList.contains('dark');
    
    // Cambiamos el icono y texto del botón
    if (isDark) {
        icon.textContent = '☀️';
        text.textContent = 'Modo Claro';
    } else {
        icon.textContent = '🌙';
        text.textContent = 'Modo Oscuro';
    }
    
    // 3️⃣ Guardamos la preferencia en localStorage
    localStorage.setItem('theme', isDark ? 'dark' : 'light');
}

// 4️⃣ Función para cargar el tema guardado
function loadTheme() {
    // Obtenemos el tema guardado (si existe)
    const savedTheme = localStorage.getItem('theme');
    
    // Si hay un tema guardado y es 'dark', lo aplicamos
    if (savedTheme === 'dark') {
        document.documentElement.classList.add('dark');
        icon.textContent = '☀️';
        text.textContent = 'Modo Claro';
    }
}

// 5️⃣ Event listener para el botón
themeToggle.addEventListener('click', toggleTheme);

// 6️⃣ Cargamos el tema cuando se carga la página
loadTheme();

🧠 Desglosemos el JavaScript paso a paso:

  • Paso 1: Obtenemos referencias al botón y sus elementos internos
  • Paso 2: toggleTheme() añade/quita la clase "dark" y actualiza el botón
  • Paso 3: localStorage.setItem() guarda la preferencia del usuario
  • Paso 4: loadTheme() recupera y aplica el tema guardado
  • Paso 5: Conectamos la función al click del botón
  • Paso 6: Cargamos el tema al iniciar la página

🚀 Paso 4: ¡Prueba tu Dark Mode!

Ahora tienes 3 archivos en la misma carpeta:

Abre el archivo index.html en tu navegador (doble clic en el archivo o arrastra al navegador). ¡Haz clic en el botón y mira la magia!

El tema cambia al hacer clic
Transiciones suaves
Se guarda tu preferencia

💡 Mejoras que puedes hacer (nivel intermedio)

1. Detectar la preferencia del sistema

Puedes hacer que tu web respete la preferencia de dark mode del sistema operativo del usuario:

// Añade esto al final de script.js
function initTheme() {
    const savedTheme = localStorage.getItem('theme');
    
    // Si NO hay tema guardado, usar preferencia del sistema
    if (!savedTheme) {
        const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
        
        if (prefersDark) {
            document.documentElement.classList.add('dark');
            icon.textContent = '☀️';
            text.textContent = 'Modo Claro';
        }
    } else {
        loadTheme();
    }
}

// Reemplaza loadTheme() con initTheme()
initTheme();

2. Añadir más temas (no solo claro/oscuro)

Puedes crear múltiples temas definiendo más conjuntos de variables:

/* En style.css */
:root.ocean {
    --bg-primary: #0a192f;
    --bg-secondary: #172a45;
    --text-primary: #ccd6f6;
    --text-secondary: #8892b0;
    --button-bg: #64ffda;
}

:root.sunset {
    --bg-primary: #1a1423;
    --bg-secondary: #2d1b3d;
    --text-primary: #f7e7ce;
    --button-bg: #ff6b6b;
}

3. Añadir animación al cambiar de tema

Para un efecto más dramático, puedes añadir una animación de fade:

/* En style.css */
body {
    animation: fadeIn 0.3s ease;
}

@keyframes fadeIn {
    from {
        opacity: 0.8;
    }
    to {
        opacity: 1;
    }
}

❌ Errores comunes que debes evitar

⚠️ ¡Cuidado con estos errores!

  • Olvidar cargar el tema al inicio: Sin loadTheme(), la preferencia guardada no se aplicará
  • No usar variables CSS: Si usas colores directos en lugar de var(--nombre), el dark mode no funcionará
  • Inconsistencia en los nombres: Si tu clase CSS es "dark" pero guardas "dark-mode" en localStorage, no coincidirá
  • No añadir transiciones: Sin transition: 0.3s ease, el cambio será brusco y feo

🎯 Casos de uso reales

Este código es 100% production-ready. Así es cómo lo puedes usar:

💼 Portfolio personal: Dale una opción profesional a los recruiters
📝 Blog: Lectura cómoda a cualquier hora
🛒 E-commerce: Experiencia premium para usuarios
📱 Apps web: Menos fatiga visual en uso prolongado

🔍 Recursos adicionales

Quieres seguir aprendiendo sobre manipulación del DOM y JavaScript? Te recomiendo estos tutoriales:

💪 Resumen: Lo que acabas de aprender

🎓 Conceptos dominados:

  • ✅ CSS Variables (:root y custom properties)
  • ✅ Manipulación del DOM con JavaScript (classList.toggle)
  • ✅ localStorage para persistencia de datos
  • ✅ Event listeners y funciones
  • ✅ Transiciones CSS para UX profesional
  • ✅ Estructura de proyecto con múltiples archivos

¡Felicidades! Ahora tienes un Dark Mode totalmente funcional. Este es exactamente el tipo de feature que hace destacar a un portfolio junior. Es visual, práctico y muestra que entiendes JavaScript, CSS y UX.

🎯 ¿Qué hacer ahora?

Sigue construyendo tu portfolio con más proyectos prácticos:

👉 Tu primera página web responsive (móvil + desktop)

Aprende a hacer que tu web se vea perfecta en cualquier dispositivo