wandres.dev
FONDOS Y BORDES · Capas, repetición y radios

El modelo de capas de background y el orden de pintado

Por qué la primera capa que escribes es la que queda arriba, dónde vive el color de fondo, y cómo se rellenan las listas cuando no tienen la misma longitud.

⏱ 17 min

background no es una propiedad: son ocho, y todas menos una aceptan una lista de valores separados por comas que define capas independientes. Ese modelo convierte un elemento en un lienzo de composición sin pseudoelementos ni marcado extra, y trae dos reglas contraintuitivas —el orden de pintado invertido y el reciclado de listas cortas— que explican casi todos los fondos que salen mal.

🎯 Al terminar esta lección sabrás
  • Enumerar las propiedades que forman una capa de fondo.
  • Predecir qué capa queda encima cuando hay varias.
  • Situar background-color en el orden de pintado y saber dónde declararlo.
  • Aplicar la regla de reciclado cuando las listas tienen longitudes distintas.

Qué forma una capa

Una capa de fondo es la combinación de siete propiedades que se aplican a una imagen:

Propiedad Qué controla
background-image La imagen o degradado de la capa
background-position Dónde se ancla dentro del área de posicionamiento
background-size Cuánto mide
background-repeat Si y cómo se repite
background-origin Cuál es el área de posicionamiento
background-clip Hasta dónde se pinta
background-attachment Respecto a qué se fija

La octava, background-color, es distinta: no acepta lista. Hay un solo color de fondo por elemento, y siempre se pinta debajo de todas las capas de imagen.

Cuando escribes varias imágenes separadas por comas, cada una crea una capa, y las siete propiedades restantes se emparejan por posición con esas imágenes.

