wandres.dev
GRADIENTES · Interpolación, ángulos y cónicos

Lineal, radial y cónico: la geometría de cada degradado

Dónde está la línea del degradado lineal y cuánto mide, los cuatro tamaños del radial y qué significan de verdad, y el ángulo de partida del cónico.

⏱ 18 min

Los tres tipos de degradado de CSS no se distinguen por su aspecto sino por la función que asigna a cada píxel su posición en la escala de colores: la proyección sobre una recta, la distancia a un punto, o el ángulo alrededor de un punto. Todo lo demás —la sintaxis de posición, los tamaños, los ángulos— sale de ahí, y cuando tienes esa función en la cabeza dejas de probar valores al azar.

🎯 Al terminar esta lección sabrás
  • Calcular dónde empieza y acaba la línea de un degradado lineal.
  • Explicar la esquina mágica de to top right y qué garantiza.
  • Elegir entre los cuatro tamaños de un degradado radial.
  • Situar el origen angular de un cónico y desplazarlo con from.

La línea del degradado lineal

Un degradado lineal define una recta que pasa por el centro de la caja con el ángulo que le indiques. Cada píxel se proyecta perpendicularmente sobre esa recta, y la posición de esa proyección decide qué color le toca.

.a { background: linear-gradient(#3364db, #09183b); }        /* to bottom */
.b { background: linear-gradient(90deg, #3364db, #09183b); } /* to right */
.c { background: linear-gradient(to top right, #3364db, #09183b); }

El valor por defecto es to bottom, equivalente a 180deg. Los ángulos se miden desde arriba y en sentido horario: 0deg es hacia arriba, 90deg hacia la derecha, 180deg hacia abajo. Es una convención distinta de la de las matemáticas y de la de rotate(), y confundirlas es el origen de la mitad de los degradados que salen del revés.

La longitud de la línea no es el ancho ni el alto de la caja. Se calcula para que el degradado cubra la caja entera, con la fórmula:

longitud = |ancho * sin(angulo)| + |alto * cos(angulo)|

En una caja de 400 por 200 con un ángulo de 45 grados, la línea mide 400 * 0.707 + 200 * 0.707, unos 424 píxeles. Por eso una parada al 50% no cae donde la intuición dice: cae en el punto medio de esa recta, no en el centro geométrico de un lado.

El caso de la esquina merece su párrafo. Cuando escribes to top right, el ángulo no es 45 grados salvo que la caja sea cuadrada: el navegador lo elige de modo que la perpendicular a la línea que pasa por el punto de inicio pase exactamente por las otras dos esquinas. Es decir, en to top right las esquinas superior izquierda e inferior derecha reciben exactamente el mismo color, el del 50%. Esa garantía es la razón de que la sintaxis de esquina exista: te da un degradado diagonal que se ve simétrico sea cual sea la proporción de la caja, cosa que un ángulo fijo no consigue.

El radial y sus tamaños

Un degradado radial asigna a cada píxel su distancia normalizada al centro, medida sobre una elipse o una circunferencia.

.a { background: radial-gradient(#fff, #000); }
.b { background: radial-gradient(circle at 30% 20%, #fff, #000); }
.c { background: radial-gradient(circle closest-side at 30% 20%, #fff, #000); }
.d { background: radial-gradient(ellipse 200px 80px at center, #fff, #000); }

El valor por defecto completo es ellipse farthest-corner at center. La forma es elipse salvo que digas circle, y su tamaño se determina con una de estas cuatro palabras:

Palabra El borde del degradado toca
closest-side el lado más cercano al centro
closest-corner la esquina más cercana
farthest-side el lado más lejano
farthest-corner la esquina más lejana, y es el valor por defecto

La diferencia se ve mejor con el centro descolocado. Con at 20% 20%, closest-side produce un círculo pequeño que toca el borde izquierdo, y farthest-corner uno grande que llega hasta la esquina inferior derecha. Con el centro en el medio y una caja no cuadrada, closest-side y farthest-side producen elipses de proporciones distintas.

También puedes dar el tamaño explícito. Una circunferencia toma un solo valor y no admite porcentajes, porque no habría forma de decidir respecto a qué dimensión. Una elipse toma dos, cada uno con su porcentaje respecto al ancho y al alto de la caja.

💡
closest-side es el que quieres para un foco

El caso más común de degradado radial es una luz suave sobre una superficie. Con farthest-corner, que es el valor por defecto, el degradado se estira hasta la esquina y en cajas anchas queda desproporcionado. radial-gradient(circle closest-side at 50% 0%, ...) produce un foco de tamaño predecible que no depende de la proporción del contenedor.

El cónico y su ángulo de partida

Un degradado cónico asigna a cada píxel el ángulo del segmento que lo une con el centro. El resultado es la rueda que gira alrededor de un punto, con una discontinuidad inevitable donde se cierra el círculo.

.a { background: conic-gradient(#3364db, #f38ba8, #3364db); }
.b { background: conic-gradient(from 90deg, #3364db, #f38ba8, #3364db); }
.c { background: conic-gradient(at 30% 70%, #3364db, #f38ba8, #3364db); }

El origen angular está arriba y el sentido es horario, igual que en el lineal. from <angle> gira ese origen; at <position> mueve el centro con la misma sintaxis que background-position.

Las paradas de un cónico se expresan en ángulos o en porcentajes, donde 100% equivale a 360deg y a 1turn. Las dos formas se pueden mezclar.

/* Un grafico de sectores de tres partes. */
.tarta {
  background: conic-gradient(
    #89b4fa 0deg 120deg,
    #a6e3a1 120deg 200deg,
    #f9e2af 200deg 360deg
  );
  border-radius: 50%;
}

Ese ejemplo enseña de paso lo más útil del cónico: es el único degradado con el que se dibuja un sector circular sin SVG. Combinado con border-radius: 50% y con un pseudoelemento que tape el centro, tienes un anillo de progreso completo en dos declaraciones.

La discontinuidad del cierre es su única pega estructural. Si el primer y el último color no coinciden, se ve una costura dura en la posición de partida. Repetir el color inicial al final, como en los ejemplos, la elimina.

Elegir por la geometría

La pregunta no es cuál queda mejor sino qué magnitud quieres representar.

Lineal cuando la variación depende de una dirección: la profundidad de una superficie iluminada desde arriba, el desvanecimiento del final de una lista, la transición entre dos zonas de la página.

Radial cuando depende de la distancia a un punto: un foco, una viñeta, el resplandor de un elemento activo, el difuminado de los bordes de una imagen.

Cónico cuando depende de un ángulo: sectores, ruedas de color, indicadores de progreso circular, y el efecto de brillo giratorio de un borde.

Los tres tienen su variante repeating-, que reinicia la escala al llegar al final en vez de mantener el último color. Es lo que produce rayas, anillos concéntricos y ruedas de sectores repetidos.

Un degradado es una imagen, y eso decide dónde puedes ponerlo y qué cuesta

La clasificación que de verdad importa no es lineal, radial y cónico: es que los tres son valores de tipo imagen, igual que un url(). De ahí sale casi todo lo que se puede y no se puede hacer con ellos, y también casi todo lo que cuesta. Como son imágenes, valen en cualquier propiedad que acepte una: background-image, border-image-source, mask-image, list-style-image y content. Como son imágenes, no tienen dimensiones intrínsecas: se estiran a lo que diga background-size, y cuando ese tamaño cambia el degradado hay que volver a rasterizarlo entero. Esa es la explicación de por qué animar el tamaño de un elemento con un degradado de fondo cuesta mucho más que animar el de uno con color plano: el color plano se rellena en el compositor, el degradado se recalcula píxel a píxel en cada fotograma en el que la caja cambia. Y como son imágenes y no colores, no se interpolan como los colores: no existe una transición entre dos degradados de la forma en que existe entre dos colores, porque interpolar dos imágenes no está definido en general. La consecuencia práctica que la gente descubre tarde es que la forma fiable de animar un degradado no es tocar la propiedad background-image, sino registrar con @property los parámetros que lo generan —un ángulo, una posición, un canal de color— y dejar que el degradado se reconstruya en cada fotograma a partir de esos números. Ahí lo que se interpola es un número, que sí está definido, y el degradado es solo su consecuencia. Es el mismo cambio de mentalidad de las custom properties: en vez de animar el resultado, animas el parámetro del que el resultado depende.

⚔️ Mide la geometría
  1. Pon un degradado lineal a 45 grados en una caja de 400 por 200 y localiza dónde cae la parada del 50%.
  2. Compara to top right con 45deg en la misma caja rectangular.
  3. Dibuja el mismo radial con los cuatro tamaños y el centro en 20% 20%.
  4. Haz un gráfico de sectores con conic-gradient y quítale la repetición del primer color para ver la costura.