Aninhamento

Aninhar regras de estilo CSS pode tornar suas folhas de estilo mais organizadas, fáceis de ler e de manter.

Visão geral

Agora que você aprendeu sobre seletores, provavelmente está se perguntando como organizá-los melhor nas suas folhas de estilo. Imagine que você esteja aplicando estilos a itens dentro de uma seção de "recursos" no seu site. Com o aninhamento, é possível agrupar esses estilos dentro da regra .feature desta forma:

.feature {
  button {
    color: blue;
  }

  .link {
    color: red;
  }

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

Isso seria o mesmo que escrever cada estilo separadamente:

.feature button {
  color: blue;
}

.feature .link {
   color: red;
}

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

O aninhamento pode ter quantas camadas forem necessárias.

.feature {
  .heading {
    color: blue;

    a {
      color: green;
    }
  }
}

Agrupamento e estabelecimento de relações

O aninhamento permite agrupar e estabelecer relações entre regras de estilo de maneira mais concisa.

Por padrão, a regra aninhada será relacionada à regra externa como um combinador descendente. Use seletores nas regras aninhadas para mudar as relações.

/* 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;
  }
}

Definir relações explícitas com o seletor &

Você também pode usar o seletor & para ser mais explícito ao aninhar regras de estilo. Pense em & como um símbolo que representa o seletor principal.

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

Isso seria equivalente a escrever os estilos assim:

.feature button {
  color: blue;
}

Quando & é obrigatório

Sem &, os seletores aninhados serão seletores descendentes do seletor principal. Para formar seletores compostos, & é obrigatório.

.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 */
  }
}

Você também pode mudar o contexto e colocar o seletor & no final ou nos dois lados do seletor de filhos.


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

No último exemplo, estamos adicionando estilos para imagens dentro de um elemento com a classe .my-component. Isso pode ser útil se você estiver trabalhando em um projeto em que não é possível adicionar um class ou um id a um elemento.

Aninhamento e especificidade

Assim como :is(), o seletor de aninhamento usa a especificidade do seletor com a maior especificidade na lista de seletores do elemento pai.

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

.intro a {
  color: blue;
}

A primeira regra segmenta todos os links dentro dos elementos #main-header e .intro, a eles uma cor verde.

A segunda regra tenta substituir isso para deixar azuis os links dentro do elemento .intro.

Podemos entender por que isso não funciona se analisarmos a especificidade de cada regra.

/* 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;
}

Como a primeira regra tem um id na lista de seletores, e as regras aninhadas usam a especificidade do seletor com a maior especificidade, ela tem uma especificidade maior do que a segunda regra. Os links ficam verdes mesmo para elementos a que não estão dentro de um elemento com o seletor #main-header.

Aninhamento inválido

Assim como :is(), o seletor de aninhamento não pode representar pseudoelementos.

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

  & {
    border: 1px solid navy;
  }
}

Você esperaria que o blockquote e os pseudoelementos tivessem texto e bordas coloridos em navy, mas não é o caso. Como o seletor & não pode representar pseudoelementos, os estilos de borda aninhados só serão aplicados à blockquote.

Ao criar seletores compostos usando & e seletores de tipo, o seletor de tipo precisa vir primeiro, sem espaços em branco entre eles.

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

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

Essa regra permite que o aninhamento de CSS funcione com ferramentas de pré-processamento, como o Sass. Em Sass, escrever &p anexaria o seletor principal ao seletor de tipo aninhado, e o resultado seria .featurep.

Aninhamento de at-rules

As regras de grupo condicionais do CSS, como @container, @media, @supports e @layer, também podem ser aninhadas.

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

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

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

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

Teste seu conhecimento

Ao usar o aninhamento de CSS, o que o seletor & representa?

O seletor de elementos filhos aninhados
Incorreto.
O seletor de elemento pai
Correto.
o seletor de irmão mais próximo
Incorreto.

É possível aninhar apenas dois níveis.

Verdadeiro
Incorreto.
Falso
Correto.

Quais regras at podem ser aninhadas?

@media
Correto.
@container
Correto.
@import
Incorreto.
@supports
Correto.
@layer
Correto.