.superficie {
  background-image:
    radial-gradient(circle closest-side, #ffffff30, transparent),
    linear-gradient(in oklab to bottom, #1e1e2e, #11111b);
  background-position: 20% 0, center;
  background-size: 60% auto, cover;
  background-repeat: no-repeat, no-repeat;
  background-color: #11111b;
}

El orden de pintado

Esta es la regla que sorprende: la primera capa de la lista es la que queda más cerca del lector. Las siguientes se pintan debajo, en orden, y el color de fondo queda al final del todo.

flowchart TB
A[Mas cerca del lector] --> B[Borde del elemento]
B --> C[Capa 1 la primera de la lista]
C --> D[Capa 2]
D --> E[Capa 3 la ultima de la lista]
E --> F[background-color siempre al fondo]
F --> G[Lo que haya detras del elemento]
style B fill:#cba6f7,color:#11111b
style C fill:#89b4fa,color:#11111b
style D fill:#89b4fa,color:#11111b
style E fill:#89b4fa,color:#11111b
style F fill:#94e2d5,color:#11111b

Es el mismo orden que un z-index implícito y decreciente, y es el contrario del que usa box-shadow, donde la primera sombra de la lista también va encima, pero también el contrario de lo que hace la mayoría de la gente al escribir: se tiende a listar del fondo hacia arriba, como se apilan las capas en un editor gráfico, y sale al revés.

La regla mnemotécnica que funciona: lo que escribes primero es lo que ves primero. El brillo va arriba en el código porque va arriba en la pantalla; la base va al final.

El borde se pinta por encima de todas las capas de fondo, lo cual importa cuando el borde es semitransparente: verás el fondo a través de él.

Dónde va el color

En la forma larga, background-color es una propiedad aparte y se puede declarar donde quieras. En la forma abreviada hay una restricción sintáctica: el color solo se puede escribir en la última capa de la lista.

/* Valido: el color va en la ultima capa. */
.a {
  background:
    radial-gradient(circle, #ffffff20, transparent) no-repeat,
    linear-gradient(in oklab, #1e1e2e, #11111b) #11111b;
}

/* Invalido: el color en la primera capa. */
.mal {
  background:
    #11111b radial-gradient(circle, #ffffff20, transparent),
    linear-gradient(in oklab, #1e1e2e, #11111b);
}

La razón es que el color no es una propiedad de capa, así que la gramática necesita un sitio único e inequívoco donde ponerlo, y eligió el final. En la práctica es más legible declararlo aparte:

.a {
  background-color: #11111b;
  background-image:
    radial-gradient(circle, #ffffff20, transparent),
    linear-gradient(in oklab, #1e1e2e, #11111b);
  background-repeat: no-repeat;
}
⚠️
La abreviada resetea el color aunque no lo menciones

background: url(patron.png) pone background-color a transparent, porque la abreviada asigna el valor inicial a todas las propiedades que no menciona. Si antes había un color de fondo declarado con menor prioridad, desaparece. Es el fallo más común al mezclar la forma abreviada con la larga en la misma hoja.

El reciclado de listas

Las listas de las siete propiedades de capa no tienen por qué medir lo mismo que la de imágenes, y la regla de ajuste es asimétrica:

Si una lista es más corta, se recicla desde el principio. Con tres imágenes y background-repeat: no-repeat, repeat, la tercera imagen usa no-repeat, porque se vuelve al primer valor.

Si una lista es más larga, sobra y se ignora. Con dos imágenes y cuatro posiciones, las dos últimas posiciones no hacen nada. No es un error y no avisa.

El reciclado se aprovecha para no repetir:

.tres-capas {
  background-image: url(a.avif), url(b.avif), url(c.avif);
  background-repeat: no-repeat;      /* las tres */
  background-size: contain;          /* las tres */
  background-position: left, center, right;
}

Y es también el origen de errores muy difíciles de ver: si añades una cuarta imagen a un fondo con tres posiciones, la cuarta hereda la posición de la primera sin que nada indique que ha pasado.

El fondo se pinta dentro del elemento, y por eso no compone con nada de fuera

Hay una diferencia estructural entre apilar capas de background y apilar elementos, y entenderla decide cuándo puedes usar una y cuándo necesitas la otra. Las capas de fondo de un elemento se componen entre sí y sobre el color de fondo, y esa composición ocurre en un paso del pintado de ese elemento que es anterior a que el elemento se componga con la página. La consecuencia inmediata es que background-blend-mode, que mezcla las capas entre ellas, nunca ve lo que hay detrás del elemento: puede multiplicar la capa 1 sobre la capa 2, y no puede multiplicar la capa 2 sobre el fondo del padre. Para eso hace falta mix-blend-mode, que actúa sobre el elemento entero y sí ve el fondo. Son dos propiedades con nombres casi idénticos que operan en fases distintas del pipeline, y confundirlas produce el clásico “he puesto multiply y no hace nada”. La segunda consecuencia es de rendimiento y es la que decide arquitecturas: como las capas de fondo se componen dentro del pintado del elemento, cualquier cambio en cualquiera de ellas invalida el mapa de píxeles del elemento entero y obliga a repintar todas las capas, no solo la que cambió. Si tienes cuatro capas y quieres animar la opacidad de una, no puedes: background no tiene opacidad por capa, y aunque la simules metiendo alfa en el color estás repintando las cuatro en cada fotograma. Ahí es donde el pseudoelemento deja de ser un apaño y pasa a ser la solución correcta: un ::before con su propia capa es un elemento independiente, se rasteriza una vez, y su opacity la resuelve el compositor sin tocar nada más. La regla que se deduce: usa capas de fondo para lo estático y elementos para lo que cambie. Cuatro capas quietas en un elemento son gratis; una sola capa que se anima dentro de un fondo compuesto es cara, y sacarla a su propio elemento la vuelve gratis otra vez.

⚔️ Ordena las capas
  1. Apila tres degradados en un elemento y comprueba cuál queda arriba.
  2. Escribe la misma composición con la forma abreviada y coloca el color en el sitio correcto.
  3. Declara cuatro imágenes con dos posiciones y localiza el reciclado en el inspector.
  4. Pon un background: url(...) después de un background-color y observa cómo desaparece el color.