Capas en CSS: Guía Completa para Dominar la Regla @layer y Controlar la Especificidad
John Serrano (DEV)

John Serrano (DEV) @johnserranodev

About: Hola, Soy John Serrano Ingeniero de Software +7 años de experiencia. Me especializo en la creación de experiencias digitales de alto impacto. De Cúcuta, Colombia.

Location:
Colombia
Joined:
May 28, 2024

Capas en CSS: Guía Completa para Dominar la Regla @layer y Controlar la Especificidad

Publish Date: May 6
4 0

Introducción: ¿Qué son las Capas de Cascada en CSS?

Las capas de cascada (cascade layers) en CSS han sido introducidas para resolver uno de los problemas más complejos y persistentes en la escritura de estilos: los conflictos de especificidad. En este artículo exploraremos cuál es exactamente ese problema y cómo la regla @layer nos ofrece una solución eficaz y moderna.

La regla @layer permite declarar estas capas de cascada, que funcionan de forma análoga a las capas en editores gráficos como Photoshop o GIMP: cada capa es un grupo independiente, pero en lugar de imágenes, gestionamos reglas CSS.

El objetivo principal es claro:

  • Organizar mejor el código.

  • Evitar los problemas clásicos de especificidad.

  • Reducir la necesidad de usar !important o sobreescribir selectores complejos.

El problema: La especificidad se vuelve inmanejable

Todo desarrollador que ha trabajado con CSS se ha encontrado con la frustración de querer sobrescribir estilos provenientes de otras partes del código, de librerías o frameworks externos, solo para verse atrapado en una batalla de especificidad. Tradicionalmente, para resolver estos conflictos, se han creado "metodologías" y "buenas prácticas" que, en esencia, intentan evitar que la cascada actúe, en lugar de aprovecharla. Ejemplos de estas prácticas son restringirse a usar sólo clases simples o evitar selectores anidados.

El manejo de la cascada y la especificidad ha sido durante años una de las partes más confusas de CSS. Esto se debe en parte a que pocos lenguajes basan su comportamiento en una cascada, pero también a que la forma tradicional de resolución de estilos en CSS depende de heurísticas, no de un control explícito por parte del autor.

Por ejemplo, la especificidad está basada en la suposición de que un selector más detallado (como un ID único) debería tener mayor prioridad que un selector genérico (como una clase). Sin embargo, esto no siempre refleja las verdaderas intenciones del autor, y las soluciones comunes suelen agravar el problema: añadir selectores innecesarios o recurrir al temido !important.

/* Especificidad forzada y confusa */
.overly#powerful .framework.widget {
  color: maroon;
}

.my-single_class { /* ¿Agregar IDs? */
  color: rebeccapurple; /* ¿O usar !important? */
}
Enter fullscreen mode Exit fullscreen mode

La solución: Capas de cascada para un control real

Las capas de cascada permiten a los autores de CSS tomar el control total de la cascada, creando sistemas intencionados y ordenados, en lugar de depender de reglas implícitas y suposiciones.

Mediante la regla @layer y las importaciones con capa mediante @import, podemos establecer nuestras propias capas jerárquicas: desde los estilos de bajo nivel como resets y temas base, hasta las capas superiores como componentes, utilidades y sobrescrituras.

Dentro de cada capa, la especificidad sigue funcionando como siempre. Pero entre capas, los conflictos siempre se resuelven a favor de la capa con mayor prioridad, sin necesidad de escalar especificidad ni usar !important.

@layer framework {
  .overly#powerful .framework.widget {
    color: maroon;
  }
}

@layer site {
  .my-single_class {
    color: rebeccapurple;
  }
}
Enter fullscreen mode Exit fullscreen mode

Las capas son ordenadas y no se acumulan como la especificidad de los selectores. Añadir más capas no incrementa su poder. Tampoco son absolutas como !important, ni arbitrarias como un z-index inflado. De hecho, por defecto, los estilos dentro de una capa son menos prioritarios que los estilos no agrupados en capas.

@layer defaults {
  a:any-link { color: maroon; }
}

/* Estilos no encapsulados en capas siempre tienen la máxima prioridad */
a {
  color: mediumvioletred;
}
Enter fullscreen mode Exit fullscreen mode

Sintaxis y declaración de capas

CSS nos ofrece varias formas para declarar capas utilizando @layer o mediante @import:

Sintaxis Descripción
@layer nombre Crea una capa CSS con el nombre indicado.
@layer Crea una capa anónima (sin nombre).
@layer nombre.subcapa Crea una capa con subcapas anidadas.
@layer nombre1, nombre2, ... Declara y ordena múltiples capas.
@import url("archivo.css") layer(nombre) Importa CSS en la capa especificada.

El orden en que se definen las capas determina su prioridad en la cascada, algo fundamental para evitar conflictos de especificidad. No obstante, como veremos más adelante en esta guía, ese orden también puede ser manipulado para ajustarlo a nuestras necesidades.

