Mercado
Precios
Iniciar sesiónEmpezar
Guía prácticaCSS y web
CSS y web

Crea un tema con variables CSS: modo claro, oscuro y colores de marca

Los temas fallan cuando los colores se nombran por cómo se ven en lugar de por lo que hacen. Nombra los roles, apúntalos a una paleta, y el modo claro, el modo oscuro y una segunda marca se quedan en unas pocas líneas cada uno.

GradientlyCuenta verificada de Gradiently·1 de octubre de 2026·6 min de lectura
Portada: Modal Compass · GR·5TEZ·Q9

La versión corta

  • Un tema con variables CSS funciona mejor en dos capas: variables de paleta que guardan los colores en bruto y variables semánticas que describen para qué sirve cada color.
  • Los componentes solo deberían leer variables semánticas como --color-text o --color-surface, nunca valores de paleta directamente.
  • El modo oscuro consiste entonces en apuntar las variables semánticas a otros valores de la paleta, dentro de una media query o un atributo data.
  • La función light-dark() y la propiedad color-scheme permiten que una sola declaración contenga los dos modos en los navegadores actuales.
  • Un pequeño script en línea en el head que aplica el tema guardado antes de que se pinte la página evita el parpadeo del tema equivocado.
En esta página
Dos capas: paleta y rolesAñadir modo oscuro con variables CSSUn selector de tema que no parpadeaTemas de marca más allá del claro y el oscuroMantén la web y tus diseños en una sola paleta

Un tema con variables CSS es un conjunto de propiedades personalizadas, como --color-surface y --color-text, que todos los componentes leen en lugar de colores escritos a mano. Para cambiar el tema cambias las variables, normalmente en :root o en un atributo data-theme, y toda la interfaz lo sigue. El truco que lo hace escalar es dividir las variables en dos capas: una paleta de colores en bruto y unos roles semánticos que apuntan a esa paleta.

Dos capas: paleta y roles

Las variables de paleta se nombran por lo que son: --violet-600, --ink-900. Las variables semánticas se nombran por lo que hacen: --color-accent, --color-text-muted. Los componentes solo leen las segundas. Cuando llega el modo oscuro, reapuntas los roles y no tocas ningún componente. Es la misma idea que los tokens de diseño, expresada directamente en CSS.

Paleta--violet-600: #7c3aed

Quién la lee

Solo la capa de roles

Cambia cuando

Se rediseña la marca
Rol--color-accent: var(--violet-600)

Quién la lee

Todos los componentes

Cambia cuando

Cambia el tema o el modo
Componente

Ejemplo

--button-bg: var(--color-accent)

Quién la lee

Un componente

Cambia cuando

Un solo componente necesita un ajuste local
CapaEjemploQuién la leeCambia cuando
Paleta--violet-600: #7c3aedSolo la capa de rolesSe rediseña la marca
Rol--color-accent: var(--violet-600)Todos los componentesCambia el tema o el modo
Componente--button-bg: var(--color-accent)Un componenteUn solo componente necesita un ajuste local
La capa de componente es opcional. Úsala solo donde un componente necesite de verdad diferenciarse del rol.
css
:root {
  /* Palette: raw values, named for what they are */
  --paper-50: #faf8f5;
  --paper-100: #f1ede6;
  --ink-900: #14121f;
  --ink-700: #3d3a4f;
  --ink-500: #6b6880;
  --violet-600: #6d28d9;
  --violet-300: #c4b5fd;
  --night-950: #0d0b16;
  --night-900: #17142a;
  --night-800: #221e3a;

  /* Roles: what each colour is for (light mode) */
  --color-bg: var(--paper-50);
  --color-surface: var(--paper-100);
  --color-text: var(--ink-900);
  --color-text-muted: var(--ink-500);
  --color-border: color-mix(in oklab, var(--ink-900) 12%, transparent);
  --color-accent: var(--violet-600);
  --color-on-accent: #ffffff;
}

body { background: var(--color-bg); color: var(--color-text); }
.card { background: var(--color-surface); border: 1px solid var(--color-border); }
.button { background: var(--color-accent); color: var(--color-on-accent); }
Los componentes nunca mencionan el violeta ni la tinta. Esa única regla es lo que hace intercambiable el tema.
Los roles del tema claro. Un fondo de papel cálido en lugar del blanco puro hace que el acento violeta se sienta más sereno.

Nombres de rol que sobreviven a un rediseño

Un nombre de rol debería seguir siendo cierto después de que cambien los colores. --light-grey deja de ser claro en modo oscuro, y --blue miente el día que la marca se vuelve verde. Nombra la función y la pareja, para que quien lea la hoja de estilos después sepa qué color va sobre cuál.

