Diseño

Por qué los degradados CSS se vuelven grises en el medio, y dos formas de arreglarlo

El degradado de azul a amarillo pasa por un gris muerto por aritmética, no porque tu navegador esté roto. Aquí está la aritmética, y los dos arreglos.

Un degradado CSS se vuelve gris en el medio porque el navegador mezcla tus dos colores canal por canal, en sRGB, y el punto medio entre dos tonos opuestos es neutro. Pasa del azul #0000FF al amarillo #FFFF00: el canal rojo va de 0 a 255, el canal verde de 0 a 255, el canal azul de 255 a 0. A mitad de camino, los tres quedan en 127,5, que el navegador pinta como #808080. Cambiar el ángulo no lo va a mover, porque el ángulo no es lo que lo decide.

Ese es todo el mecanismo, y los arreglos salen directamente de ahí. O le das a la mezcla una parada por la que pasar, o le dices al navegador que interpole en un espacio que no sea sRGB.

Qué pares de colores se vuelven grises

Los que están más o menos opuestos en la rueda de color, porque son los pares cuyos canales se cancelan. El tono se mide en grados alrededor de la rueda, así que la distancia entre tus dos extremos predice el daño antes de que renderices nada.

DegradadoDistancia de tonoPunto medio en sRGBLo que ves
#0000FF#FFFF00180°#808080Gris medio muerto
#00FFFF#FF0000180°#808080Gris medio muerto
#FF00FF#00FF00180°#808080Gris medio muerto
#FF0000#00FF00120°#808000Verde oliva militar oscuro
#6D5EFC#22D3EE58°#4899F5Un azul limpio

La última fila es de la que hay que aprender. Dos tonos separados por un trecho corto nunca pasan cerca del eje neutro, así que no se drena nada del medio. Por eso tantos degradados que se ven bien en sitios reales resultan ser dos colores que son casi el mismo color. Pon los dos extremos en el generador de degradados y cambia un extremo por un tono vecino: el medio se vuelve a llenar a medida que se cierra la distancia, y puedes ver el punto exacto en el que deja de ser barro.

El gris es solo el fallo más escandaloso, no el general. El par de 120° no se vuelve gris, se vuelve oscuro: el rojo y el verde están los dos al 50% de luminosidad, y el oliva #808000 está al 25%. Del azul al amarillo se pierde lo contrario — mantiene su 50% de luminosidad de punta a punta y tira por la borda toda la saturación. Lo que garantiza la aritmética es que el punto medio es lo que sea que produzca promediar los canales, y cuanto más separados estén los extremos, menos se parecerá eso a cualquiera de los dos.

Arreglo 1: dale a la mezcla algún lugar al que ir

Agrega una tercera parada en un tono que de verdad quieras, y el navegador interpola dos veces sobre una distancia más corta cada vez, en lugar de una sola vez por el medio de la nada.

El azul está en 240° de la rueda y el amarillo en 60°, lo que hace que las dos rutas midan exactamente lo mismo. Por el verde, el tono del punto medio es 150° — #00FF80. Por el magenta, es 330° — #FF0080. Elige la que pertenezca a tu diseño:

background-image: linear-gradient(90deg, #0000FF, #00FF80, #FFFF00);

Esto funciona en cualquier cosa que entienda linear-gradient, que es todo navegador con el que te vayas a cruzar. El problema es que ahora tienes dos rampas en lugar de una, y si la luminosidad de la parada del medio queda por encima o por debajo de la de ambos extremos, te sale una banda clara u oscura visible justo donde estabas tratando de arreglar las cosas. Elige la parada del medio en HSL para poder mantener fijas la saturación y la luminosidad y mover solo el tono, y luego conviértela de vuelta a hex para la hoja de estilos. Ese es el único trabajo en el que HSL es realmente mejor que hex, y vale la pena conocer las ventajas y desventajas entre hex, RGB y HSL antes de ajustar a mano una rampa de color.

Una advertencia si vas a agregar la parada en el generador de aquí en lugar de a mano: una parada nueva llega con el color del promedio de canales de sus dos vecinas. Para el azul y el amarillo ese promedio es #808080 — la herramienta te entrega exactamente el gris del que viniste a deshacerte. Cámbiale el color con la muestra. El control deslizante de posición solo mueve dónde está la parada, no lo que es.

El porcentaje que no ayuda

Un porcentaje suelto entre dos colores es una pista de interpolación de color. Mueve el punto en el que los dos colores están mezclados 50/50:

background-image: linear-gradient(90deg, #0000FF, 30%, #FFFF00);

La gente recurre a esto cuando el medio se ve mal, y no arregla nada. La mezcla sigue recorriendo el mismo camino por el espacio de color, así que el gris sigue ahí — solo que ahora llega al 30% en lugar de al 50%. Una pista cambia el ritmo de la mezcla. No puede cambiar por dónde va la mezcla.

Arreglo 2: interpola en otro espacio de color

El CSS moderno te deja nombrar el espacio en el que el navegador mezcla, justo al lado del ángulo:

background-image: linear-gradient(90deg in oklch, #0000FF, #FFFF00);

Dos paradas, sin barro. OKLCH es un espacio polar: luminosidad, croma, tono. Interpolar en él rota el tono alrededor de la rueda mientras el croma se mueve en línea recta entre los dos extremos, así que el medio se mantiene como un color saturado en lugar de colapsar hacia el neutro. También reparte la luminosidad de manera uniforme de una forma que coincide con cómo funciona el ojo y no con cómo caen los números de sRGB, que es la razón por la que el resultado suele verse más suave incluso cuando el gris nunca fue el problema.

La advertencia honesta es el gamut. El azul hacia el amarillo en OKLCH pide un punto medio con aproximadamente el doble del croma que una pantalla sRGB puede producir a esa luminosidad y ese tono, así que el navegador lo mapea de vuelta dentro del gamut. Obtienes un medio saturado. No obtienes el que describen los números.

Por defecto el navegador toma el camino corto alrededor de la rueda. Agrega longer hue para mandarlo por el otro lado y que barra todo lo que hay en medio, que es como se consigue un arcoíris a partir de dos paradas:

background-image: linear-gradient(90deg in oklch longer hue, #0000FF, #FFFF00);

¿OKLAB u OKLCH?

OKLAB es el mismo modelo de color en coordenadas rectangulares: luminosidad más dos ejes. Mezclar en él arregla la caída de luminosidad que hace que los degradados en sRGB se vean sucios, y para la mayoría de los pares de colores con eso basta. Pero una línea recta trazada entre dos tonos opuestos pasa cerca del eje neutro en cualquier espacio rectangular, así que para extremos genuinamente complementarios el punto medio de OKLAB sigue teniendo poco croma — más claro y mejor comportado que #808080, pero no vivo. Si mantener el color arriba a lo largo del medio es todo el objetivo, usa OKLCH y deja que tome la rueda de tonos.

El fallback que tienes que escribir tú

Un navegador viejo no ignora la parte in oklch y sigue adelante. Falla al parsear el valor, lo que invalida la declaración entera, y entonces no tienes ningún degradado. El arreglo es el truco estándar de la cascada de CSS — pon la versión simple primero y la versión mejorada segunda:

background-image: linear-gradient(90deg, #0000FF, #00FF80, #FFFF00);
background-image: linear-gradient(90deg in oklch, #0000FF, #FFFF00);

Cualquier cosa que entienda la segunda línea la usa. Cualquier cosa que no, se queda con la primera. El soporte para espacios de interpolación ya es amplio, así que esto es un seguro más que una restricción real — pero no puedes ver qué están usando tus visitantes, y el modo de fallo es un fondo en blanco en lugar de un degradado simple. Cuesta una línea.

Por qué un desvanecido a transparente también puede verse gris

Este tiene una causa distinta y agarra desprevenida a gente que ni siquiera está mezclando dos tonos. En CSS, transparent no es «nada» — está definido como negro transparente, rgba(0, 0, 0, 0). Por lo tanto, una mezcla ingenua de blanco a transparent lleva el color hacia el negro mientras el alpha va hacia cero, y el medio sale como una neblina gris sobre lo que sea que haya detrás.

La especificación exige que los navegadores interpolen con alpha premultiplicado, lo que evita esto, y los motores actuales lo hacen. Si aun así estás viendo el fantasma — en un motor más viejo, o en algo que renderiza CSS pero no es un navegador — escribe la versión explícita con alpha cero de tu propio color en lugar de la palabra clave:

background-image: linear-gradient(180deg, #FFFFFF, #FFFFFF00);

No cuesta nada, no es ambiguo, y se lee mejor que transparent de todos modos, porque quien lo lee ve qué color se está desvaneciendo.

¿Neblina gris o rayas grises? No es el mismo bug

Si el medio no está desteñido sino rayado — bandas visibles que avanzan a saltos por una mezcla suave — eso es banding, y ninguno de los arreglos de arriba lo toca. Ocho bits por canal dan 256 valores. Estira un degradado sutil a lo largo de 1200 píxeles y hay muchos más píxeles que colores distintos para llenarlos, así que la transición llega en escalones que puedes contar. Aumenta la distancia de color entre las paradas, reduce el área, o pon encima una textura de ruido muy tenue. Los navegadores aplican algo de dither y de forma inconsistente, así que el mismo degradado puede tener banding en una máquina y verse limpio en la siguiente.

El diagnóstico rápido: un medio turbio se ve igual a cualquier tamaño y en cualquier pantalla, porque es aritmética. El banding cambia cuando redimensionas el elemento, porque es cuantización.

Qué hacer la próxima vez, antes de que se ponga gris

Decide la ruta del tono antes de elegir los dos extremos. Si el encargo te entrega dos colores complementarios, estás eligiendo entre tres resultados: una tercera parada que se compromete con un lado de la rueda, una mezcla en OKLCH que se compromete por ti, o un medio gris. No hay una cuarta opción en la que sRGB haga discretamente lo correcto. Los degradados construidos con tonos separados por menos de unos 60° nunca plantean la pregunta, que es gran parte de por qué los colores análogos aparecen una y otra vez como la recomendación segura en las guías para construir una paleta de colores que se sostenga.

La forma más rápida de ver todo esto es poner los dos extremos en el generador de degradados CSS, agregar una tercera parada y elegir su color hasta que se aclare el barro — la vista previa es tu propio navegador renderizando la misma línea que estás a punto de pegar, así que no se está aproximando nada. Escribe sRGB simple en una sola capa, así que si quieres la versión OKLCH copias el CSS y le agregas in oklch después del ángulo tú mismo.

Elegir esa parada del medio es un problema de color más que de CSS, y va mucho más rápido en HSL que en hex. Hex, RGB y HSL explicados cubre qué formato te deja mantener un color fijo mientras mueves una sola propiedad suya, y en qué te va a engañar la idea de luminosidad que tiene HSL.

Preguntas frecuentes

¿Por qué mi degradado CSS se ve gris en el medio?

Los navegadores mezclan las paradas de un degradado en sRGB, canal por canal. Cuando los dos colores están en lados opuestos de la rueda de color, cada canal termina promediado cerca de la mitad de su rango, así que el punto medio queda cerca del gris neutro. Del azul al amarillo se cae en #808080.

¿Cómo evito que un degradado CSS se vuelva gris?

Agrega una tercera parada en un tono por el que quieras que pase la mezcla, o interpola en otro espacio de color con linear-gradient(90deg in oklch, ...). La tercera parada funciona en todos los navegadores; la versión OKLCH se queda con dos paradas y necesita encima una declaración simple de fallback.

¿Qué hace «in oklch» en un degradado CSS?

Le dice al navegador que mezcle en OKLCH y no en sRGB. OKLCH es polar, así que el tono rota alrededor de la rueda de color en lugar de que la mezcla la corte por el medio, lo que impide que el punto medio colapse hacia el gris. Agregar «longer hue» manda la mezcla por el otro lado de la rueda y da un arcoíris.

¿Qué es mejor para degradados, OKLAB u OKLCH?

OKLAB arregla la luminosidad despareja y sirve para la mayoría de los pares de colores. Para dos tonos casi complementarios, OKLAB igual desatura en el medio, porque una línea recta entre tonos opuestos pasa cerca del eje neutro en cualquier espacio de color rectangular. OKLCH rota el tono en lugar de eso y mantiene el color arriba.

¿Por qué un degradado que se desvanece a transparente se ve gris?

La palabra clave transparent de CSS significa negro transparente, rgba(0, 0, 0, 0), así que una mezcla ingenua se oscurece hacia el negro mientras se desvanece. Los navegadores actuales interpolan con alpha premultiplicado y lo evitan. Si aun así ves una neblina gris, escribe la versión con alpha cero de tu propio color, como #FFFFFF00, en lugar de la palabra clave.

¿Cuál es la diferencia entre un degradado turbio y uno con bandas?

Un medio turbio es un color desaturado causado por las matemáticas de la interpolación en sRGB, y se ve idéntico a cualquier tamaño. El banding son rayas visibles causadas por tener solo 256 valores por canal a lo largo de un área grande, y cambia cuando redimensionas el elemento.

Última actualización 19 de septiembre de 2026