A continuación, exploraremos cada una de estas sintaxis en detalle y aprenderemos a utilizarlas para construir sistemas CSS más robustos, predecibles y sostenibles.

Cómo crear y ordenar Capas en CSS

Ahora que entendemos qué son las capas de cascada y por qué resuelven problemas de especificidad, es momento de aprender a utilizarlas de forma práctica en nuestros estilos CSS. La regla @layer es sencilla en su sintaxis, pero poderosa en sus aplicaciones.

Declarando una Capa Simple

La forma más básica es declarar una capa con un nombre único y agrupar dentro de ella nuestras reglas CSS:

@layer base {
  body {
    font-family: system-ui, sans-serif;
    color: #333;
  }
}
Enter fullscreen mode Exit fullscreen mode

Esta capa llamada base se comporta como un grupo. Los estilos dentro de ella competirán entre sí usando la especificidad tradicional, pero como bloque completo, base tendrá una prioridad determinada por su posición frente a otras capas.

Declarando Capas Anónimas

Si no necesitas un nombre específico, puedes crear una capa anónima:

@layer {
  h1 {
    font-size: 2rem;
  }
}
Enter fullscreen mode Exit fullscreen mode

Las capas anónimas son útiles para agrupar estilos sin preocuparte por su identificación, pero su uso es menos común en proyectos grandes donde el control del orden es esencial.

Creando Subcapas Anidadas

CSS permite anidar capas creando jerarquías internas mediante subcapas:

@layer components.buttons {
  .btn {
    padding: 0.5rem 1rem;
    border-radius: 0.25rem;
  }
}
Enter fullscreen mode Exit fullscreen mode

En este caso, buttons es una subcapa dentro de components. La jerarquía te da mayor control para modular tu CSS y ordenar prioridades dentro de sistemas grandes.

Declarando y ordenando Múltiples Capas

Una de las grandes ventajas de las cascade layers es que puedes declarar varias capas al mismo tiempo y establecer su orden:

@layer reset, base, components, utilities;
Enter fullscreen mode Exit fullscreen mode

El orden en esta declaración es crucial:

  • reset tendrá la menor prioridad.

  • utilities tendrá la mayor prioridad dentro de las capas.

Las reglas fuera de cualquier capa siguen siendo las de máxima prioridad (salvo que uses !important).

Ejemplo claro: Controlando el orden con @layer

Observa el siguiente ejemplo. Aquí declaramos un orden específico: primero la capa reset, luego texts, y al final theme.

<button class="primary">Primer botón</button>
<button class="primary">Segundo botón</button>

<style>
  /* Declaramos el orden de las capas */
  @layer reset, texts, theme;

  @layer reset {
    button {
      padding: 30px;
    }
  }

  @layer theme {
    .primary {
      background: #3454d1;
      border: 2px outset #6381db;
      color: white; /* Color de texto en theme */
      font-size: 1rem;
      padding: 5px 10px;
      border-radius: 6px;
    }
  }

  @layer texts {
    .primary {
      color: red; /* Color de texto en texts */
    }
  }
</style>
Enter fullscreen mode Exit fullscreen mode

¿Qué color se aplica?

Aunque en el flujo normal de CSS el color rojo (texts) viene después y debería prevalecer, gana la capa theme, porque hemos definido en la primera línea que theme es la capa con mayor prioridad entre las tres. Por tanto, el texto aparecerá en blanco, como define la capa theme.

Fusionando reglas de una misma Capa

Otra característica importante es que, si vuelves a declarar una capa con el mismo nombre más adelante, el navegador fusiona ambas definiciones en la misma capa, sin alterar su posición en la prioridad general.

@layer theme {
  .primary {
    color: gold; /* Nueva regla dentro de theme */
  }
}
Enter fullscreen mode Exit fullscreen mode

Ahora, como ambas reglas (color: white y color: gold) están en la misma capa theme, se aplicará la última que aparezca dentro de esa capa, es decir, el color dorado.

Regla de Oro: Los estilos fuera de Capa siempre Ganan

Cualquier estilo declarado fuera de cualquier @layer (es decir, sin pertenecer a ninguna capa) se agrupará automáticamente en la capa anónima. Esta capa siempre tiene la máxima prioridad sobre cualquier capa que definas con @layer.

/* Esta regla gana siempre sobre cualquier capa */
.primary {
  color: black;
}
Enter fullscreen mode Exit fullscreen mode

Por tanto, si necesitas forzar estilos al margen de tu sistema de capas, simplemente escríbelos fuera de cualquier @layer.

Importando CSS en una Capa

También puedes importar archivos CSS directamente dentro de una capa, ideal para organizar tu proyecto modularmente:

@import url("reset.css") layer(reset);
@import url("framework.css") layer(components);
Enter fullscreen mode Exit fullscreen mode

Esto asegura que todo el contenido de reset.css estará encapsulado en la capa reset, evitando que choque en especificidad con otras partes de tu código.

Regla Fundamental: El orden define la Prioridad

