Cascada en CSS

La cascada de CSS: Importancia, Especificidad y Orden

Uno de los conceptos más importantes de CSS, y a la vez, uno de los conceptos más desconocidos o malentendidos, es el denominado Cascada de CSS. De hecho, la cascada es la que le da sentido a la C inicial de las siglas CSS, lo que da una idea de la importancia que tiene en este tema.

En algunos casos, el concepto de cascada puede resultar demasiado avanzado como para verlo en un tema de introducción, por lo que se debe conocer bien el tema de selectores CSS y dominar algo de propiedades CSS para comprenderlo totalmente. Si estás comenzando con CSS, se aconseja que se posponga para una lectura posterior.

¿Qué es la Cascada CSS?

Cuando hablamos de la Cascada CSS nos referimos al algoritmo o conjunto de reglas y normas que tiene el navegador para aplicar estilos CSS a un elemento HTML. No es tan sencillo como la mayoría cree, ya que hay múltiples casos donde pueden existir ambigüedades o conflictos de valores, y el navegador debe resolverlos para saber cual debe prevalecer.

Imagina que tenemos enlazados dos archivos .css mediante <link> y en cada uno tenemos un mismo selector .text aplicando colores diferentes. ¿Cuál de los dos se aplicará finalmente? Quizás pienses que el último que haya sido definido. A veces, esto es cierto, pero otras muchas veces no. Expliquemos la razón.

La cascada comprende varios temas importantes a la hora de resolver dichos conflictos:

  • Importancia: Los estilos pueden tener una importancia concreta, eso le da mayor o menor prioridad.
  • Origen: Existen varios orígenes de CSS, cada uno con una prioridad específica.
  • Orden de aparición: El orden en el que se procesa el CSS influye a la hora de resolver conflictos.
  • Especificidad: Cuanto más específicos sean los estilos CSS, mayor prioridad.
  • Capas: Los estilos CSS se pueden aislar en capas fusionables. Lo explicamos en @layers CSS.

Vamos a repasar cada uno de ellos para comprenderlo lo mejor posible.

Importancia

Existe la posibilidad de añadir el texto !important al final de una regla, consiguiendo que el navegador le de prioridad a la hora de evaluar dichos estilos sobre otros. Veamos un ejemplo de como funciona:

<div class="text">Texto del elemento</div>

<style>
.text {
color: red!important;
}

.text {
color: blue;
}
</style>

Observa que, a pesar de tener definido un color blue posteriormente, el texto !important le dará prioridad al anterior, dibujando el color de texto en rojo, en lugar de azul. En el caso de tener varias reglas con !important, prevalecerá la que además se encuentre en último lugar.

OJO: Desgraciadamente, esta es una de las características más conocidas de CSS debido a que es una forma «cómoda» de forzar la importancia de una regla CSS. Su utilización no es una mala práctica, sin embargo, su uso indiscriminado si lo es y debería evitarse salvo causas justificadas.

Origen

La cascada tiene en cuenta las hojas de estilo donde está colocado nuestro código CSS. Generalmente, no necesitaremos preocuparnos de este factor, ya que nos centraremos casi siempre en el CSS de autor. Sin embargo, es una buena idea conocer en que se basa cada origen.

Tenemos 3 orígenes, ordenados de menor a mayor importancia:

  • 1️⃣ Agente de usuario: Estilos CSS que tiene y aplica el navegador por defecto.
  • 2️⃣ CSS de usuario: Estilos CSS que añade el usuario para personalizar, por ejemplo, con UserStyles.
  • 3️⃣ CSS de autor: Son los estilos CSS que crea el desarrollador en la página web.

Nota: En el caso de que una propiedad CSS de cada origen tuviera definido un !important, el orden de importancia anterior se invertiría, resultando que el CSS del agente de usuario tendría prioridad sobre el CSS de usuario y de autor.

Orden de aparición

Esta suele ser una de las partes de la cascada que más clara suele estar, ya que es bastante intuitiva. En el tema introductorio Cómo enlazar CSS, vimos que es posible aplicar estilos CSS a un documento de varias formas:

  • 1️⃣ Atributo style en una etiqueta HTML.
  • 2️⃣ Bloque de estilos <style> en el documento HTML.
  • 3️⃣ Archivo .css externo referenciado mediante <link rel="stylesheet">.

