Um dos nossos recursos favoritos do pré-processador CSS agora está integrado à linguagem: regras de estilo de aninhamento.
Antes do aninhamento, cada seletor precisava ser declarado explicitamente, separadamente. Isso leva à repetição, ao aumento do tamanho da folha de estilo e a uma experiência de criação dispersa.
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
Depois do aninhamento, os seletores podem ser continuados e as regras de estilo relacionadas a eles podem ser agrupadas.
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } }
O aninhamento ajuda os desenvolvedores a reduzir a necessidade de repetir seletores e também a localizar regras de estilo para elementos relacionados. Ele também pode ajudar os estilos a corresponder ao HTML de destino. Se o componente .nesting no exemplo anterior fosse removido do projeto, você poderia excluir todo o grupo em vez de pesquisar arquivos para instâncias de seletor relacionadas.
O aninhamento pode ajudar com: - Organização - Redução do tamanho do arquivo - Refatoração
O aninhamento está disponível no Chrome 112 e também para teste no Safari Technical Preview 162.
Como começar a usar o aninhamento de CSS
No restante desta postagem,a seguinte caixa de areia de demonstração é usada para ajudar você a visualizar as seleções. Nesse estado padrão, nada é selecionado e tudo fica visível. Ao selecionar as várias formas e tamanhos, você pode praticar a sintaxe e vê-la em ação.

