El
modelo de color HSL
(matiz, saturación y luminosidad) ofrece a los desarrolladores una forma mucho más legible de trabajar con colores en CSS en comparación con RGB. En lugar de adivinar qué combinación de valores de rojo, verde y azul produce el tono que buscas, HSL te permite describir el color de la misma manera en que tu cerebro lo percibe: elige un color, decide qué tan vivo es y luego determina qué tan claro u oscuro debe ser. Ese cambio de modelo mental es exactamente por qué tantos desarrolladores están abandonando
rgb()
en favor de
hsl()
.
Tabla de contenidos
RGB vs HSL - La diferencia fundamental
RGB define el color mezclando tres canales de luz: rojo, verde y azul, cada uno en una escala del 0 al 255. El problema es que así es como las pantallas renderizan píxeles, no como los humanos percibimos el color. Si quieres un azul un poco más claro en RGB, tienes que incrementar los tres canales en la proporción exacta - no hay un único parámetro que puedas ajustar de forma aislada.
HSL se corresponde directamente con la manera en que las personas describen el color en una conversación:
- Matiz (Hue) - el color en sí, expresado como un grado en una rueda de color de 360 grados. El rojo es 0, el verde es 120, el azul es 240.
- Saturación (Saturation) - qué tan vivo o apagado es el color, desde 0% (gris puro) hasta 100% (máxima viveza).
- Luminosidad (Lightness) - qué tan claro u oscuro es el color, desde 0% (negro) hasta 100% (blanco), siendo 50% el color "puro".
Aquí está el mismo azul medio expresado en ambos formatos:
/* RGB - what do these numbers even mean at a glance? */
color: rgb(70, 130, 180);
/* HSL - instantly readable: blue hue, moderate saturation, medium lightness */
color: hsl(207, 44%, 49%);
Ambos producen el mismo azul acero. Pero solo la versión HSL te dice algo útil de un vistazo. El matiz es 207 (azulado), la saturación es moderada en 44% y la luminosidad está en el punto medio con 49%. Puedes razonar sobre él sin necesidad de abrir un selector de color.
| Propiedad | RGB | HSL |
|---|---|---|
| Legible por humanos | Raramente | Sí |
| Aclarar/oscurecer un color | Ajustar 3 valores | Ajustar solo la luminosidad |
| Cambiar la saturación | Recalcular los 3 valores | Ajustar solo la saturación |
| Crear paleta de colores | Prueba y error | Rotar el matiz en grados |
| Temas con variables CSS | Verboso | Limpio y predecible |
Sintaxis de HSL en CSS
La función
hsl()
de CSS está disponible desde CSS3. La sintaxis moderna (CSS Color Level 4) también permite un cuarto parámetro alpha directamente dentro de
hsl()
, lo que hace que
hsla()
sea prácticamente innecesaria hoy en día:
/* Classic syntax */
color: hsl(207, 44%, 49%);
/* With alpha (transparency) - old way */
color: hsla(207, 44%, 49%, 0.8);
/* Modern CSS Color Level 4 syntax - commas optional, alpha with slash */
color: hsl(207 44% 49%);
color: hsl(207 44% 49% / 0.8);
color: hsl(207 44% 49% / 80%);
Todos los navegadores principales admiten ambas sintaxis. La versión sin comas es hacia donde se dirige CSS, pero la versión con comas funciona en todos lados, incluyendo Internet Explorer 9+.
Por qué HSL gana en el desarrollo de interfaces
El verdadero potencial de HSL se hace evidente en el momento en que necesitas generar variaciones de un color, algo que ocurre constantemente en el desarrollo de interfaces.
Construir una paleta de colores en segundos
Supón que el color de tu marca es un verde vivo en
hsl(140, 70%, 45%)
. Necesitas un estado hover, un estado deshabilitado y un tinte de fondo claro. Con HSL, solo tocas un valor en cada caso:
--color-base: hsl(140, 70%, 45%); /* base green */
--color-hover: hsl(140, 70%, 38%); /* darker - just lower lightness */
--color-disabled: hsl(140, 20%, 65%); /* washed out - lower saturation */
--color-tint: hsl(140, 70%, 92%); /* very light background tint */
Intenta hacer eso de forma predecible en RGB sin tener un selector de color abierto. Es genuinamente difícil porque no existe un eje aislado que puedas ajustar.
Colores análogos y complementarios
Como el matiz es un grado en una rueda de color, generar paletas armoniosas es simplemente aritmética. Los colores análogos están dentro de 30 grados entre sí. Los colores complementarios están a 180 grados de distancia:
--primary: hsl(210, 80%, 50%); /* blue */
--analogous-1: hsl(180, 80%, 50%); /* cyan - 30 degrees left */
--analogous-2: hsl(240, 80%, 50%); /* purple - 30 degrees right */
--complementary: hsl(30, 80%, 50%); /* orange - 180 degrees opposite */
La saturación y la luminosidad se mantienen idénticas, por lo que los colores se perciben como una familia cohesionada. Así es exactamente como sistemas de diseño como Tailwind CSS y Material Design generan sus escalas de color de forma programática.
Ejemplos prácticos en CSS
Propiedades personalizadas de CSS con componentes HSL
Uno de los patrones más potentes con HSL es separar los tres valores en propiedades personalizadas de CSS independientes. Esto te permite reconstruirlos en cualquier lugar y ajustar canales individuales al vuelo:
:root {
--brand-h: 210;
--brand-s: 80%;
--brand-l: 50%;
--brand-color: hsl(var(--brand-h), var(--brand-s), var(--brand-l));
}
.button {
background-color: var(--brand-color);
}
.button:hover {
/* Just override lightness - no need to redefine the whole color */
background-color: hsl(var(--brand-h), var(--brand-s), 40%);
}
.button:disabled {
background-color: hsl(var(--brand-h), 20%, 70%);
}
hsl()
, necesitas comas:
hsl(var(--h), var(--s), var(--l))
. La sintaxis moderna sin comas aún no funciona con
var()
dentro de
hsl()
en todos los navegadores.
Generar una escala tonal completa
Los sistemas de diseño suelen necesitar entre 9 y 10 tonos de un mismo color (como la escala del 50 al 950 de Tailwind). Con HSL, puedes generar toda la escala incrementando la luminosidad en intervalos regulares mientras mantienes el matiz y la saturación fijos:
:root {
--blue-50: hsl(210, 80%, 95%);
--blue-100: hsl(210, 80%, 87%);
--blue-200: hsl(210, 80%, 76%);
--blue-300: hsl(210, 80%, 65%);
--blue-400: hsl(210, 80%, 55%);
--blue-500: hsl(210, 80%, 50%); /* base */
--blue-600: hsl(210, 80%, 43%);
--blue-700: hsl(210, 80%, 36%);
--blue-800: hsl(210, 80%, 26%);
--blue-900: hsl(210, 80%, 16%);
}
Para profundizar en cómo se relacionan los distintos formatos de color entre sí, la guía de conversión de HEX a RGB ofrece una visión completa de los formatos de color en CSS, incluyendo cuándo conviene usar cada uno.
Estados hover, temas y modo oscuro
Estados hover y focus
HSL hace que los estados hover sean triviales. En lugar de definir un color completamente diferente, simplemente ajustas la luminosidad:
.btn-primary {
background: hsl(210, 80%, 50%);
transition: background 0.2s ease;
}
.btn-primary:hover { background: hsl(210, 80%, 43%); }
.btn-primary:active { background: hsl(210, 80%, 36%); }
.btn-primary:focus-visible {
outline: 3px solid hsl(210, 80%, 70%);
}
Cada estado está claramente relacionado con el color base. Cualquier compañero que lea este código entiende de inmediato la relación entre los estados.
Temas con variables HSL
HSL es la base del sistema de temas moderno en CSS. Al exponer solo el matiz como variable, puedes permitir que usuarios o administradores cambien todo el esquema de color de una aplicación modificando un único número:
/* Default theme: blue */
:root {
--theme-hue: 210;
}
/* Green theme - just swap the hue */
[data-theme="green"] {
--theme-hue: 140;
}
/* Purple theme */
[data-theme="purple"] {
--theme-hue: 270;
}
/* All components use the same hue variable */
.button { background: hsl(var(--theme-hue), 75%, 50%); }
.link { color: hsl(var(--theme-hue), 75%, 40%); }
.badge { background: hsl(var(--theme-hue), 75%, 92%); color: hsl(var(--theme-hue), 75%, 25%); }
.focus-ring { outline-color: hsl(var(--theme-hue), 75%, 65%); }
Modo oscuro con HSL
El modo oscuro es donde HSL realmente destaca. En lugar de mantener dos paletas de colores completamente separadas, simplemente inviertes los valores de luminosidad dentro del mismo matiz:
:root {
--bg: hsl(210, 20%, 98%); /* near-white background */
--text: hsl(210, 20%, 15%); /* near-black text */
--card: hsl(210, 20%, 93%); /* slightly darker card */
}
@media (prefers-color-scheme: dark) {
:root {
--bg: hsl(210, 20%, 10%); /* flip: near-black background */
--text: hsl(210, 20%, 90%); /* flip: near-white text */
--card: hsl(210, 20%, 15%); /* slightly lighter card in dark */
}
}
Observa que el matiz (210) y la saturación (20%) nunca cambian. Solo se invierte la luminosidad. Esto hace que el modo oscuro se sienta como el mismo diseño, simplemente invertido, que es exactamente lo que un buen modo oscuro debe lograr.
Soporte de navegadores y compatibilidad
HSL tiene un excelente soporte en navegadores. La función
hsl()
ha estado disponible desde:
- Chrome 1 (2008)
- Firefox 1 (2004)
- Safari 3.1 (2008)
- Internet Explorer 9 (2011)
- Edge 12 (2015)
La sintaxis moderna sin comas (
hsl(210 80% 50%)
) y la sintaxis con barra para el canal alpha (
hsl(210 80% 50% / 0.5)
) forman parte de la
especificación CSS Color Level 4
y están disponibles en todos los navegadores modernos desde 2023. Si necesitas compatibilidad con IE11 (algo poco común a estas alturas), usa la sintaxis con comas.
hsl()
con comas funciona en todos los navegadores que probablemente usen tus usuarios. La sintaxis moderna con espacios funciona en Chrome 90+, Firefox 89+ y Safari 14.1+, cubriendo más del 95% del uso global de navegadores.
Siempre puedes usar un selector de color para convertir entre los formatos HSL, RGB y HEX cuando necesites comparar valores o entregar colores a herramientas que solo aceptan un formato específico.
HSL vs OKLCH - ¿Qué viene después?
Si quieres ir más allá de HSL, OKLCH vale la pena conocerlo. Es un espacio de color perceptualmente uniforme, lo que significa que pasos numéricos iguales en luminosidad o croma se perciben como pasos iguales para el ojo humano, algo que HSL no garantiza completamente.
El problema con HSL es que dos colores con el mismo valor de luminosidad pueden verse muy diferentes en brillo percibido. Por ejemplo,
hsl(60, 100%, 50%)
(amarillo) parece mucho más brillante que
hsl(240, 100%, 50%)
(azul), aunque ambos tienen 50% de luminosidad. OKLCH corrige esto.
/* HSL - same lightness, different perceived brightness */
color: hsl(60, 100%, 50%); /* yellow - looks very bright */
color: hsl(240, 100%, 50%); /* blue - looks much darker */
/* OKLCH - same lightness, actually looks the same to the eye */
color: oklch(0.75 0.18 90); /* yellow-ish */
color: oklch(0.75 0.18 260); /* blue-ish - genuinely similar perceived brightness */
OKLCH también admite
colores de gama amplia
(colores de pantalla P3) que van más allá del rango sRGB al que HSL está limitado. El soporte de navegadores para
oklch()
es sólido en 2024: Chrome 111+, Firefox 113+, Safari 15.4+.
Para la mayoría de los proyectos actuales, HSL es el punto de equilibrio ideal: legible, fácil de mantener, con soporte universal y una mejora enorme respecto a RGB. OKLCH es la elección correcta cuando estás construyendo un sistema de diseño que necesita ratios de contraste matemáticamente consistentes o cuando quieres apuntar a pantallas de gama amplia.
Si estás explorando relaciones de color visualmente mientras construyes tu paleta, el explorador de colores te permite experimentar con valores HSL y ver en tiempo real cómo interactúan las rotaciones de matiz, los cambios de saturación y las variaciones de luminosidad.
Elige colores HSL sin adivinar
Nuestro selector de color te permite ajustar visualmente los valores de matiz, saturación y luminosidad, y luego copiar directamente en tu CSS el resultado del modelo de color HSL, sin necesidad de hacer cálculos mentales.
Probar el selector de color →
No necesitas hacer una reescritura completa, pero vale la pena usar HSL para cualquier nueva definición de color que escribas, especialmente cuando uses propiedades personalizadas de CSS. Las mayores ventajas se obtienen cuando estás construyendo o manteniendo un sistema de diseño, creando estados hover o implementando el modo oscuro. Mezclar RGB y HSL en el mismo proyecto es CSS perfectamente válido: los navegadores manejan ambos sin ninguna diferencia de rendimiento.
No, no hay ninguna diferencia de rendimiento significativa. El navegador convierte todos los formatos de color de CSS a una representación interna en el momento del parseo, por lo que tanto si escribes
hsl(207, 44%, 49%)
como
rgb(70, 130, 180)
, el motor de renderizado los trata de forma idéntica después de ese paso inicial. La elección es puramente cuestión de experiencia del desarrollador y mantenibilidad, no de rendimiento en tiempo de ejecución.
Sí, y este es uno de los casos de uso más potentes de HSL en JavaScript. Puedes almacenar el matiz, la saturación y la luminosidad como números independientes y luego construir el string de color dinámicamente:
element.style.color = `hsl(${hue}, ${saturation}%, ${lightness}%)`
. Esto hace que las animaciones, el cambio de temas y los controles de color interactivos sean mucho más sencillos de implementar que trabajando con canales RGB, donde necesitarías matemáticas de conversión para lograr los mismos efectos.
HSL (matiz, saturación, luminosidad) y HSB/HSV (matiz, saturación, brillo/valor) son modelos de color distintos aunque comparten el eje de matiz. En HSL, una luminosidad del 50% te da el color puro con saturación máxima. En HSB, un brillo del 100% te da el color puro. Los dos modelos producen resultados diferentes para los mismos valores de saturación y brillo/luminosidad. CSS usa HSL específicamente: HSB/HSV es común en herramientas de diseño como Photoshop y Figma, pero no es un formato nativo de CSS.
La conversión de HEX a HSL pasa por un paso intermedio en RGB: primero convierte los pares HEX a valores RGB (0-255), normalízalos a 0-1 y luego aplica la fórmula de conversión a HSL. En la práctica, la mayoría de los desarrolladores usan un selector de color, una herramienta de diseño como Figma o el selector de color de las DevTools del navegador para hacerlo al instante, en lugar de calcularlo a mano. Las DevTools del navegador te permiten hacer clic en cualquier muestra de color y alternar entre las representaciones HEX, RGB y HSL.
Sí, OKLCH es más fiable para el trabajo de accesibilidad porque es perceptualmente uniforme: pasos iguales en su canal de luminosidad corresponden a cambios iguales en el brillo percibido. Esto facilita la creación de paletas de colores donde los ratios de contraste son predecibles entre distintos matices. Con HSL, el amarillo al 50% de luminosidad parece mucho más brillante que el azul al 50% de luminosidad, lo que puede generar sorpresas en términos de accesibilidad. Para el cumplimiento del contraste según WCAG, OKLCH ofrece resultados más predecibles al construir escalas de color accesibles.