Variables CSS para temas claro/oscuro sin librerías

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
localStorageevita 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.