Dentro da caixa de areia, há círculos, triângulos e quadrados. Alguns são pequenos, médios ou grandes. Outros são azuis, rosa ou roxos. Todos estão dentro do elemento contido .demo. A seguir, há uma prévia dos elementos HTML que você vai segmentar.
<div class="demo">
<div class="sm triangle pink"></div>
<div class="sm triangle blue"></div>
<div class="square blue"></div>
<div class="sm square pink"></div>
<div class="sm square blue"></div>
<div class="circle pink"></div>
…
</div>
Exemplos de aninhamento
O aninhamento de CSS permite definir estilos para um elemento no contexto de outro seletor.
.parent {
color: blue;
.child {
color: red;
}
}
Neste exemplo, o .child seletor de classe está aninhado em
o .parent seletor de classe. Isso significa que o seletor .child aninhado só será aplicado a elementos filhos de elementos com uma classe .parent.
Esse exemplo também pode ser escrito usando o símbolo &, para indicar explicitamente onde a classe pai precisa ser colocada.
.parent {
color: blue;
& .child {
color: red;
}
}
Esses dois exemplos são funcionalmente equivalentes, e o motivo de você ter opções ficará mais claro à medida que exemplos mais avançados forem explorados neste artigo.
Selecionar os círculos
Para este primeiro exemplo, a tarefa é adicionar estilos para esmaecer e desfocar apenas os círculos dentro da demonstração.
Sem aninhamento, CSS hoje:
.demo .circle {
opacity: .25;
filter: blur(25px);
}
Com aninhamento, há duas maneiras válidas:
/* & is explicitly placed in front of .circle */
.demo {
& .circle {
opacity: .25;
filter: blur(25px);
}
}
ou
/* & + " " space is added for you */
.demo {
.circle {
opacity: .25;
filter: blur(25px);
}
}
O resultado: todos os elementos dentro de .demo com uma classe .circle estão
desfocados e quase invisíveis:
Selecionar triângulos e quadrados
Essa tarefa exige a seleção de vários elementos aninhados, também chamados de seletor de grupo.
Sem aninhamento, CSS hoje, há duas maneiras:
.demo .triangle,
.demo .square {
opacity: .25;
filter: blur(25px);
}
ou, usando :is()
/* grouped with :is() */
.demo :is(.triangle, .square) {
opacity: .25;
filter: blur(25px);
}
Com aninhamento, há duas maneiras válidas:
.demo {
& .triangle,
& .square {
opacity: .25;
filter: blur(25px);
}
}
ou
.demo {
.triangle, .square {
opacity: .25;
filter: blur(25px);
}
}
O resultado: apenas os elementos .circle permanecem dentro de .demo:
Selecionar triângulos e círculos grandes
Essa tarefa exige um seletor composto, em que os elementos precisam ter as duas classes presentes para serem selecionados.
Sem aninhamento, CSS hoje:
.demo .lg.triangle,
.demo .lg.square {
opacity: .25;
filter: blur(25px);
}
ou
.demo .lg:is(.triangle, .circle) {
opacity: .25;
filter: blur(25px);
}
Com aninhamento, há duas maneiras válidas:
.demo {
.lg.triangle,
.lg.circle {
opacity: .25;
filter: blur(25px);
}
}
ou
.demo {
.lg {
&.triangle,
&.circle {
opacity: .25;
filter: blur(25px);
}
}
}
O resultado, todos os triângulos e círculos grandes estão ocultos dentro de .demo:
Dica profissional com seletores compostos e aninhamento
O símbolo & é seu amigo aqui, porque mostra explicitamente como unir seletores aninhados. Confira o exemplo abaixo:
.demo {
.lg {
.triangle,
.circle {
opacity: .25;
filter: blur(25px);
}
}
}
Embora seja uma maneira válida de aninhar, os resultados não corresponderão aos elementos esperados.
O motivo é que, sem & para especificar o resultado desejado de .lg.triangle,
.lg.circle combinados, o resultado real seria .lg .triangle, .lg
.circle; seletores descendentes.
Selecionar todas as formas, exceto as rosas
Essa tarefa exige uma pseudoclasse funcional de negação, em que os elementos não podem ter o seletor especificado.
Sem aninhamento, CSS hoje:
.demo :not(.pink) {
opacity: .25;
filter: blur(25px);
}
Com aninhamento, há duas maneiras válidas:
.demo {
:not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
ou
.demo {
& :not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
O resultado: todas as formas que não são rosas estão ocultas dentro de .demo:
Precisão e flexibilidade com &
Digamos que você queira segmentar .demo com o seletor :not(). & é necessário para isso:
.demo {
&:not() {
...
}
}
Isso combina .demo e :not() para .demo:not(), em vez do exemplo anterior que precisava de .demo :not(). Esse lembrete é muito importante quando você quer aninhar uma interação :hover.
.demo {
&:hover {
/* .demo:hover */
}
:hover {
/* .demo :hover */
}
}
Mais exemplos de aninhamento
A especificação de CSS para aninhamento está repleta de mais exemplos. Se você quiser saber mais sobre a sintaxe usando exemplos, ela abrange uma ampla variedade de exemplos válidos e inválidos.
Os próximos exemplos vão apresentar brevemente um recurso de aninhamento de CSS para ajudar você a entender a amplitude dos recursos que ele apresenta.
Aninhamento @media
Pode ser muito confuso mudar para uma área diferente da folha de estilo para encontrar condições de consulta de mídia que modificam um seletor e seus estilos. Essa distração desaparece com a capacidade de aninhar as condições diretamente no contexto.
Para conveniência da sintaxe, se a consulta de mídia aninhada estiver modificando apenas os estilos do contexto do seletor atual, uma sintaxe mínima poderá ser usada.
.card {
font-size: 1rem;
@media (width >= 1024px) {
font-size: 1.25rem;
}
}
O uso de & explicitamente também pode ser usado:
.card {
font-size: 1rem;
@media (width >= 1024px) {
&.large {
font-size: 1.25rem;
}
}
}
Este exemplo mostra a sintaxe expandida com &, ao mesmo tempo em que segmenta cartões .large para demonstrar que outros recursos de aninhamento continuam funcionando.
Saiba mais sobre as @regras de aninhamento.
Aninhamento em qualquer lugar
Todos os exemplos até este ponto continuaram ou foram anexados a um contexto anterior. Você pode mudar ou reorganizar completamente o contexto, se necessário.
.card {
.featured & {
/* .featured .card */
}
}
O símbolo & representa uma referência a um objeto seletor (não uma string) e pode ser colocado em qualquer lugar em um seletor aninhado. Ele pode até ser colocado várias vezes:
.card {
.featured & & & {
/* .featured .card .card .card */
}
}
Embora esse exemplo seja um pouco inútil, certamente há cenários em que é útil repetir um contexto de seletor.
Exemplos de aninhamento inválidos
Há alguns cenários de sintaxe de aninhamento que são inválidos e podem surpreender você se você estiver aninhando em pré-processadores.
Aninhamento e concatenação
Muitas convenções de nomenclatura de classe CSS contam com o aninhamento para concatenar ou anexar seletores como se fossem strings. Isso não funciona no aninhamento de CSS, porque os seletores não são strings, mas referências de objetos.
.card {
&--header {
/* is not equal to ".card--header" */
}
}
Uma explicação mais detalhada pode ser encontrada em a especificação.
Exemplo de aninhamento complicado
Aninhamento em listas de seletores e :is()
Considere o seguinte bloco de CSS de aninhamento:
.one, #two {
.three {
/* some styles */
}
}
Este é o primeiro exemplo que começa com uma lista de seletores e continua a aninhar ainda mais. Os exemplos anteriores só terminaram com uma lista de seletores. Não há nada inválido neste exemplo de aninhamento, mas há um detalhe de implementação potencialmente complicado sobre o aninhamento em listas de seletores, especialmente aquelas que incluem um seletor de ID.
Para que a intent do aninhamento funcione, qualquer lista de seletores que não seja o aninhamento mais interno será encapsulada com :is() pelo navegador. Esse encapsulamento mantém o agrupamento da lista de seletores em qualquer contexto criado. O efeito colateral desse agrupamento, :is(.one, #two), é que ele adota a especificidade da pontuação mais alta nos seletores entre parênteses. É assim que :is() sempre funciona, mas pode ser uma surpresa ao usar a sintaxe de aninhamento, porque não é exatamente o que foi criado. O truque resumido: o aninhamento com IDs e listas de seletores pode levar a seletores de especificidade muito alta.
Para recapitular claramente o exemplo complicado, o bloco de aninhamento anterior será aplicado ao documento da seguinte maneira:
:is(.one, #two) .three {
/* some styles */
}
Fique atento ou ensine seus linters a avisar quando o aninhamento estiver dentro de uma lista de seletores que usa um seletor de ID. A especificidade de todo o aninhamento nessa lista de seletores será alta.
Como misturar aninhamento e declarações
Considere o seguinte bloco de CSS de aninhamento:
.card {
color: green;
& { color: blue; }
color: red;
}
A cor dos elementos .card será blue.
Todas as declarações de estilo misturadas são elevadas para a parte de cima, como se tivessem sido criadas antes de qualquer aninhamento. Mais detalhes podem ser encontrados em a especificação.
Há maneiras de contornar isso. O seguinte encapsula os três estilos de cor em &, que mantém a ordem em cascata conforme o autor pretendia. A cor dos elementos .card será vermelha.
.card {
color: green;
& { color: blue; }
& { color: red; }
}
Na verdade, é uma boa prática encapsular todos os estilos que seguem o aninhamento com um &.
.card {
color: green;
@media (prefers-color-scheme: dark) {
color: lightgreen;
}
& {
aspect-ratio: 4/3;
}
}
Detecção de recursos
Há duas ótimas maneiras de detectar o aninhamento de CSS: usar o aninhamento ou usar @supports para verificar a capacidade de análise do seletor de aninhamento.

Usando o aninhamento:
html {
.has-nesting {
display: block;
}
.no-nesting {
display: none;
}
}
Usando @supports:
@supports (selector(&)) {
/* nesting parsing available */
}
Meu colega Bramus tem um ótimo Codepen mostrando essa estratégia.
Depuração com o Chrome DevTools
O suporte atual no DevTools para aninhamento é mínimo. No momento, você vai encontrar estilos representados no painel "Estilos" conforme esperado, mas o rastreamento do aninhamento e do contexto completo do seletor ainda não é compatível. Temos um design e planos para tornar isso transparente e claro.

O Chrome 113 planeja ter suporte adicional para aninhamento de CSS. Fique por dentro das novidades.
O futuro
O aninhamento de CSS está apenas na versão 1. A versão 2 vai apresentar mais açúcar sintático e possivelmente menos regras para memorizar. Há muita demanda para que a análise do aninhamento não seja limitada ou tenha momentos complicados.
O aninhamento é uma grande melhoria na linguagem CSS. Ele tem implicações de criação para quase todos os aspectos arquitetônicos do CSS. Esse grande impacto precisa ser profundamente explorado e compreendido antes que a versão 2 possa ser especificada de maneira eficaz.
Como um pensamento final, aqui está uma demonstração
que usa @scope, aninhamento e @layer juntos. É tudo muito emocionante!