Nombres que se rompen

  • --blue, --purple-button
  • --light-grey-bg
  • --white-text
  • --dark-border

Nombres que duran

  • --color-accent, --color-on-accent
  • --color-surface
  • --color-text
  • --color-border

Añadir modo oscuro con variables CSS

El modo oscuro reapunta los roles. Respeta por defecto el ajuste del sistema operativo y deja que un atributo data-theme lo sobrescriba cuando el lector elige. Define también color-scheme, para que las barras de desplazamiento, los controles de formulario y el lienzo por defecto coincidan.

css
:root { color-scheme: light; }

/* Follow the system unless the reader picked light */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --color-bg: var(--night-950);
    --color-surface: var(--night-900);
    --color-text: #f2f0fa;
    --color-text-muted: #a5a1bd;
    --color-border: color-mix(in oklab, #ffffff 12%, transparent);
    --color-accent: var(--violet-300);
    --color-on-accent: var(--ink-900);
  }
}

/* The reader picked dark explicitly */
:root[data-theme="dark"] {
  color-scheme: dark;
  --color-bg: var(--night-950);
  --color-surface: var(--night-900);
  --color-text: #f2f0fa;
  --color-text-muted: #a5a1bd;
  --color-border: color-mix(in oklab, #ffffff 12%, transparent);
  --color-accent: var(--violet-300);
  --color-on-accent: var(--ink-900);
}
Los valores oscuros aparecen dos veces: una para la preferencia del sistema y otra para una elección explícita. Un mixin de preprocesador o light-dark() elimina la repetición.
Los roles del tema oscuro. El acento sube a un violeta más claro, porque el violeta del modo claro es demasiado oscuro para leerse sobre un fondo casi negro.

El modo oscuro no es el modo claro invertido. Las superficies se aclaran a medida que suben, los acentos se aclaran y las sombras dejan paso a los bordes. Diseño en modo oscuro y degradados para modo oscuro cubren la parte visual.

El atajo light-dark()

Los navegadores actuales admiten light-dark(), que recibe un valor claro y uno oscuro y elige uno según el color-scheme del elemento. Define color-scheme: light dark en la raíz para seguir al sistema, o fuerza uno con el atributo, y cada rol se queda en una sola línea: --color-bg: light-dark(var(--paper-50), var(--night-950)). Mantén la forma larga si tienes que dar soporte a navegadores anteriores a 2024.

Un selector de tema que no parpadea

Si la elección guardada se aplica después de que se renderice la página, los lectores que eligieron el modo oscuro ven un destello blanco en cada carga. Aplica el atributo en un pequeño script en línea dentro del head, antes de que ninguna hoja de estilos pinte el body.

html
<head>
  <script>
    (function () {
      var saved = localStorage.getItem("theme");
      if (saved === "light" || saved === "dark") {
        document.documentElement.dataset.theme = saved;
      }
    })();
  </script>
  <link rel="stylesheet" href="/styles.css">
</head>
Se ejecuta antes del primer pintado. El botón del selector solo tiene que definir dataset.theme y guardar el valor en localStorage.
  1. 1

    Ofrece tres opciones

    Claro, oscuro y sistema. Quitar el atributo devuelve el control a prefers-color-scheme.

  2. 2

    Guarda solo las elecciones explícitas

    Guarda light o dark; borra la clave para sistema, de modo que se respete un cambio posterior en el sistema operativo.

  3. 3

    Evita transiciones al cargar

    Si los colores tienen transición, actívala solo después del primer pintado, o la página se animará de claro a oscuro mientras carga.

Temas de marca más allá del claro y el oscuro

Las mismas dos capas sirven para varias marcas en un mismo código. Cada marca aporta su propia paleta y sus valores de rol bajo un atributo data-brand, y los modos siguen funcionando encima. Con color-mix() puedes derivar estados hover y tintes a partir de un acento por marca, como se muestra en color-mix() en CSS.

css
[data-brand="harbour"] {
  --color-accent: #0f766e;
  --gradient-hero: linear-gradient(150deg, #042f2e 0%, #0f766e 55%, #5eead4 100%);
}

[data-brand="ember"] {
  --color-accent: #c2410c;
  --gradient-hero: linear-gradient(150deg, #431407 0%, #c2410c 55%, #fdba74 100%);
}

.button:hover { background: color-mix(in oklab, var(--color-accent), black 12%); }
.hero { background: var(--gradient-hero); }
Los degradados también pueden ser tokens. Guarda el valor completo en una variable y la cabecera cambia con la marca.
Los dos tokens de cabecera del código de arriba. Misma estructura, mismo ángulo, distinta marca.

Como las propiedades personalizadas se heredan, un tema no tiene por qué cubrir toda la página. Pon data-theme="dark" en una sección, como una franja promocional o un pie de página, y todo lo que haya dentro leerá los roles oscuros mientras el resto de la página sigue claro. Escribe el selector oscuro como [data-theme="dark"] en lugar de :root[data-theme="dark"] si quieres que funcione, y define también color-scheme en la sección.

Los degradados no hacen transición por sí solos

Cambiar una variable de degradado sustituye el fondo al instante. Para animar entre dos degradados, registra las paradas de color con @property, como se explica en @property en CSS.

Mantén la web y tus diseños en una sola paleta

Un tema en CSS es solo la mitad de una marca. Los mismos colores deberían aparecer en tus posts, presentaciones y emails. El kit de marca de Gradiently guarda tus paletas, tus logos y tus fuentes de títulos y de texto, y el Designer lo aplica cuando maqueta un diseño, así que el post que haces el lunes usa el mismo acento que tu web. Si todavía estás eligiendo esos colores, empieza por cómo elegir los colores de marca.

Pregunta al Designer

Describe lo que necesitas y la IA de Gradiently lo crea, sobre tu Mark.

Probar el Designer

Preguntas frecuentes

¿Cómo creo un tema con variables CSS?

Define variables de paleta con los colores en bruto y después variables semánticas como --color-bg que apunten a ellas. Los componentes solo leen las semánticas, y los temas las reapuntan.

¿Cómo añado modo oscuro con variables CSS?

Sobrescribe las variables semánticas dentro de @media (prefers-color-scheme: dark) y bajo un selector [data-theme="dark"] para los lectores que lo elijan.

¿Cómo evito que el tema parpadee al cargar la página?

Lee el tema guardado en un pequeño script en línea dentro del head y aplica el atributo antes de que la hoja de estilos pinte la página.

¿Qué hace light-dark() en CSS?

Devuelve su primer valor en modo claro y el segundo en modo oscuro, según el color-scheme del elemento. Funciona en los navegadores principales actuales.

¿Puedo guardar un degradado en una variable CSS?

Sí. Guarda el degradado completo como valor y úsalo en background. Para animar entre degradados, registra las paradas con @property.

Compartir esta guía

Escrito por GradientlyCuenta verificada de Gradiently

El equipo detrás de Gradiently, una herramienta de diseño creada en torno a los Marks: degradados vivos que hacen que todo lo que diseñas parezca tuyo.

Ver nuestro perfil

En esta página

Dos capas: paleta y rolesAñadir modo oscuro con variables CSSUn selector de tema que no parpadeaTemas de marca más allá del claro y el oscuroMantén la web y tus diseños en una sola paleta

Compartir esta guía

Siguiente en CSS y web

Generador de degradados CSS: escríbelos a mano o con herramientas

Sigue leyendo

Todas las guías de CSS y web
CSS y web

Design tokens: una sola fuente de verdad para color y tipografía

6 min de lectura

Un color de marca que vive en cuarenta archivos acabará desviándose. Un token vive en un solo sitio y todas las plataformas lo leen de ahí. Así se estructuran los design tokens, se nombran para que duren y llegan al código y al diseño.

Fondos

Diseño en modo oscuro: fondos, color y contraste

6 min de lectura

El modo oscuro no es el modo claro invertido. Superficies, texto, acentos y degradados necesitan sus propios valores, y las reglas son distintas de las que ya conoces.

CSS y web

color-mix() en CSS: mezclar colores en el navegador

6 min de lectura

color-mix() deja que el navegador haga las cuentas de color que antes hacías en un preprocesador o a ojo. Elige el espacio de color adecuado y un solo color de marca puede producir toda una paleta de tintes, sombras y versiones translúcidas.

Encuentra el look que es solo tuyo.

Cada Mark es un fondo vivo con un único dueño. Prueba uno que siga disponible y reserva el tuyo cuando te convenza.

Empieza a diseñar

Comprobar un certificado

Escribe un número de certificado o el código de un Mark para ver de quién es.

Funciona con ChatGPT y Claude

Pídele un diseño a tu IA. Lo crea en tu Mark, listo para editar.

ChatGPTClaude
Cómo conectarlo

Producto

  • Mercado
  • Explorar
  • Precios
  • Certificados

Aprende

  • Guía práctica
  • Centro de ayuda
  • Novedades

Desarrolladores

  • Introducción
  • ChatGPT y Claude
  • Referencia de la API
  • Claves de API

Empresa

  • Quiénes somos
  • Contacto
  • Iniciar sesión

Legal

  • Términos
  • Privacidad
  • Reembolsos
  • Protección de Marks
  • Cookies
  • Todas las políticas
Recorre las letras. Cada una lleva un Mark real.Toca una letra para ver su Mark.Un nombre. Diez Marks dentro.
© 2026 Gradiently