CodeForge

Maquetación Web Dinámica / Arquitectura CSS y design tokens

Theming claro/oscuro con tokens semánticos

Teoría22 min20 XP

La primera gran recompensa de tu sistema de tokens: el tema oscuro. Y no duplicando CSS ni reescribiendo componentes, sino RE-APUNTANDO los tokens semánticos en un solo lugar. Le sumamos prefers-color-scheme para respetar la preferencia del sistema operativo y un toggle persistente para que el usuario elija. Un tema oscuro de verdad, elegante y mantenible.

Los interruptores de toda la casa

Re-apuntar los semánticos

Defines los tokens semánticos para el tema claro (por defecto) y los sobrescribes para el oscuro bajo un selector [data-theme="dark"]:

temas.css
:root {
--gris-900: #0f172a; --gris-50: #f8fafc; --blanco: #fff;
/* semánticos — TEMA CLARO (default) */
--color-fondo: var(--gris-50);
--color-texto: var(--gris-900);
--color-superficie: var(--blanco);
}

[data-theme="dark"] {
/* los MISMOS semánticos, re-apuntados para OSCURO */
--color-fondo: #0b1120;
--color-texto: #f1f5f9;
--color-superficie: #151e31;
}

/* los componentes NO cambian: solo usan los semánticos */
body { background: var(--color-fondo); color: var(--color-texto); }
.tarjeta { background: var(--color-superficie); }

Ni un componente se duplica. El tema entero vive en ese bloque [data-theme="dark"]. Ahí se ve la recompensa de la capa semántica de la lección anterior.

Pruébalo

Dale al toggle: TODO cambia —fondo, texto, superficie, acento, bordes— con una transición suave, y ningún componente sabe que existe un tema. Fíjate en que el violeta también cambió (a #a78bfa en oscuro): un buen acento para fondo claro no siempre lo es para oscuro — un detalle que la capa semántica te deja ajustar sin tocar componentes.

Respetar el sistema y persistir la elección

Dos piezas para un theming profesional:

auto.css
/* AUTO: si el usuario tiene el SO en oscuro, arranca en oscuro sin JS */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
  --color-fondo: #0b1120; --color-texto: #f1f5f9; /* ...los de oscuro... */
}
}
persistir.js
// PERSISTIR: recordar la elección manual entre visitas (localStorage, módulo 7)
const guardado = localStorage.getItem("tema");
if (guardado) document.documentElement.setAttribute("data-theme", guardado);

boton.addEventListener("click", () => {
const oscuro = document.documentElement.getAttribute("data-theme") === "dark";
const nuevo = oscuro ? "light" : "dark";
document.documentElement.setAttribute("data-theme", nuevo);
localStorage.setItem("tema", nuevo);   // se recuerda al recargar
});

La combinación ideal: arranca respetando el SO (prefers-color-scheme), pero si el usuario elige manualmente, ese data-theme gana y se persiste. (En el playground de arriba omitimos localStorage porque su iframe de prueba lo bloquea; en una página real es el código de aquí.)

Gracias a tus tokens semánticos, ¿qué necesitas para agregar un tema oscuro completo a un producto ya construido?

Mini-reto

Dale a "El Observador" un tema oscuro completo con el sistema de tokens que montaste: define el bloque [data-theme="dark"] re-apuntando tus semánticos, agrega el toggle con localStorage y el @media prefers-color-scheme para el arranque automático. Pruébalo cambiando el modo de tu sistema operativo Y con el botón. Un tema oscuro real, sin un solo componente duplicado.

Qué sigue

Tienes los valores organizados. Falta ordenar la CASCADA misma —el otro frente de la guerra de especificidad—. La próxima lección cubre las metodologías: BEM para nombrar sin colisiones, @layer para controlar qué gana en la cascada de forma explícita, y el criterio de cuándo nada de esto hace falta.