La Cascada en CSS: Qué es y cómo funciona

¡Hola gente bonita!👋

¿Alguna vez has escrito una propiedad CSS y el valor no parece funcionar? Tal vez tuviste que recurrir al uso de !important para que funcionara. O quizás hayas recurrido a escribir el CSS inline en el elemento del archivo HTML. Por lo general, el problema puede ser que has creado dos reglas que podrían aplicarse al mismo elemento.

El CSS consiste en declarar reglas: Bajo varias condiciones, queremos que ocurran ciertas cosas. Si esta clase se añade a ese elemento, aplique estos estilos. Si el elemento X es hijo del elemento Y, aplica estos estilos. El navegador toma estas reglas, calcula cuáles se aplican y dónde se van aplicar, y las utiliza para representarlas en la página web.

👉 Recuerda que el aspecto final de una página web es el resultado de reglas de estilo diferentes.

Pero, ¿Qué es una regla en la sintaxis de CSS? 🤔 Puede que no estés familiarizado con el vocabulario en CSS, pero como voy a utilizar este término a lo largo del articulo, es mejor tener claro lo que significa:

Una regla también conocida como estilo, es una colección de declaraciones dirigidas a uno o más selectores, una hoja de estilo se compone de múltiples reglas.

Si quieres aprender sobre la terminología en CSS, he publicado un post ilustrativo en mi Instagram:

El primer paso es entender cómo el navegador da importancia a sus reglas. Por ejemplo, puedes encontrarte con que una de tus reglas no hace lo que esperabas porque otra regla entra en conflicto con ella. Predecir cómo se comportan las reglas requiere comprender la cascada.

Cuando dos o más reglas se dirigen al mismo elemento, las reglas pueden proporcionar declaraciones contradictorias. En el siguiente ejemplo se muestra tres conjuntos de reglas, cada uno de los cuales especifica un estilo de fuente diferente para el título de la página. El título NO puede tener tres fuentes diferentes a la vez. Entonces, ¿Cómo sabe CSS que estilo aplicar? 🤔 o ¿Cuál tiene prioridad sobre los demás? Aquí es donde utilizamos la cascada.

<h1 class="title" id="page-title">Lupita Code</h1>
h1 {
    font-family: serif;
}

#page-title {
    font-family: sans-serif;
}

.title {
    font-family: monospace;
}

Los tres conjuntos de reglas intentan establecer una familia de fuentes diferente para este encabezado <h1>. ¿Cuál de ellas ganará? 🤔. Para determinar la respuesta, el navegador (para saber que estilos tiene prioridad sobre los demás) sigue una serie de reglas o pasos (en orden) que son: Origen de la hoja de estilo, especificidad de los selectores y orden en que se declaran los estilos. Estos conceptos lo vamos a explicar más adelante.

En este caso, las reglas dictan que la segunda declaración, que tiene un selector ID gana; el título tendrá una fuente sans-serif.

Cuando se observan ejemplos pequeños, este proceso suele ser sencillo. Pero a medida que tu hoja de estilos crece, o el número de páginas a las que les aplicas aumenta, tu código puede volverse complejo con sorprendente rapidez.

🤔 ¿Qué es la cascada?

La cascada es el algoritmo por el cual el navegador decide qué estilos CSS aplicar a un elemento - a mucha gente le gusta pensar en esto como el estilo que "gana".
Especifica cómo el navegador debe manejar múltiples estilos que se aplican a la misma etiqueta HTML y qué hacer cuando las propiedades CSS entran en conflicto. La cascada es una parte fundamental del funcionamiento del lenguaje.

Los conflictos de estilo se producen en dos casos: por herencia y cuando uno o más estilos se aplican al mismo elemento.

Cabe mencionar que las iniciales de CSS significan Cascading Style Sheets (Hojas de Estilo en Cascada), y es muy importante entender la palabra cascada ya que como podrás darte cuenta forma parte del propio nombre.

  • En cascada se refiere a la forma en que CSS aplica un estilo encima de otro.
  • Las hojas de estilo controlan la apariencia de los documentos web.

Podemos decir entonces que la cascada es el algoritmo para resolver conflictos cuando se aplican varias reglas CSS a un elemento HTML. La forma en que se comporta la cascada es la clave para comprender el CSS.

La cascada puede ser una herramienta poderosa, pero su uso incorrecto puede conducir a hojas de estilo frágiles que dan pesadillas a los desarrolladores/as de front-end cada vez que tienen que hacer un cambio. Mientras nos sumergimos en la cascada, veremos algunas formas de evitar que la cascada se nos vaya de las manos.

🔼 Las 4 etapas de la cascada

