wandres.dev
COLOR I · sRGB, gamma y el problema

La mezcla que sale mal

El mismo 50% en cuatro espacios con sus números, los cuatro sitios de una interfaz donde la diferencia se nota, y cómo elegir el espacio a conciencia.

⏱ 16 min

color-mix() recibe el espacio de interpolación como primer argumento, y eso no es un detalle de sintaxis: es la especificación admitiendo que no existe la mezcla de dos colores, sino una por cada criterio. Cambiar ese argumento cambia el resultado de forma drástica, y la mayoría de las paletas generadas automáticamente lo dejan en el valor por defecto sin haberlo pensado nunca.

🎯 Al terminar esta lección sabrás
  • Escribir una mezcla eligiendo el espacio de interpolación de forma explícita.
  • Comparar el resultado del mismo 50% en cuatro espacios distintos.
  • Reconocer los cuatro puntos de una interfaz donde la elección se nota.
  • Elegir el método de interpolación de tono en espacios polares.

color-mix y el espacio como argumento

.a { background: color-mix(in srgb,        #0000ff, #ffff00); }
.b { background: color-mix(in srgb-linear, #0000ff, #ffff00); }
.c { background: color-mix(in oklab,       #0000ff, #ffff00); }
.d { background: color-mix(in hsl,         #0000ff, #ffff00); }

Sin porcentajes, la mezcla es al 50%. Con ellos, color-mix(in oklab, #0000ff 30%, #ffff00) toma el 30% del primero. Los espacios disponibles incluyen srgb, srgb-linear, lab, lch, oklab, oklch, xyz, hsl y hwb.

Los degradados aceptan el mismo argumento con la misma sintaxis, y por la misma razón.

El mismo 50% en cuatro espacios

Tomando de nuevo azul puro y amarillo puro, cuyas luminancias son 0.0722 y 0.9278:

espacio resultado luminancia qué criterio aplica
srgb #808080 0.216 media de los valores codificados
srgb-linear #bcbcbc 0.500 media de la luz emitida
oklab gris azulado, claridad 0.71 ~0.36 punto medio perceptual
hsl verde saturado variable media del ángulo de tono

Las tres primeras filas salen de los números de la función de transferencia. La cuarta merece explicación: en HSL, el azul está en 240 grados y el amarillo en 60, así que la interpolación recorre el ángulo entre ellos y pasa por los verdes en 150. El resultado ni siquiera es un gris: es un verde saturado que no está en ninguno de los dos extremos. Mezclar en un espacio polar sin entenderlo produce colores que aparecen de la nada.

La fila de oklab es la que corresponde a “el color que parece estar a la misma distancia visual de los dos”. Su claridad es la media de las claridades perceptuales de los extremos, y conserva un resto de croma azulado porque el camino entre los dos colores en ese espacio no pasa exactamente por el neutro.

Los cuatro sitios donde se nota

Las rampas de una paleta. Generar diez tonos mezclando la marca con blanco y con negro es la operación más común de un sistema de diseño, y en srgb produce una rampa cuyos pasos no son perceptualmente iguales: los tonos claros se amontonan y los oscuros dan saltos. La prueba visual es poner la rampa al lado de una escala de grises equivalente y comparar dónde caen los escalones.

:root {
  --marca: #3b5bdb;
  /* pasos perceptualmente regulares */
  --marca-100: color-mix(in oklab, var(--marca) 12%, white);
  --marca-300: color-mix(in oklab, var(--marca) 40%, white);
  --marca-500: var(--marca);
  --marca-700: color-mix(in oklab, var(--marca) 70%, black);
  --marca-900: color-mix(in oklab, var(--marca) 40%, black);
}

Los estados derivados. El clásico “el hover es un 10% más oscuro” aplicado a botones de distintos colores da resultados desiguales en srgb: el mismo 10% oscurece mucho un amarillo y casi nada un azul, porque parten de luminancias muy distintas. En un espacio perceptual, el mismo 10% se percibe como el mismo cambio en todos los tonos.

Los degradados de marca. Un degradado entre dos colores corporativos casi siempre queda mejor in oklab, porque no atraviesa la zona muerta central. Es el cambio de una palabra con el mayor retorno visual de todo este tramo.

Las mezclas con transparencia. color-mix() con un color translúcido interpola también el alfa, y el espacio elegido afecta al componente de color pero no al alfa. Conviene comprobarlo cuando el resultado se compone sobre fondos distintos.

Elegir el método de tono

En los espacios polares —hsl, lch, oklch— hay dos ángulos posibles entre dos tonos, y CSS deja elegir cuál se recorre:

.a { background: linear-gradient(in oklch shorter hue,     #e11d48, #0ea5e9); }
.b { background: linear-gradient(in oklch longer hue,      #e11d48, #0ea5e9); }
.c { background: linear-gradient(in oklch increasing hue,  #e11d48, #0ea5e9); }
.d { background: linear-gradient(in oklch decreasing hue,  #e11d48, #0ea5e9); }

shorter hue es el valor por defecto y recorre el arco corto. longer hue recorre el largo, que es lo que quieres si el efecto buscado es un arcoíris entre dos colores próximos. increasing y decreasing fuerzan el sentido, y sirven cuando dos degradados adyacentes deben girar en el mismo sentido para que la composición sea coherente.

Esta opción solo tiene sentido en espacios polares; en oklab, srgb o srgb-linear no hay ángulo que recorrer.

⚠️
Mezclar en hsl casi nunca es lo que quieres

hsl está en la lista de espacios admitidos por compatibilidad, no porque sea una buena elección. Su interpolación recorre un ángulo de tono, lo que hace aparecer colores intermedios que no están en ninguno de los extremos, y su eje de claridad no corresponde a la claridad percibida. Si el resultado de una mezcla te sorprende y estabas en hsl, el espacio es la primera causa a descartar.

El espacio de interpolación era una decisión tomada en 1996 y ahora es tuya

Durante veinticinco años, la pregunta “¿en qué espacio se mezclan estos dos colores?” no tenía respuesta en CSS porque no había pregunta: se mezclaban en sRGB codificado y punto. Toda una generación de sistemas de diseño se construyó sobre ese valor por defecto, y por eso los diseñadores desarrollaron el hábito de elegir a mano cada tono de cada rampa en lugar de derivarlos: no era una preferencia estética, era la consecuencia práctica de que la derivación automática daba resultados irregulares y había que corregirlos uno a uno. Ahora el espacio es un argumento, y eso cambia el trabajo más de lo que parece: una rampa derivada en un espacio perceptual es correcta por construcción, se puede regenerar para cualquier color de marca, y no necesita el ajuste manual que hacía imposible tener temas personalizables de verdad. La consecuencia interesante no es que los degradados se vean mejor, es que un tipo entero de trabajo manual deja de hacer falta. Y hay una moraleja más general, que se repite cada vez que una plataforma expone una decisión que antes estaba enterrada: cuando algo pasa de ser un valor por defecto invisible a ser un argumento, aparece de golpe una capa de calidad que no era alcanzable a base de esfuerzo. La respuesta correcta no es aprender a usar el argumento nuevo, es preguntarse qué prácticas de tu equipo existían solo para compensar el valor por defecto antiguo.