01

Trata HSL como un modelo de edición sRGB

CSS Color 4 define hsl() como una forma de especificar un color sRGB mediante tono, saturación y luminosidad. No ofrece un gamut más amplio ni es un espacio perceptualmente uniforme. El navegador convierte las coordenadas en componentes rojo, verde y azul. Esto permite realizar ajustes manuales y mantener una salida compatible con HEX y rgb(), pero también significa que los canales sRGB resueltos, no las tres etiquetas de entrada, son la evidencia final para comparar, almacenar y comprobar contraste.

  • El tono es un ángulo alrededor del cilindro HSL: 0deg es rojo, 120deg el primario verde sRGB y 240deg el primario azul sRGB.
  • Saturación 0% produce un resultado acromático; 100% usa la máxima saturación HSL disponible para ese tono y luminosidad.
  • Luminosidad 0% se resuelve como negro, 100% como blanco y 50% es el punto medio del modelo, no una promesa de brillo percibido medio.
  • Alpha es un componente separado: modifica la composición con el fondo, no las coordenadas almacenadas.
  • HEX, rgb() y hsl() pueden representar el mismo resultado sRGB dentro del gamut aunque expongan controles distintos.
02

Escribe una sintaxis sin componentes ambiguos

CSS moderno separa los componentes HSL con espacios y coloca alpha después de una barra. La forma antigua con comas sigue disponible por compatibilidad, pero mezclar ambas gramáticas es inválido. El tono acepta un ángulo; cero sin unidad también es válido, aunque deg explícito documenta mejor un token. Los ángulos dan vueltas, por lo que 0deg, 360deg y 720deg resuelven el mismo tono. Los ejemplos son opacos salvo cuando muestran alpha.

css
:root {
  --accent: hsl(210deg 100% 40%);
  --accent-translucent: hsl(210deg 100% 40% / 60%);
}

/* Valid legacy syntax, retained for compatibility. */
.legacy-example {
  color: hsl(210, 100%, 40%);
}
Entrada HSLHEX resueltoQué demuestra
hsl(0 100% 50%)#FF00000deg es rojo
hsl(360 100% 50%)#FF0000El tono da la vuelta
hsl(120 100% 50%)#00FF00Primario verde sRGB
hsl(240 100% 50%)#0000FFPrimario azul sRGB
hsl(210 0% 50%)#808080El tono no afecta un resultado acromático
03

La saturación cambia el colorido, no la opacidad

Mantén el tono en 210deg y la luminosidad en 50%, y reduce la saturación en pasos iguales de 25 puntos. El resultado se acerca al eje acromático sin dejar de ser completamente opaco. No equivale a bajar alpha: un azul translúcido revela un fondo desconocido, mientras que un HSL menos saturado ya se resuelve como una nueva terna sRGB opaca. La tabla aplica el algoritmo de CSS Color 4 y redondea los canales finales de 8 bits al entero más cercano.

SaturaciónHSLHEX resueltoRGB resuelto
100%hsl(210 100% 50%)#0080FF0 128 255
75%hsl(210 75% 50%)#2080DF32 128 223
50%hsl(210 50% 50%)#4080BF64 128 191
25%hsl(210 25% 50%)#60809F96 128 159
0%hsl(210 0% 50%)#808080128 128 128
04

Los pasos de luminosidad pueden cruzar el umbral del primer plano

Mantén ahora tono 210deg y saturación 100% mientras cambias la luminosidad HSL. La secuencia es fácil de generar, pero el primer plano adecuado no permanece constante. El contraste se calcula desde cada HEX redondeado con la fórmula de luminancia relativa sRGB de WCAG. AA para texto normal exige al menos 4,5:1. La opción más fuerte entre negro y blanco solo es una elección probada para esa pareja, no una certificación de accesibilidad de la página.

LuminosidadHEX resueltoTexto negroTexto blancoElección AA normal
20%#0033661.67:112.61:1Blanco
30%#004D992.52:18.33:1Blanco
40%#0066CC3.77:15.57:1Blanco
50%#0080FF5.53:13.80:1Negro
60%#3399FF7.14:12.94:1Negro
70%#66B3FF9.46:12.22:1Negro
80%#99CCFF12.44:11.69:1Negro
  • En esta escala, el primer plano cambia entre los pasos 40% y 50%.
  • Un estado hover o selected generado con el mismo tono sigue necesitando comprobaciones propias de contraste textual y no textual.
  • No redondees una relación antes de compararla con 4,5:1; redondea solo la cifra mostrada.
  • Si hay alpha, degradados, imágenes u overlays, calcula los colores finales renderizados antes de evaluar el contraste.