Las capas se aplican en el orden en que se declaran, no en el orden en que el CSS es escrito dentro de ellas. Es decir, si defines primero @layer base y luego @layer components, la capa components tendrá prioridad, incluso si sus selectores tienen menor especificidad.

Ejemplo:

@layer base {
  h1 {
    color: black;
  }
}

@layer components {
  h1 {
    color: crimson;
  }
}
Enter fullscreen mode Exit fullscreen mode

En este caso, el h1 será crimson porque components es una capa declarada después de base.

Ventajas claras de las Capas en CSS

  • Evitan la escalada de especificidad.
  • Reducen el uso innecesario de !important.
  • Permiten importar librerías sin perder el control sobre tus estilos personalizados.

Fomentan un código CSS modular, predecible y mantenible a largo plazo.

¿Para qué sirven las Capas en CSS?

Las capas (@layer) en CSS nos permiten organizar y controlar la prioridad de nuestros estilos de forma mucho más flexible que con la especificidad tradicional.

Cuando tu proyecto crece o incluyes librerías externas, la especificidad empieza a depender de factores difíciles de manejar. Con @layer, puedes definir de forma explícita qué grupo de estilos tiene prioridad sobre otro, sin necesidad de recurrir a selectores más largos o a !important.

Especificidad: El problema que resuelve @layer

Observa este ejemplo básico. Aquí usamos el mismo selector .primary varias veces. CSS simplemente aplica la propiedad del último bloque que coincide:

.primary {
  color: red;
}

.primary {
  background: #34a;
  border: 2px outset #6381db;
  color: #fff;
  padding: 5px 10px;
  border-radius: 6px;
}

.primary {
  margin: 20px;
  color: green;
}
Enter fullscreen mode Exit fullscreen mode

En este caso, el color de texto será verde (color: green), ya que es el último que aparece para la propiedad color.

Especificidad: Cómo afecta cuando cambian los selectores

Ahora, hagamos los selectores un poco más específicos:

/* Especificidad: 0,2,1 */
button[class].primary {
  color: red;
}

/* Especificidad: 0,1,1 */
button.primary {
  background: #34a;
  border: 2px outset #6381db;
  color: #fff;
  padding: 5px 10px;
  border-radius: 6px;
}

/* Especificidad: 0,1,0 */
.primary {
  margin: 20px;
  color: green;
}
Enter fullscreen mode Exit fullscreen mode

Aquí ya no importa tanto el orden. El navegador aplicará las propiedades siguiendo la especificidad:

Primero se aplican los estilos con menos especificidad (.primary con 0,1,0).

Luego los de especificidad media (button.primary con 0,1,1).

Por último, los más específicos (button[class].primary con 0,2,1).

🔎 Resultado:

El color rojo prevalecerá, porque el selector button[class].primary es el más específico.

Cómo @layer Cambia las Reglas del Juego

Ahora vamos a agrupar el selector más específico dentro de 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: green;
}
Enter fullscreen mode Exit fullscreen mode

¿Qué ocurre ahora?

  • Primero, el navegador procesa la capa texts.

  • Luego, agrupa y aplica todos los estilos fuera de capa en lo que se llama la capa anónima.

  • Y por regla general, esta capa anónima siempre tiene mayor prioridad que cualquier capa declarada con @layer.

Por tanto, el color verde (color: green) volverá a ganar, incluso aunque el selector de la capa texts tenga mayor especificidad. Esto demuestra cómo @layer permite a los desarrolladores reorganizar la prioridad de estilos de forma más potente que simplemente aumentando la especificidad.

Uso de @layer con CSS Nesting

Gracias al CSS Nesting nativo, también podemos declarar capas dentro de un selector. Esto permite una estructura de código aún más ordenada y modular.

<div class="primary">Hello, John Serrano!</div>

<style>
  @layer base, theme;

  .primary {
    @layer theme {
      background: indigo;
      color: white;
    }
    @layer base {
      background: grey;
      width: 250px;
      height: 200px;
      padding: 1rem;
    }
  }
</style>
Enter fullscreen mode Exit fullscreen mode

¿Cómo funciona aquí?

  • En la línea @layer base, theme; declaramos que la capa base se aplicará antes que la capa theme.

  • Así, aunque theme venga antes en el código, sus estilos ganan porque está declarada con mayor prioridad.

Si cambias esa primera línea por:

@layer theme, base;
Enter fullscreen mode Exit fullscreen mode

Ahora, la capa base tendrá prioridad y el fondo gris sobrescribirá al fondo índigo.

Conclusiones

Las capas en CSS (@layer) nos permiten controlar el orden y la prioridad de los estilos de forma más clara y organizada, sin depender únicamente de la especificidad. Son una herramienta poderosa para mantener el código limpio y predecible, especialmente en proyectos grandes o con estilos externos.

Te invito a visitar mi blog, donde encontrarás más contenido sobre JavaScript, React, CSS, IA, buenas prácticas y mucho más. 👉 johnserrano.co/blog ¡No te lo pierdas!

Gracias por leer. ❤️

Comments 0 total

    Add comment