Introducción a Cascade Layers
Tabla de contenido
Cascade Layers es una manera de organizar los estilos de nuestras aplicaciones separándolos por capas que se apilan unas sobre otras para componer con más control.

Son capas independientes pero permeables, con su propia cascada y lógica de especificidad, que se apilan unas sobre otras, lo que nos permite mantener nuestro código más estructurado, ordenado y fácil de localizar.
Es como si dividiésemos nuestro CSS en diferentes hojas de estilo y las incluyésemos en el documento una a continuación de la anterior con la etiqueta <link>
o <style>
, pero con un funcionamiento diferente por las reglas de especificidad propias de las capas.
En realidad, ya trabajamos con el concepto de capas como estilos que se apilan, puesto que los estilos que los desarrolladores (autores) creamos, además de las preferencias del usuario, se aplican encima de los estilos que los navegadores dan a las etiquetas HTML.


Pero con Cascade Layers vamos a tener un control más fino, flexible y granular ya que podremos organizarlos en orden de importancia, de manera que los estilos más específicos tengan prioridad sobre los estilos más generales.
Qué problemas resuelven
- Organización de los estilos según abstracciones representativas.
- Facilita sobrescribir estilos.
Al poder separar nuestros estilos en capas podemos organizarlos mejor, de forma más intuitiva y con un control más fino. Además, nos facilita la tarea del viejo y conocido problema de sobrescribir estilos lidiando con la especificidad, por lo que es una solución perfecta para trabajar en grandes proyectos.
Qué problemas persisten
- La encapsulación nativa de estilos
Las capas son permeables, no hay encapsulación y, por lo tanto, unas pueden sobrescribir a otras, lo que nos puede llevar a obtener resultados no deseados si dejamos de prestar atención a la hora de escribir nuestras clases. Es por eso que BEM (por poner un ejemplo de nomenclatura) sigue siendo un enfoque muy útil para evitar colisiones.
La encapsulación de estilos por componentes está resuelta, por ejemplo, cuando utilizamos frameworks de desarrollo que traen consigo CSS modules o CSS-in-JS, pero estas soluciones pueden llevarnos a un exceso de confianza y a repetir nombres de clases en diferentes componentes. Por lo tanto, hay que recordar que al no existir (todavía) encapsulación nativa de CSS (salvo que usemos web components), debemos siempre prestar atención al escribir nuestras clases y elegir una metodología común para el equipo.
Cómo trabajar con capas
Creando las capas
Las capas se declaran creando un nuevo bloque de estilos utilizando la directiva @layer
y pueden ser anónimas o tener nombre.
/* Capa anónima */
@layer {
p {
color: red;
}
@media (min-width: 457px) {
a {
color: pink;
}
}
}
/* Capa con nombre */
@layer layout {
.container {
width: max(100%, 60rem);
}
}
Ordenando las capas
Una vez creadas las capas, el orden de aparición es importante, ya que la última capa tiene mayor relevancia y sobrescribirá a la anterior. Hasta ahora, es el funcionamiento esperado ya que es como se comporta CSS.
<div class="rectangle"></div>
/* menor relevancia */
@layer default {
.rectangle {
background-color: coral;
}
}
/* mayor relevancia */
@layer theme {
.rectangle {
background-color: lime;
}
}
En el ejemplo anterior, .rectangle
será de color lime
. Sin embargo, el orden de apilamiento puede ser alterado si lo declaramos utilizando @layer
seguido (y separado por comas) de los nombres de las capas creadas, siendo la primera la de menor relevancia y la última la de mayor. Es conveniente que esta declaración se produzca al principio del documento.
<div class="rectangle"></div>
@layer default, theme
@layer theme {
.rectangle {
background-color: lime;
}
}
@layer default {
.rectangle {
background-color: coral;
}
}
En este caso, .rectangle
seguirá siendo lime
porque al ordenarlas theme ha sido declarada después que default
. De esta manera, podemos controlar el estilado final reordenando las capas sin tener que confiar en el orden en el que fueron escritas.
Fusionando capas
Los nombres de las capas pueden repetirse, pero hay que tener en cuenta que el navegador las fusionará entre sí para formar una única capa.
@layer theme {
.rectangle {
background-color: lime;
}
}
/* 500 líneas de CSS después */
@layer theme {
.rectangle {
background-color: coral;
border: 1px solid;
}
}
Así en el ejemplo anterior, .rectangle
será de color coral
y tendrá un borde de un 1px
.
Anidando capas
Las capas se pueden anidar, por lo tanto podemos establecer relaciones lógicas y semánticas entre ellas, y referenciarlas para modificarlas o extenderlas más adelante.
@layer theme {
@layer base {
.rectangle {
padding: 1rem;
}
}
}
/* ... */
@layer theme.base {
.rectangle {
padding: 0 1rem;
color: white;
}
}
Importando ficheros externos a capas
Una funcionalidad muy interesante es la de poder envolver ficheros enteros en capas para poder organizarlas mejor. Podríamos por ejemplo, envolver librerías de terceros y declararlas con una relevancia media o baja para que las próximas capas puedan sobrescribir sus estilos fácilmente, siempre que no contengan !important
.
@import url(https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.2/css/bootstrap.min.css)
layer(bootstrap);
@layer default, reset, bootstrap, components, theme;
Importando CSS externo usando
Actualmente no se puede envolver un archivo en una capa usando la etiqueta <link>
, sin embargo ya existe una propuesta formal de Miriam Suzanne para que se incluya como funcionalidad. En este momento la importación se hace usando @import
pero estas regla es bloqueante, ya que mientras se resuelve la petición la carga de la página queda bloqueada, mientras que <link>
no bloquea la lectura del código por el navegador.
<!-- styles imported into to the <layer-name> layer -->
<link rel="stylesheet" href="example.css" layer="<layer-name>">
<!-- styles imported into to a new anonymous layer -->
<link rel="stylesheet" href="example.css" layer>
<!-- with fallback for old browsers -->
<link rel="stylesheet" layer="bootstrap" media="supports(at-rule(@layer))" href="bootstrap.css">
Cómo se relacionan las capas con el resto de estilos
Los estilos que renderiza el navegador son el resultado de su proceso interno de ordenamiento según su relevancia, lo que llamamos cascada.
La cascada toma una lista desordenada de valores declarados para una propiedad de un elemento concreto, los ordena según su precedencia y devuelve un único valor. - W3C
Los navegadores siguen este esquema (simplificado) para determinar la cascada:
- Origen e importancia (a. Estilos del navegador, b. Preferencias del usuario, c. Estilos del autor (desarrollador) - Estilos con
!important
) - Contexto
- Estilos declarados mediante el atributo
style
- Capas
- Especificidad de los selectores
- Orden de aparición en el código
La especificidad en las capas
Dentro de una capa, la especificidad funciona tal y como estamos acostumbrados. Los selectores más específicos van a sobrescribir a los menos específicos.
Si dudas de la especificidad de los selectores, echa un vistazo a esta calculadora.
Sin embargo, si usamos cascade layers no importa cómo de específico sea un selector si en alguna capa posterior se le aplican estilos diferentes, aunque sea con un selector menos específico.
<section id="my-id" class="my-class">...</section>
@layer theme {
section#my-id.my-class {
padding: 1rem;
background: teal;
}
}
@layer overrides {
section {
color: white;
background: coral;
}
}
En este ejemplo, a pesar de que el selector de la capa theme
tiene un peso (1, 1, 1) y el de la capa overrides
sólo (0, 0 , 1) el color de fondo será coral
porque la capa overrides
está declarada después 🤯.
Una vez que se evalúan las capas y una es la “ganadora” no se continua evaluando la especificidad o el orden de aparición para el resto de las capas, así que no necesitarás volver a preocuparte si un selector se repite en diferentes capas y tiene diferente especificidad.
Estilos declarados fuera de una capa
Por otro lado, un factor a tener en cuenta es que las capas tienen menor relevancia que los estilos declarados fuera de ellas, aunque estén escritos antes que las capas, y es porque los estilos fuera de las capas se interpretan como parte de una última capa final, y por eso prevalecen.
<section id="my-id" class="my-class">...</section>
section {
background: aqua;
}
@layer theme {
section#my-id.my-class {
padding: 1rem;
background: teal;
}
}
@layer overrides {
section {
color: white;
background: coral;
}
}
En el ejemplo anterior, el color de fondo de section
es aqua
a pesar de lo poco específico de su selector e incluso de estar declarado antes que las capas.
!important
Por último, hay que tener en cuenta que una capa con menor relevancia pero que contenga un valor para una propiedad con !important
prevalecerá. Es decir, tendrá más peso que una capa más relevante, anulando el funcionamiento que hemos descrito hasta ahora.
Así que, la primera capa (y menos relevante) con un !important
sobrescribirá capas posteriores, no importa si en ellas también se utiliza !important
para intentar sobrescribir la capa anterior. Dado este comportamiento, una idea interesante es la declarar aquellos valores que no queremos que sean sobrescritos lo más próximo al inicio del documento.
<section id="my-id" class="my-class">...</section>
@layer defaults, theme, overrides;
@layer defaults {
section {
background: lime !important;
}
}
section {
background: aqua !important;
}
@layer theme {
section#my-id.my-class {
background: teal !important;
}
}
@layer overrides {
section {
background: coral !important;
}
}
En el ejemplo anterior, el color de fondo de section será lime
.
Soporte
De acuerdo a caniuse, el soporte es casi total, así que podemos utilizarlo sin problema.
Cómo usarlo en proyectos reales
Cascade Layers encaja perfectamente en cualquier tipo de proyecto, y no necesariamente tiene que ser un proyecto exclusivo con este enfoque, puedes añadir alguna capa a tu proyecto con CSS habitual, pero puede ser especialmente adecuado para tareas concretas como:
- Escribir hojas de estilo tipo reset o estilos base de la aplicación
- Sobrescribir librerías frameworks de CSS o librerías de terceros
- Agrupar estilos por componentes
- Aplicar temificados
- Crear modo oscuro y modo claro
- Agrupar estilos para los estados de algunos elementos
@layer button, states;
@layer button {
.button {
padding: 1rem;
border: 0;
color: #282828;
background-color: #36f5bf;
}
}
@layer states {
:hover {
color: #fff;
background-color: transparent;
}
:focus-visible {
outline: max(2px, 0.08em) solid currentColor;
outline-offset: 0.25rem;
}
}
Conclusión
Aunque no resuelve la encapsulación, es una herramienta muy útil para gestionar los estilos de tus aplicaciones.
Sin embargo, hay ciertas reglas sobre la revelancia de las capas que hay que tener en mente para evitar resultados inesperados, ya que al principio puede costar el cambio de mentalidad y depurar los estilos cuando existen capas anidadas.
Enlaces de interés
- Especificación
- Soporte en caniuse
- Artículo en developer.chrome
- Artículo en bram.us
- Artículo en smashing magazine
- La imagen del artículo es una foto de Clark Van Der Beken en Unsplash.
Si te ha parecido interesante
Tanto si tienes alguna duda o te apetece charlar sobre este tema, así como si el contenido te parece interesante o crees que pdemos hacer algo juntos, no dudes en ponerte en contacto con nosotros a través del email hola@mamutlove.com