La regla @layer
de CSS permite declarar una capa de cascada. Estas capas son muy similares y funcionan de forma muy parecida a las capas de cualquier editor gráfico. Permiten agrupar código CSS en el interior de una capa, y finalmente, fusionarlo todo manteniendo el orden especificado, algo que puede hacer mucho más fácil el organizar CSS, sobretodo de cara a la especificidad CSS.
Veamos un ejemplo de la sintaxis de la regla @layer
:
@layer reset {
body {
margin: 0;
box-sizing: border-box;
}
}
En este caso, estamos creando una capa reset
con código CSS para hacer un reseteo de ciertas propiedades. El nombre reset
lo establece el desarrollador, y puede ser cualquier otro nombre que desee. Esto significa que, a partir de ahora, existirá una capa reset
que incluye los estilos indicados en el interior de dicha regla.
Pero... Aparte de la creación de una capa, ¿cuál es su finalidad? ¿Para qué necesitamos las capas? Básicamente para poder reordenarlas y evitar problemas de especificidad que pueden aparecer a la larga. Lo iremos explicando a lo largo de este artículo.
Crear capas en CSS
Primero, vamos a conocer las múltiples formas de crear capas en CSS utilizando la regla @layer
, o incluso mediante la regla @import
que vimos en algún tema anterior. Veamos que sintaxis tenemos disponibles:
Formato | Descripción |
---|---|
@layer | Crea una capa CSS anónima (sin nombre). |
@layer nombre | Crea una capa CSS con el nombre indicado. |
@layer nombre.subcapa | Crea una capa CSS con nombre, con una subcapa anidada subcapa. |
@layer nombre1, nombre2, nombre3... | Declara y establece un orden para varias capas CSS. |
@import( fichero.css) layer( nombre) | Importa un archivo CSS y lo introduce en la capa indicada. |
Utilizando la regla @layer
podemos crear una capa CSS con un nombre determinado:
@layer utils {
.primary {
background: #34a;
border: 2px outset #6381db;
color: #fff;
padding: 5px 10px;
border-radius: 6px;
}
}
Al crear una capa, de forma implícita estamos indicando el orden de las capas (orden en el que han sido definidas). Esto es muy importante, ya que determina el orden en el que se van a evaluar. Sin embargo, veremos más adelante que ese orden se puede alterar.
Capas con nesting CSS
Gracias al nesting CSS nativo, también es posible utilizar la regla @layer
a la inversa, es decir, crear nuestro código CSS en un selector y escribir las reglas @layer
en su interior. Veamos un fragmento de código de ejemplo:
<div class="primary">Hello, friend!</div>
<style>
@layer base, theme;
.primary {
@layer theme {
background: indigo;
color: white;
}
@layer base {
background: grey;
width: 250px;
height: 200px;
padding: 1rem;
}
}
</style>
Puedes cambiar la primera línea @layer base, theme
por @layer theme, base
. Esto hará que el orden de las capas sea diferente y aplique primero la capa theme
y luego la capa base
.
Capas anónimas
Si en lugar de escribir el nombre de la capa (utils en nuestro ejemplo) no escribimos nada, estamos creando una capa anónima sin nombre, que es lo mismo que ocurre si colocamos CSS sin ninguna capa, al final se creará una capa anónima donde se incluirá ese código CSS.
La sintaxis explícita sería la siguiente:
@layer {
.primary {
background: #34a;
border: 2px outset #6381db;
color: #fff;
padding: 5px 10px;
border-radius: 6px;
}
}
En el caso de crear capas anónimas, no existe ninguna forma de hacer referencia a ellas posteriormente para añadir más código CSS o reordenarlas. Recuerda que si creamos múltiples capas anónimas como en el ejemplo anterior, el navegador creará múltiples capas anónimas diferentes.
Orden de las capas
Podemos cambiar el orden de las capas, si establecemos una regla @layer
con las diferentes capas separadas por coma. Hay que asegurarse que esto ocurre antes de la creación de las capas, ya que una vez declaradas no se puede cambiar su orden:
@layer reset, texts, theme;
@layer reset {
button {
padding: 30px;
}
}
@layer theme {
.primary {
background: #34a;
border: 2px outset #6381db;
color: #fff;
padding: 5px 10px;
border-radius: 6px;
}
}
@layer texts {
.primary {
color: red;
}
}
<button class="primary">First button</button>
<button class="primary">Second button</button>
Si en el caso anterior, no definimos la primera línea, el orden de las capas sería reset, theme, texts
(el orden natural definido), sin embargo, al haberlo indicado, el orden se establece en reset, texts, theme
. Observa que la diferencia aparente es que el texto de los botones aparecen en color rojo. Para ello, hay que comprender como funciona la especificidad de CSS.
Este ejemplo es muy sencillo, y simplemente, con la primera regla @layer
cambiamos el orden en el que se procesan las capas, consiguiendo darle prioridad a la capa theme
porque está en último lugar, sobreescribiendo los estilos del color de texto de la capa texts
.
En el caso de indicar múltiples veces una misma capa, el navegador fusionará los estilos en la misma capa. Esto permitirá que en algunos casos podamos añadir más estilos a una capa ya definida. Imagina que añadimos el siguiente código CSS al ejemplo anterior:
@layer theme {
.primary {
color: gold;
}
}
Observa que en este caso, el color de texto del botón será gold
.
Ten en cuenta que cualquier estilo declarado sin capa, independientemente del orden de aparición, se agrupará en una capa anónima y se aplicará siempre al final del resto de capas declaradas.
La especificidad en capas CSS
Observa el siguiente ejemplo. En él, encontrarás tres grupos de código CSS donde se utiliza el selector. En estos bloques de código no suele haber dudas, ya que al ser el mismo selector, se aplica el orden y la herencia, y simplemente se fusionan los estilos, sobreescribiendo el último a los anteriores de coincidir las propiedades:
.primary {
color: red;
}
.primary {
background: #34a;
border: 2px outset #6381db;
color: #fff;
padding: 5px 10px;
border-radius: 6px;
}
.primary {
margin: 20px;
color: gold;
}
<button class="primary">Click me!</button>
Sin embargo, modifiquemos las clases para hacer más específicos los selectores. En cada grupo seleccionamos el mismo elemento pero con diferente especificidad:
- Primer grupo: Botones
button
que tienen un atributoclass
y claseprimary
(especificidad 021) - Segundo grupo: Botones
button
que tienen claseprimary
. (especificidad 011) - Tercer grupo: Botones que tienen clase
primary
. (especificidad 010)
Al contrario que muchos desarrolladores piensan, en CSS no se fusionan los estilos al ser (al fin y al cabo) el mismo elemento, sino que los selectores más especificos son los que tendrán prioridad, independientemente del orden:
button[class].primary {
color: red;
}
button.primary {
background: #34a;
border: 2px outset #6381db;
color: #fff;
padding: 5px 10px;
border-radius: 6px;
}
.primary {
margin: 20px;
color: gold;
}
<button class="primary">Click me!</button>
En este caso, se aplicará primero el último grupo (al ser el menos especifico), luego se aplicarán los estilos del segundo grupo, sobreescribiendo el color blanco por el color dorado. Por último, el primer bloque sobreescribirá con el color rojo.
Modifiquemos un poco el ejemplo anterior, y vamos a añadir el primer grupo en una capa llamada texts
:
@layer texts {
button[class].primary {
color: red;
}
}
button.primary {
background: #34a;
border: 2px outset #6381db;
color: #fff;
padding: 5px 10px;
border-radius: 6px;
}
.primary {
margin: 20px;
color: gold;
}
<button class="primary">Click me!</button>
Ahora, observa que la capa texts
creada será la primera en procesarse por el navegador. Lo primero que hará es agrupar todos los estilos en dicha capa, calcular sus especificidades y aplicarlas. Luego, buscará si existen otras capas diferentes para procesarlas. Si no existen más, agrupará el resto de los estilos fuera de capas en una capa anónima y los aplicará después de los anteriores.
De esta forma, hemos cambiado el comportamiento que explicamos al principio por algo que, unido a la posibilidad de agrupar en diferentes capas y ordenar mediante la regla @layer
se convierte en un recurso muy potente para organizar código por parte de los desarrolladores.
Capas CSS anidadas
Dentro de las capas de CSS, también es posible crear capas dentro de otras. Para ello, solo tenemos que utilizar la regla @layer
dentro de otra regla @layer
, como se puede ver a continuación:
@layer base {
@layer reset {
body {
margin: 0;
box-sizing: border-box;
}
}
}
Ten en cuenta que también puedes usar una sintaxis rápida separando los nombres de la capa con puntos. El ejemplo anterior podría definirse también de la siguiente forma:
@layer base.reset {
body {
margin: 0;
box-sizing: border-box;
}
}
Importar CSS en una capa
Si ya conocemos la regla @import, sabremos que es posible utilizarla para importar código CSS de ficheros externos e incorporarlo a nuestra página. Sin embargo, existe una forma de hacerlo añadiéndolo a una capa CSS específica, utilizando la palabra clave layer
tras la importación:
@import url("framework.css") layer(framework);
Esto permitirá que incluso código externo que tengamos separados en diferentes archivos, se pueda colocar directamente en una capa, evitando posibles problemas de especificidad al ser código CSS externo, como por ejemplo, suele ocurrir con los frameworks CSS.