Entender el algoritmo de cascada ayuda a comprender cómo el navegador resuelve conflictos de estilos.
Cuando las declaraciones entran en conflicto, la cascada considera cuatro cosas para resolver la diferencia:

Posición y orden de aparición: El orden en que aparecen tus reglas CSS en la hoja de estilos.
Especificidad de los selectores: Qué selectores tienen prioridad sobre otros.
Origen de la hoja de estilo: El orden de aparición del CSS y su procedencia, ya sea un estilo del navegador, el CSS de una extensión del navegador o el CSS de tu autoría.
Importancia: Algunas reglas CSS tienen más peso que otras, especialmente con el tipo de regla !important.

Las reglas de la cascada se consideran en este orden. Aunque hay varios autores de diversos libros de CSS que solo consideran tres etapas de manera general:

  1. Origen de la hoja de estilo.
  2. Especificidad de los selectores.
  3. Orden en que se declaran los estilos en la hoja de estilos.

El siguiente diagrama de flujo muestra cómo son aplicadas estas reglas.

Estas reglas permiten que los navegadores se comporten de forma predecible al resolver cualquier ambigüedad en el CSS. Vamos a repasarlas una por una.

🔢 Posición y orden de aparición:

El orden en el que aparecen tus reglas CSS y cómo aparecen es tomado en consideración por la cascada mientras ésta calcula la resolución de conflictos.

Ejemplo 1 - Orden de las reglas

button {
  color: red;
}

button {
  color: blue;
}

En este ejemplo hay dos reglas que tienen selectores de idéntica especificidad, por lo que gana la última en ser declarada, es decir, aquí prevalece siempre la última regla definida, la cuál sobreescribe las propiedades anteriores.

Ahora te propongo un reto, dada las siguientes clases, ¿De qué color serían estos divs?

.red {
color: red;
}

.blue {
color: blue;
}
-------
<div class=”red blue”> Lupita Code </div>
<div class=”blue red”> Lupita Code </div>

Si has contestado "ambos divs tienen color blue", felicidades, es la opción correcta. Pero no te sientas mal si no has acertado...

El verdadero truco de la pregunta es que los navegadores no miran el orden en que se declaran las clases en el HTML, sino en el CSS.

👉 Recuerda que cuando dos selectores tienen la misma especificidad, gana la declaración que aparece en último lugar.

Sin embargo hay algunos casos que no esta muy claro que estilo debería sobreescribir a los anteriores, ahí es cuando aplicamos el concepto de cascada, que es la que se encarga de determinar el que tiene mayor prioridad.

Ejemplo 2 - Orden de las hojas de estilo

Hay cuatro formas de incluir CSS en un documento HTML que van de mayor a menor prioridad:

  1. En línea dentro de la etiqueta HTML usando el atributo style;: El CSS en línea es el que tiene mayor precedencia, por lo que siempre será el que tenga prioridad sobre otras reglas CSS.

  2. En el <head> a través de la la etiqueta <style>: el CSS incrustado/interno será el siguiente a tener en cuenta en orden de prioridad.

  3. Asociando una hoja de estilo externa a nuestro documento HTML usando la etiqueta <link> añadida en el <head>: CSS externos son la tercera opción de prioridad al momento de tomar en cuenta las reglas CSS.

  4. En el <head> usando @import dentro de la etiqueta <style>, ejemplo: <style> @import url('style.css') </style> (poco usable).

Nota: A pesar de que hay muchas maneras de incluir CSS en nuestro documento HTML, la forma más usada es asociar una hoja de estilo externa.

Como puedes notar los estilos pueden venir de varias partes en una página HTML. Si tienes un <link> que incluye CSS en la parte superior de tu página HTML, y luego otro <link> que incluye CSS en la parte inferior de tu página: el <link> inferior tendrá la mayor especificidad. Lo mismo ocurre con los elementos <style> incrustados. Se vuelven más específicos cuanto más abajo en la página estén.

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <button>I am a button</button>
    <style>
      button {
        background: pink;
      }
    </style>
  </body>
</html>
/*styles.css*/

button {
  background: yellow;
}

La etiqueta <style> incrustada está más abajo en la página que la etiqueta <link>, así que aunque la especificidad del botón es la misma, la posición de la regla de estilo la hace ganar. Por lo tanto, El botón tendrá un background de color rosa pink.

Dado que CSS tiene en cuenta el orden de las hojas en la cascada, el orden en el que se cargan las hojas de estilo es realmente importante.

Si tienes dos hojas de estilo enlazadas en el <head> de tu documento HTML, la segunda hoja de estilo anulará las reglas de la primera. Esta es también la razón por la que si estás usando un reset de CSS o un framework, querrás cargarlo antes de tus estilos personalizados.