Veamos un ejemplo donde se apliquen estas tres formas:

<html>
<head>
<link rel="stylesheet" href="index.css" />
<style>
.text { color: red }
</style>
</head>
<body>
<div class="text">¡Desde Manz.dev puedes ver mis streams!</div>
</body>
</html>

Observa que en este ejemplo concreto, la etiqueta <link> está definida antes del bloque <style>. En un principio, para un mismo selector que entre en conflicto, prevalecería el que se encuentra definido en el bloque <style>, ya que se define después de la etiqueta <link>. De la misma forma, ocurriría si se tratase de dos etiquetas <link>. La última es la que prevalece porque «sobreescribe» a la anterior.


Supongamos que nos encontramos ahora en una misma hoja de estilos, donde aplicamos estilos a exactamente el mismo selector. Utilizamos la propiedad color pero con diferente valor en cada coincidencia. Algo similar a lo siguiente:

<div class="text">Texto del elemento</div>

<style>
.text {
padding: 8px
color: red;
}

.text {
background-color: grey
color: blue;
}
</style>

La pregunta sería: ¿Cuál de las dos propiedades color prevalece? Se refieren al mismo elemento y están al mismo nivel. La respuesta es muy fácil: Prevalece siempre la última regla definida. En el caso anterior, el resultado final interpretado por el navegador (valor computado) sería el siguiente:

.text {
padding: 8px; /* No hay conflicto, se añade */
background-color: grey; /* No hay conflicto, se añade */
color: blue; /* Hay conflicto: se sobreescribe la última */
}

Sin embargo, puede ocurrir que en determinados casos no esté tan claro cuál es el estilo que debería sobreescribir a los anteriores. Ahí es cuando entra en juego el concepto de especificidad, que es uno de los que se encarga de eliminar la ambigüedad determinando cuál es más específico. Supongamos el siguiente caso, donde tenemos un mismo elemento <div> con un id y una clase:

<div id="element" class="block">Texto del elemento</div>

<style>
div { color: red; }
#element { color: blue; }
.block { color: green; }
</style>

Nuestro elemento HTML <div> encaja con los tres bloques del ejemplo anterior. ¿Cómo sabe el navegador CSS que estilo aplicar? ¿Cuál tiene prioridad sobre los demás? En ese caso, el navegador calcula que selector es más específico aplicando las normas de la especificidad CSS.

Especificidad CSS

En el caso de que tengamos un conflicto donde no se haya eliminado la ambigüedad, se pasa a calcular el selector más específico siguiendo unas normas que se detallan a continuación:

Componente Descripción
Componente ID Número de veces que aparece un #id en el selector.
Componente Clase Número de veces que aparece una .clase, :pseudoclase o [atributo] en el selector.
Componente Elemento Número de veces que aparece un elemento o un ::pseudoelementos en el selector.

Para saber si un selector de CSS es más específico que otro (y por lo tanto, el navegador le da prioridad) sólo hay que calcular los dígitos de los componentes anteriores, que forman un número que indica la especificidad:

div { ... }                   /* Especificidad: 0,0,1 (1 elemento) */
div div { ... } /* Especificidad: 0,0,2 (2 elementos) */
#pagina div { ... } /* Especificidad: 1,0,1 (1 id y 1 elemento) */
#pagina div:hover { ... } /* Especificidad: 1,1,1 (1 id, 1 pseudoclase y 1 elemento) */
#pagina div:hover a { ... } /* Especificidad: 1,1,2 (1 id, 1 pseudoclase y 2 elementos) */
#pagina .sel:hover>a { ... } /* Especificidad: 1,2,1 (1 id, 1 clase, 1 pseudoclase y 1 elemento) */

En keegan.st tienes una excelente calculadora de especificidad CSS donde podrás calcular la especificidad de un selector CSS rápida y cómodamente.

Existe una excepción a todo esto que es el CSS en línea. En el caso de que se definan unos estilos CSS a través del atributo style de una etiqueta HTML, siempre tendrá preferencia directa, ya que es la forma más específica.

Tabla de contenidos