Anidación

Anidar reglas de diseño de CSS puede hacer que tus hojas de diseño sean más organizadas, fáciles de leer y mantener.

Descripción general

Ahora que aprendiste sobre los selectores, probablemente te preguntes cómo organizarlos mejor en tus hojas de estilo. Imagina que estás aplicando estilos a los elementos dentro de una sección de "funciones" en tu sitio. Con el anidamiento, puedes agrupar estos estilos dentro de la regla .feature de la siguiente manera:

.feature {
  button {
    color: blue;
  }

  .link {
    color: red;
  }

  .text {
    font-size: 1.3em;
  }
}

Esto sería lo mismo que escribir cada diseño por separado:

.feature button {
  color: blue;
}

.feature .link {
   color: red;
}

.feature .text {
   font-size: 1.3em;
}

El anidamiento puede tener tantas capas como sea necesario.

.feature {
  .heading {
    color: blue;

    a {
      color: green;
    }
  }
}

Agrupación y establecimiento de relaciones

El anidamiento te permite agrupar y establecer relaciones entre las reglas de estilo de forma más concisa.

De forma predeterminada, la regla anidada se relacionará con la regla externa como un combinador de descendientes. Usa selectores en las reglas anidadas para cambiar las relaciones.

/* targets headings that are siblings of the .feature element and come immediately after it */
.feature {
  + .heading {
    color: blue;
  }

/* targets all paragraphs that are direct children of the .feature element */
  > p {
    font-size: 1.3em;
  }
}

Define relaciones explícitas con el selector &

También puedes usar el selector & para ser más explícito cuando anides reglas de estilo. Piensa en & como un símbolo que representa el selector principal.

.feature {
 & button {
    color: blue;
  }
}

Esto sería equivalente a escribir los estilos de la siguiente manera:

.feature button {
  color: blue;
}

Cuándo se requiere &

Sin &, los selectores anidados serán selectores descendientes del selector principal. Para formar selectores compuestos, & es obligatorio.

.feature {
  &:last-child {
    /* Selects the .feature element that is the :last-child, equivalent to .feature:last-child */
  }
   
  & :last-child {
    /* Selects the :last-child inside of a .feature element, equivalent to .feature :last-child */
  }

  &.highlight {
    /* Selects .feature elements that also have a .highlight class, equivalent to .feature.highlight */
  }

  & .highlight {
     /* Selects elements inside of the .feature element with the class .highlight, equivalent to .feature .highlight */
  }
}

También puedes cambiar el contexto y colocar el selector & al final del selector secundario o en ambos lados.


/* Targets buttons with an adjacent sibling button */
button {
  & + & {
    /* … */
  }
}
img {
  .my-component & {
    /* styles for images inside of `.my-component` ... */
  }
}

En el último ejemplo, agregamos estilos para las imágenes dentro de un elemento con la clase .my-component. Esto puede ser útil si trabajas en un proyecto en el que no puedes agregar un class o un id a un elemento.

Anidamiento y especificidad

Al igual que :is(), el selector de anidación toma la especificidad del selector con la mayor especificidad en la lista de selectores del elemento superior.

#main-header,
.intro {
  & a {
    color: green;
  }
}

.intro a {
  color: blue;
}

La primera regla segmenta todos los vínculos dentro de los elementos #main-header y .intro, y les asigna un color verde.

La segunda regla intenta anular esto para que los vínculos dentro del elemento .intro sean azules.

Podemos ver por qué no funciona si observamos la especificidad de cada regla.

/* equivalent to :is(#main-header, .intro) a with a specificity of (1, 0, 1) */
#main-header,
.intro {
  & a {
    color: green;
  }
}

/* lower specificity of (0, 1, 1) */
.intro a {
  color: blue;
}

Dado que la primera regla tiene un id en su lista de selectores y las reglas anidadas toman la especificidad del selector con la mayor especificidad, tiene una especificidad mayor que la segunda regla. Los vínculos son verdes incluso para los elementos a que no están dentro de un elemento con el selector #main-header.

Anidación no válida

Al igual que :is(), el selector de anidación no puede representar seudoelementos.

blockquote, blockquote::before, blockquote::after {
  color: navy;

  & {
    border: 1px solid navy;
  }
}

Se esperaría que el elemento blockquote y sus seudoelementos tuvieran texto y bordes de color navy, pero no es así. Dado que el selector & no puede representar seudoelementos, los estilos de borde anidados solo se aplicarán a la cita.

Cuando crees selectores compuestos con & y selectores de tipo, el selector de tipo debe ir primero sin ningún espacio en blanco entre ellos.

/* valid css nesting */
.feature {
  p& {
    font-weight: bold;
  }
}

/* invalid css nesting */
.feature {
  &p {
    font-weight: bold;
  }
}

Esta regla permite que el anidamiento de CSS funcione junto con herramientas de preprocesamiento como Sass. En Sass, escribir &p agregaría el selector principal al selector de tipo anidado, y el resultado sería .featurep.

Anidación de reglas @

Las reglas de grupo condicionales de CSS, como @container, @media, @supports y @layer, también se pueden anidar.

.feature {
  @media (min-width: 40em) {
    /* ... */
  }

  @container (inline-size > 900px) {
    /* ... */
  }
}

.feature {
  @supports (display: grid) {
    /* ... */
  }
}

.feature {
  @layer component {
    h2 {
      /* ... */
    }
  }
}

Verifica tus conocimientos

Cuando se usa el anidamiento de CSS, ¿qué representa el selector &?

El selector secundario anidado
Incorrecto.
El selector principal
Correcto.
El selector de elementos secundarios adyacentes más cercano
Incorrecto.

Solo puedes anidar dos niveles de profundidad.

Verdadero
Incorrecto.
Falso
Correcto.

¿Qué reglas @ se pueden anidar?

@media
Correcto.
@container
Correcto.
@import
Incorrecto.
@supports
Correcto.
@layer
Correcto.