Ejemplo 3 - La posición de las declaraciones

La posición también se aplica en el orden de su regla CSS. En el siguiente ejemplo, el elemento tendrá un fondo púrpura porque background: purple fue declarado en último lugar. Debido a que el background: green fue declarado antes que el background: purple, ahora es ignorado por el navegador.

.my-element {
  background: green;
  background: purple;
}

Poder especificar dos valores para la misma propiedad puede ser una forma sencilla de crear fallbacks para los navegadores que no soportan un valor concreto.

En el siguiente ejemplo, la propiedad font-size se declara dos veces. Si la función clamp() está soportado en el navegador, entonces la declaración anterior de font-size será descartada. Si clamp() no está soportado por el navegador, la declaración inicial será respetada, y el tamaño de la fuente será 1.5rem.

.my-element {
  font-size: 1.5rem;
  font-size: clamp(1.5rem, calc(1rem + 3vw), 2rem);
}

📝 NOTA: Este enfoque de declarar la misma propiedad dos veces funciona porque los navegadores ignoran los valores que no entienden. A diferencia de los lenguajes de programación, CSS no lanzará un error o romperá su programa cuando detecte una línea que no puede analizar - el valor que no puede analizar es inválido y por lo tanto es ignorado. El navegador continúa entonces procesando el resto del CSS sin romper lo que ya entiende.

📑 Especificidad de los selectores

El segundo peso en la cascada es la especificidad del selector. En este nivel, el navegador se fija en los selectores utilizados en las reglas CSS.

