Variables CSS para temas claro/oscuro sin librerías

Close-up of colorful programming code on a computer screen, showcasing digital technology.
Foto de Myburgh Roux en Pexels

En los últimos años el modo oscuro se ha convertido en una expectativa de los usuarios. Afortunadamente no necesitas librerías ni JavaScript complejo para implementarlo: las CSS variables combinadas con la consulta prefers-color-scheme hacen el trabajo por ti.

¿Qué son las CSS variables?

Las --nombre-variable son valores que puedes definir en cualquier regla CSS y reutilizar en todo el documento. Lo interesante es que su valor puede cambiar en tiempo de ejecución, lo que permite adaptar colores, tamaños o cualquier otra propiedad sin tocar el resto del código.

Configuración básica del tema

Lo primero es declarar una paleta mínima en :root. Aquí usamos variables para los colores de fondo y de texto, pero puedes añadir tantas como necesites.

:root {
--color-fondo: #ffffff;
--color-texto: #222222;
--color-acento: #0066ff;
}

Con estas variables ya puedes escribir estilos habituales:

body {
background-color: var(--color-fondo);
color: var(--color-texto);
}

a {
color: var(--color-acento);
}

Definir la paleta para modo oscuro

En lugar de crear una clase extra, aprovechamos la media query (prefers-color-scheme: dark). Cuando el usuario tiene activado el modo oscuro a nivel de sistema, el navegador aplicará los valores que redefinimos dentro del bloque.

@media (prefers-color-scheme: dark) {
:root {
--color-fondo: #121212;
--color-texto: #e0e0e0;
--color-acento: #bb86fc;
}
}

Con esto ya tienes un tema que responde automáticamente a la preferencia del sistema.

Conmutador manual con JavaScript

Algunos usuarios prefieren decidir el tema desde la propia página. Podemos añadir un pequeño script que añada o elimine una clase dark al html y que sobrescriba las variables.

/ Definimos la versión manual /
.dark {
--color-fondo: #121212;
--color-texto: #e0e0e0;
--color-acento: #bb86fc;
}

/ Script de conmutación /
const boton = document.getElementById('toggle-theme');
boton.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
// Guardamos la preferencia en localStorage
const modo = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
localStorage.setItem('theme', modo);
});

// Restaurar preferencia guardada
const guardado = localStorage.getItem('theme');
if (guardado) {
document.documentElement.classList.toggle('dark', guardado === 'dark');
}

El botón se puede colocar en cualquier parte del UI:

<button id="toggle-theme">Cambiar tema</button>

Buenas prácticas

  • Nombrado consistente: usa prefijos como --color- o --bg- para identificar rápidamente el propósito.
  • Fallbacks: aunque la mayoría de navegadores modernos soportan variables, siempre puedes proporcionar valores por defecto en la propia regla.
  • Persistencia: almacenar la elección del usuario en localStorage evita que el tema cambie al recargar la página.
  • Accesibilidad: verifica el contraste de colores en ambas paletas para cumplir con WCAG.

Conclusión

Con unas pocas líneas de CSS y un pequeño script puedes ofrecer tanto un modo claro como uno oscuro sin depender de librerías externas. Las CSS variables te dan flexibilidad para escalar la paleta, mientras que prefers-color-scheme garantiza que respetas la elección del sistema. Prueba a incorporar este patrón en tus proyectos y notarás lo sencillo que es mantener la consistencia visual sin cargar peso adicional.