El problema de la cascada tradicional
Cualquiera que haya mantenido un proyecto CSS grande conoce la frustración de la cascada. Un estilo definido en un framework sobrescribe el nuestro, añadimos un selector más específico para ganar peso, el framework actualiza algo y todo se rompe de nuevo. El resultado es una escalada de especificidad, clases encadenadas como .contenedor .boton.primario[type=submit], y abuso de !important para forzar reglas.
Antes de las cascade layers, el orden efectivo de las reglas dependía de:
- El orden de aparición en el documento.
- La especificidad del selector.
- La bandera
!important.
Con proyectos que importan decenas de archivos desde distintos orígenes, controlar ese orden se vuelve una tarea artesanal. Las capas de cascada introducen una dimensión nueva: podemos agrupar reglas en capas nombradas y decidir explícitamente el orden en que se aplican.
Declarar capas con @layer
La sintaxis básica de @layer permite declarar una capa y asignarle reglas:
@layer reset {
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
}
@layer componentes {
.boton {
padding: 0.5rem 1rem;
background: #3b82f6;
color: white;
}
}
@layer utilidades {
.margen-top-grande {
margin-top: 2rem;
}
}
Las reglas dentro de una capa siguen sus propias normas de cascada y especificidad, pero cuando hay conflictos entre capas, el orden de declaración de las capas es lo único que importa. Las capas declaradas después ganan sobre las anteriores, sin importar cuál sea más específica internamente.
En el ejemplo anterior, cualquier regla dentro de utilidades vence a cualquier regla dentro de componentes y de reset, incluso aunque las reglas de reset tengan selectores más específicos.
Declaración anticipada del orden
Una técnica muy útil consiste en declarar las capas al inicio del archivo, sin contenido. Esto fija su orden de forma explícita antes de escribir reglas dentro. Es la forma más clara y recomendada de trabajar con capas:
@layer reset, base, tema, componentes, utilidades;
@layer reset {
* { box-sizing: border-box; }
}
@layer base {
body {
font-family: "Inter", sans-serif;
color: #1e293b;
}
}
@layer componentes {
.tarjeta {
padding: 1rem;
border: 1px solid #ddd;
}
}
@layer utilidades {
.oculto { display: none; }
}
La primera línea declara el orden de todas las capas. A partir de ahí, no importa en qué orden aparezcan los bloques @layer: la cascada se basa en el orden inicial. Esto permite organizar archivos, hacer imports y mantener la consistencia aunque el código crezca.
Las capas no declaradas aparecen después de todas las capas nombradas, y los estilos sin capa tienen máxima prioridad. Es el orden natural: capas primero, luego estilos no agrupados, luego
!important.
Integración de frameworks externos
Uno de los casos de uso más importantes de las cascade layers es la integración con frameworks de terceros. Cuando importamos Bootstrap, Bulma, Tailwind o cualquier otra librería, sus estilos pueden colisionar con los nuestros. La solución tradicional era reescribir con más especificidad o usar !important.
Con capas podemos asignar el framework a una capa de baja prioridad y mantener nuestros estilos en una capa superior:
@layer framework, app;
@import url("https://cdn.example.com/framework.css") layer(framework);
@layer app {
.boton {
/* Nuestro estilo gana siempre, aunque el framework use selectores más específicos */
background: purple;
}
}
La sintaxis @import url(...) layer(nombre) introduce todo el contenido del archivo importado dentro de la capa indicada. A partir de ese momento, cualquier regla en capas posteriores gana sobre el framework, independientemente de la especificidad que use el framework internamente.
flowchart TB
A[Capa: reset] --> B[Capa: framework]
B --> C[Capa: base]
C --> D[Capa: componentes]
D --> E[Capa: utilidades]
E --> F[Estilos sin capa]
F --> G[!important ascendente]
Capas anidadas
Una capa puede contener otras capas en su interior. Esto permite modelar jerarquías y separar subconjuntos lógicos dentro de un mismo ámbito:
@layer componentes {
@layer formularios, navegacion, tarjetas;
@layer formularios {
.input { padding: 0.5rem; }
}
@layer navegacion {
.nav { display: flex; }
}
@layer tarjetas {
.tarjeta { padding: 1rem; }
}
}
Las subcapas siguen el mismo principio de orden: tarjetas gana a navegacion, y navegacion gana a formularios, siempre dentro del ámbito de componentes. Esta estructura resulta muy útil cuando un equipo grande divide el trabajo por áreas de la aplicación.
Desde otras capas, el acceso a subcapas se hace con la notación punto:
@layer componentes.formularios {
.input-especial {
border-color: #3b82f6;
}
}
Capas anónimas
Además de capas nombradas, existen las capas anónimas. Se declaran sin nombre y cada bloque @layer { ... } sin nombre crea una capa nueva:
@layer {
.boton { background: red; }
}
@layer {
.boton { background: blue; }
}
Estas capas siguen el orden de aparición y no se pueden referenciar después, por lo que su uso es menos común. Se emplean principalmente para encapsular bloques que no necesitan ampliarse más adelante.
Compatibilidad con !important dentro de capas
Una sutileza importante: cuando una regla usa !important dentro de una capa, el orden de las capas se invierte para esa declaración marcada. Las capas declaradas primero ganan sobre las posteriores, al contrario que en el comportamiento normal.
@layer base, utilidades;
@layer base {
.boton {
background: red !important;
}
}
@layer utilidades {
.boton {
background: blue !important;
}
}
En este caso, pese a que utilidades gana normalmente, con !important la capa base tiene prioridad porque se declaró antes. Este comportamiento puede parecer contraintuitivo, pero existe para evitar que utilidades marcadas con !important sobrescriban resets críticos.
Buenas prácticas con capas
La organización recomendada para un proyecto mediano suele ser la siguiente:
@layer reset, base, tema, layout, componentes, variantes, utilidades;
Cada capa tiene una función concreta:
- 1 - reset: normalización del navegador (eliminación de márgenes por defecto, box-sizing).
- 2 - base: tipografía, colores fundamentales, estilos raíz.
- 3 - tema: variables CSS, tokens de diseño, modo claro y oscuro.
- 4 - layout: grids, containers, rejillas globales.
- 5 - componentes: botones, tarjetas, formularios.
- 6 - variantes: modificadores de componentes como temas alternativos.
- 7 - utilidades: clases atómicas de alta prioridad como
.oculto,.text-center.
Con esta estructura, escribir una utilidad no requiere aumentar la especificidad ni usar !important: basta con ponerla en la capa de utilidades y ganará de forma natural.
Otra buena práctica es evitar mezclar estilos con capa y sin capa. Como los estilos sin capa tienen prioridad máxima, su uso rompe el control que ganamos con las capas. Si un proyecto adopta cascade layers, conviene aplicarlas de forma sistemática en todo el CSS.
Las cascade layers son atemporales: no sustituyen a la especificidad ni a la cascada tradicional, sino que añaden una capa adicional de control para proyectos donde el orden previsible es crítico.
Las cascade layers son especialmente valiosas en design systems, white-label y cualquier proyecto que combine CSS propio con estilos externos. Permiten un control predecible y reducen drásticamente el uso de !important, una de las mayores fuentes de dolor en mantenimiento de CSS a largo plazo.
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en CSS
Documentación oficial de CSS
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, CSS es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de CSS
Explora más contenido relacionado con CSS y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Organizar las reglas CSS en capas nombradas con @layer, controlar el orden explícito de la cascada, integrar frameworks de terceros sin conflictos y evitar el abuso de !important.