La especificidad utiliza un sistema de ponderación o puntuación para determinar qué selector es el más específico, es decir, se asigna prioridad a los distintos tipos de selectores CSS. Al evaluar la especificidad, se tiene en cuenta el número de selectores y su prioridad.
Los diferentes tipos de selectores CSS tienen diferente peso. En orden de mayor a menor prioridad:

  1. Inline styles.
  2. ID selectors (#something).
  3. Classes (.something) / pseudo-selectors (:hover).
  4. Type selectors (<h1>) & pseudo-elements (::before).

Los combinadores (+, > y ~), el selector universal (*) y la pseudoclase :not() no tienen ningún efecto sobre la especificidad.

En el siguiente ejemplo, la clase title del elemento <h1> hará que esa regla sea más específica y por lo tanto se considera más importante para ser aplicada. Esto significa que el <h1> tendrá el color red.

<h1 class="title">Heading</h1>
.title {
  color: red;
}

h1 {
  color: blue;
}

A pesar de que el selector <h1> se encuentra más abajo, podrías pensar que va a sobrescribir a los estilos de la clase, pero no es así, ya que la especificidad considera más importante la clase.

Como podrás comprobar en mi siguiente artículo, cada tipo de selector recibe puntos que indican su especificidad, y se suman los puntos de todos los selectores que hayas utilizado. Esto significa que si tienes una lista de selectores como: a.my-class.another-class[href]:hover obtienes algo bastante difícil de sobrescribir con otro CSS.

Por esta razón, y para ayudar a que tu CSS sea más reutilizable, es una buena idea mantener tus selectores tan simples como sea posible.

🔎 Origen de la hoja de estilo

El CSS que escribes no es el único CSS que se aplica a una página web. La cascada tiene en cuenta el origen del CSS, es decir de donde provienen los estilos. Este origen incluye la hoja de estilos interna del navegador, los estilos añadidos por las extensiones del navegador o el sistema operativo, y el CSS de tu autoría (CSS de autor).

Los estilos del agente de usuario (los estilos por defecto del navegador) tienen menor prioridad, por lo que tus estilos los anulan.

El orden de especificidad de estos orígenes, de menos específico a más específico, es el siguiente

1. Estilos base del agente de usuario: Son los estilos que su navegador aplica a los elementos HTML por defecto.

Los estilos del agente de usuario varían ligeramente de un navegador a otro, pero en general hacen las mismas cosas: a los títulos (<h1> a <h6>) y a los párrafos (<p>) se les da un margen superior e inferior, a las listas (<ol> y <ul>) se les da un padding a la izquierda, y se establecen los colores de los enlaces y los tamaños de letra por defecto.

Si has trabajado con CSS durante mucho tiempo, probablemente estés acostumbrado a anular los estilos del agente de usuario. Cuando lo haces, utilizas la parte de origen de la cascada. Tus estilos siempre anularán los estilos del agente de usuario porque los orígenes son diferentes.

Para evitar inconsistencias entre navegadores se suele utilizar algunas hojas de estilo llamadas "reset" una muy popular se llama Normalize aunque también puedes hacer tu propio "reset". Estos estilos establecen una base para las propiedades que se tratan de forma diferente en los distintos navegadores.

2. Estilos propios del usuario: Pueden venir del sistema operativo, como un tamaño de fuente estándar, o una preferencia. También pueden venir de las extensiones del navegador, como una extensión del navegador que permite al usuario escribir su propio CSS personalizado para una página web.

Un ejemplo, es la maravillosa extensión para Chrome llamada VisBug que permite editar visualmente elementos de cualquier página web, como cambiar los colores, el texto etc.

3. CSS de autor: La hoja de estilos creada por el autor de la página, es decir, El CSS que escribe el desarrollador o desarrolladora.

4. CSS de autor con !important: Cualquier !important que el desarrollador añada a sus declaraciones.

5. Estilos propios del usuario con !important: Cualquier !important que venga del sistema operativo, o del CSS de la extensión del navegador.

6. Estilos base del agente de usuario con !important: Cualquier !important que esté definido en el CSS por defecto del navegador.

Nota: En caso de que la misma propiedad del CSS de usuario y la propiedad del CSS de autor tuvieran !important, tendra prioridad la del CSS de usuario sobre la del CSS de autor.

En la siguiente imagen compartida por el sitio Learn CSS se muestran este orden que va de menor a mayor importancia:

Hay otros autores de diversos libros de CSS que solo consideran de manera general tres fuentes responsables de los estilos que ves en una página web y que forman la cascada, las cuales ya vimos anteriormente:

  1. La hoja de estilos creada por el autor de la página.
  2. Los estilos por defecto del propio navegador.
  3. Los estilos especificados por el usuario.

Considere las siguientes reglas de estilo que estan en distintas hojas de estilo:

<h1>Lorem ipsum</h1>

Estilos del navegador:

h1 { margin-block-start: 0.83em; }

Bootstrap:

h1 { margin-block-start: 20px; }

Hoja de estilos del autor:

h1 { margin-block-start: 2ch; }

@media (max-width: 480px) {
  h1 { margin-block-start: 1ch; }
}

Estilo personalizado del usuario:

h1 { margin-block-start: 2rem !important; }

El margen final que tendrá el <h1> es de 2rem esto es porque el estilo personalizado del usuario es más especifico ya que contiene la declaración !important y va a anular cualquier otro estilo.

El concepto de origen de estilo entrará en juego cuando lleguemos a las transiciones y a las animaciones porque introducen más orígenes en esta lista.

☝️ Importancia

No todas las reglas CSS se calculan de la misma manera ni se les da la misma especificidad.

El orden de importancia, de menor a mayor, es el siguiente:

  1. Tipo de regla común, que tiene las propiedades font-size, background o color.
  2. La regla que contiene la propiedad animation.
  3. La regla que contiene !important (siguiendo el mismo orden que el origen de la hoja de estilos).
  4. La regla que contiene la propiedad transition.

El tipo de regla que tiene las propiedades de animation y transition tienen mayor importancia que las reglas comunes.

En el caso de las transiciones, la importancia es mayor que la regla que tiene la palabra clave !important. Esto se debe a que cuando una animación o transición se activa, su comportamiento esperado es cambiar el estado visual.

2 Reglas de Oro

Hay dos reglas generales para trabajar con la cascada que pueden ser útiles:

  1. No uses IDs en tu selector. Incluso un ID aumenta mucho la especificidad, esto lo vamos a tratar con más detalle en el siguiente articulo.
  2. Evita el uso de !important. Esto es aún más difícil de anular que un ID. Es útil saber que es lo que hace !important. Sin embargo, te recomiendo que no lo utilices.

En los últimos años han surgido una serie de metodologías de CSS para ayudar a controlar la especificidad del selector, una de las más populares es la metodología BEM.

📋 Conclusión:

☑️ Los navegadores utilizan un algoritmo conocido como Cascada (la C de CSS) para decidir qué reglas se aplican a cada elemento cuando encuentran declaraciones conflictivas (es decir, más de una regla que asigna valores diferentes a la propiedad de un elemento).

☑️ La cascada puede se usada para resolver conflictos cuando se aplican varios estilos a un elemento. Este es uno de sus principales objetivos, la resolución de conflictos.

☑️ La cascada, la especificidad y la herencia controlan qué estilo CSS se aplica a un elemento.

🔎 Recursos

📚 Libros de CSS consultados para este tema:

  • CSS in Depth
  • CSS The Missing Manual
  • CSS The Definitive Guide

Gracias por leer🦸🏻‍♀️
Mis redes sociales donde comparto notas de código:

30