05

La luminosidad HSL no es luminosidad percibida

La palabra luminosidad parece perceptiva, pero la luminosidad HSL se deriva de los extremos de canales sRGB codificados con gamma. CSS Color 4 advierte expresamente que no sigue la luminosidad visual entre tonos. Amarillo saturado y azul saturado tienen ambos luminosidad HSL 50%, pero su luminancia relativa WCAG y los primeros planos útiles son radicalmente distintos. Tampoco son uniformes visualmente los cambios iguales de ángulo: unas zonas de la rueda HSL parecen comprimidas y otras muy separadas.

ColorHSLHEXLuminancia relativaTexto negroTexto blanco
Amarillohsl(60 100% 50%)#FFFF0092.78%19.56:11.07:1
Azulhsl(240 100% 50%)#0000FF7.22%2.44:18.59:1
06

Evita las seis trampas habituales de HSL

  • No trates HSL como formato de gamut amplio: hsl() en CSS se resuelve a sRGB y no conserva un color Display P3 exterior a sRGB.
  • No mantengas una etiqueta de tono significativa en un gris de saturación cero; ese componente no afecta al resultado.
  • No llames tinte o sombra a una edición de luminosidad HSL salvo que el proyecto defina expresamente así esos términos.
  • No sustituyas saturación por alpha: la primera cambia el color opaco y la segunda cambia su composición con un fondo.
  • No esperes que giros angulares o pasos de luminosidad iguales parezcan equidistantes; HSL no es perceptualmente uniforme.
  • No redondees HSL repetidamente para sobrescribir un RGB canónico; las conversiones fraccionarias pueden acumular deriva de canales.

Hay además una sutileza de serialización. Un navegador puede exponer el color resuelto en forma rgb() aunque el autor escribiera hsl(), porque el color usado es sRGB. En pruebas, compara canales resueltos o una representación normalizada deliberadamente, no la cadena original. Para tokens, registra si las coordenadas HSL son la fuente editable canónica o una presentación derivada y mantén esa decisión.

07

Publica tokens HSL con evidencia resuelta

Un conjunto práctico de tokens puede usar HSL sin fingir que cada paso numérico es seguro. Conserva nombres semánticos, registra coordenadas, resuelve los valores sRGB finales durante la compilación o documentación y prueba cada pareja real. El ejemplo usa blanco sobre el color de acción con luminosidad 40% porque calcula 5,57:1. El token disabled translúcido sigue necesitando un fondo conocido antes de concluir nada sobre contraste.

css
:root {
  --action: hsl(210 100% 40%);       /* #0066CC */
  --action-hover: hsl(210 100% 32%);
  --action-disabled: hsl(210 20% 55% / 60%);
  --on-action: #FFFFFF;              /* 5.57:1 on --action */
}

.action {
  color: var(--on-action);
  background: var(--action);
}

.action:hover {
  background: var(--action-hover);
}
  • Conserva un valor canónico y precisión suficiente para reproducir los canales resueltos.
  • Documenta qué coordenada puede cambiar y qué función semántica cumple el token resultante.
  • Exporta HSL listo para copiar y un HEX o RGB resuelto para revisar entre herramientas.
  • Prueba por separado pares default, hover, active, focus, selected y disabled, en temas claro y oscuro.
  • Mide el contraste con los colores finalmente compuestos y conserva la relación sin redondear en la auditoría.
  • Usa OKLCH u otro espacio adecuado cuando los pasos perceptualmente regulares importen más que los controles HSL familiares.
  • Enlaza el método de conversión y la especificación para explicar futuros cambios del generador.
S

Fuentes primarias

Las afirmaciones de este artículo se comprueban con estas especificaciones publicadas.

  1. W3C CSS Color 4 — notación HSL
  2. W3C CSS Color 4 — conversión de HSL a sRGB
  3. W3C CSS Color 4 — componentes de color sin efecto
  4. W3C CSS Color 4 — sintaxis de color moderna y antigua
  5. W3C WCAG 2.2 — luminancia relativa
  6. W3C WCAG 2.2 — Contraste (mínimo)