Transição de CSS

Um dos nossos recursos favoritos de pré-processador de CSS agora está integrado à linguagem: o aninhamento de regras de estilo.

Adam Argyle
Adam Argyle

Antes do aninhamento, cada seletor precisava ser declarado explicitamente, separadamente do se complementam. Isso leva à repetição, folha de estilo em massa e à criação esparsa. do usuário.

Antes
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

Após o aninhamento, os seletores podem ser regras de estilo contínuas e relacionadas a ele podem ser agrupadas.

Depois
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Tente fazer isso no navegador.

A aninhamento ajuda os desenvolvedores porque reduz a necessidade de repetir seletores e também co-localizar regras de estilo para elementos relacionados. Também pode ajudar os estilos a combinar HTML segmentado. Se o componente .nesting no exemplo anterior era removido do projeto, você pode excluir todo o grupo em vez de pesquisar para instâncias de seletores relacionadas.

A Transição pode ajudar com: - Organização - Redução do tamanho do arquivo - Refatoração

O aninhamento está disponível a partir do Chrome 112 e também para teste na Prévia técnica do Safari 162.

Começar a usar a Transição de CSS

Ao longo desta postagem,o sandbox de demonstração a seguir é usado para ajudar você visualizará as seleções. Neste estado padrão, nada é selecionado e tudo fica visível. Ao selecionar as várias formas e tamanhos, é possível praticar a sintaxe e vê-la em ação.

Uma grade colorida de círculos, triângulos e quadrados pequenos e grandes.

Dentro da sandbox há círculos, triângulos e quadrados. Algumas são pequenas e médias ou grandes. Outras são azul, rosa ou roxo. Eles estão todos dentro do .demo que contém o elemento. Esta é uma visualização dos elementos HTML que você segmentação.

<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 dentro do contexto de outro seletor.

.parent {
  color: blue;

  .child {
    color: red;
  }
}

Neste exemplo, o seletor de classe .child está aninhado o seletor de classe .parent. Isso significa que o seletor .child aninhado só se aplicam a elementos filhos de elementos com uma classe .parent.

Este exemplo poderia ser escrito usando o símbolo &, para explicitamente indicam onde a classe pai deve ser colocada.

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

Esses dois exemplos são funcionalmente equivalentes, e você tem opções à medida que exemplos mais avançados são explorados neste artigo.

Seleção dos círculos

Para este primeiro exemplo, a tarefa é adicionar estilos para esmaecer e desfocar apenas o círculos na demonstração.

Sem aninhamento, CSS atual:

.demo .circle {
  opacity: .25;
  filter: blur(25px);
}

Com o 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 são desfocados e quase invisível:

A grade colorida de formas não tem mais círculos,
    elas ficam bem fracas em segundo plano.
Veja uma demonstração

Selecionando triângulos e quadrados

Essa tarefa requer a seleção de vários elementos aninhados, também chamado de seletor de grupo.

Sem aninhamento, o CSS atual oferece 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 o aninhamento, há duas maneiras válidas:

.demo {
  & .triangle,
  & .square {
    opacity: .25;
    filter: blur(25px);
  }
}

ou

.demo {
  .triangle, .square {
    opacity: .25;
    filter: blur(25px);
  }
}

Como resultado, apenas os elementos .circle permanecem dentro de .demo:

A grade colorida de formas só tem círculos,
    todas as outras formas são quase invisíveis.
Veja uma demonstração

Seleção de triângulos e círculos grandes

Essa tarefa requer um seletor composto, em que elementos devem ter as duas classes presentes para serem selecionados.

Sem aninhamento, CSS atual:

.demo .lg.triangle,
.demo .lg.square {
  opacity: .25;
  filter: blur(25px);
}

ou

.demo .lg:is(.triangle, .circle) {
  opacity: .25;
  filter: blur(25px);
}

Com o 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);
    }
  }
}

Como resultado, todos os triângulos e círculos grandes estão escondidos dentro de .demo:

A grade colorida tem apenas formas pequenas e médias visíveis.
Veja uma demonstração
Dica profissional com seletores compostos e aninhamento

O símbolo & é seu amigo aqui, já que mostra explicitamente como adicionar elementos aninhados seletores. Veja o exemplo a seguir:

.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 combinado, o resultado real seria .lg .triangle, .lg .circle. seletores descendentes.

Selecionar todas as formas exceto as rosas

Essa tarefa requer uma pseudoclasse funcional de negação, em que os elementos não podem têm o seletor especificado.

Sem aninhamento, CSS atual:

.demo :not(.pink) {
  opacity: .25;
  filter: blur(25px);
}

Com o 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 rosa ficam ocultas dentro de .demo:

A grade colorida agora é monocromática, mostrando apenas formas rosas.
Veja uma demonstração
Precisão e flexibilidade com o &

Digamos que você queira segmentar .demo com o seletor :not(). & é obrigatório para que:

.demo {
  &:not() {
    ...
  }
}

Isso compõe .demo e :not() em .demo:not(), em oposição ao anterior que precisava de .demo :not(). Esse lembrete é muito importante quando para aninhar uma interação :hover.

.demo {
  &:hover {
    /* .demo:hover */
  }

  :hover {
    /* .demo :hover */
  }
}

Mais exemplos de aninhamento

A especificação CSS para aninhamento é com mais exemplos. Para saber mais sobre a sintaxe por meio de exemplos, ela abrange uma ampla gama de exemplos válidos e inválidos.

Os próximos exemplos apresentarão brevemente um recurso de aninhamento de CSS, para que você entender a amplitude de funções que ela introduz.

Transição de @media

Pode ser uma distração se mover para uma área diferente da folha de estilo para encontrar condições da consulta de mídia que modificam um seletor e seus estilos. Essa distração não é mais possível aninhar as condições dentro do contexto.

Para facilitar a sintaxe, se a consulta de mídia aninhada só modificar os estilos para o contexto do seletor atual, uma sintaxe mínima pode ser usada.

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    font-size: 1.25rem;
  }
}

O uso explícito de & também pode ser utilizado:

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    &.large {
      font-size: 1.25rem;
    }
  }
}

Este exemplo mostra a sintaxe expandida com &, além de segmentar .large para demonstrar outros recursos de aninhamento continuam funcionando.

Saiba mais sobre o aninhamento de @rules.

Aninhamento em qualquer lugar

Todos os exemplos até aqui continuaram ou foram anexados a um contexto anterior. É possível 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 de um seletor aninhado. Ele pode até mesmo ser colocado horários:

.card {
  .featured & & & {
    /* .featured .card .card .card */
  }
}

Esse exemplo é um pouco inútil, mas certamente há cenários em que de repetir um contexto de seletor é útil.

Exemplos de aninhamento inválidos

Alguns cenários de sintaxe de aninhamento são inválidos e podem surpreender você caso você tenha feito o aninhamento em pré-processadores.

Aninhamento e concatenação

Muitas convenções de nomenclatura de classes CSS contam que o aninhamento pode concatenar ou anexam seletores como se fossem strings. Isso não funciona no aninhamento de CSS, os seletores não são strings, são referências de objetos.

.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}

Uma explicação mais detalhada pode ser encontrada na especificação.

Exemplo complicado de aninhamento

Aninhamento nas listas de seletores e :is()

Considere o seguinte bloco CSS de aninhamento:

.one, #two {
  .three {
    /* some styles */
  }
}

Esse é o primeiro exemplo que começa com uma lista de seletores e continua a aninhamento. Os exemplos anteriores tinham terminado apenas 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 dentro de listas de seletores, especialmente aqueles que incluem um seletor de ID.

Para que o intent do aninhamento funcione, qualquer lista de seletores que não for o aninhamento mais interno será unida a :is() pelo navegador. Esse ajuste 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 em resumo: 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 desta forma:

:is(.one, #two) .three {
  /* some styles */
}

Fique atento ou ensine os lints a avisarem quando você fizer o aninhamento 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 combinar aninhamento e declarações

Considere o seguinte bloco CSS de aninhamento:

.card {
  color: green;
  & { color: blue; }
  color: red;
}

A cor dos elementos .card será blue.

Todas as declarações de estilo misturado são elevadas para a parte superior, como se fossem criados antes da ocorrência de qualquer aninhamento. Confira mais detalhes nas especificações.

Existem maneiras de evitar isso. Confira abaixo os três estilos de cores em &, que mantém a ordem em cascata conforme a intenção do autor. A cor do .card elementos serão vermelhos.

.card {
  color: green;
  & { color: blue; }
  & { color: red; }
}

Na verdade, é recomendável unir todos os estilos que seguem o aninhamento com uma &.

.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 aninhamento @supports para verificar o recurso de análise do seletor de aninhamento.

Uma captura de tela da demonstração do Codepen da Bramus perguntando se o navegador oferece suporte
  Aninhamento de CSS. Abaixo dessa pergunta, há uma caixa verde indicando que eles são compatíveis.

Como usar o aninhamento:

html {
  .has-nesting {
    display: block;
  }

  .no-nesting {
    display: none;
  }
}

Utilizando @supports:

@supports (selector(&)) {
  /* nesting parsing available */
}

Bramus (link em inglês) tem um ótimo Codepen que mostra essa estratégia.

Como depurar com o Chrome DevTools

O suporte atual para aninhamento no DevTools é mínimo. Atualmente, você encontra Os estilos são representados no painel Styles como esperado, mas rastrear o aninhamento e o contexto completo do seletor ainda não é suportado. Temos um design e planos para deixar isso transparente e claro.

Uma captura de tela da sintaxe de aninhamento do Chrome DevTools.

O Chrome 113 planeja ter mais suporte para o aninhamento de CSS. Fique por dentro das novidades.

O futuro

A Transição de CSS está somente na versão 1. A versão 2 introduz mais facilidade sintática e possivelmente menos regras para memorizar. Há muita demanda para que a análise do aninhamento não seja limitada ou momentos complexos.

A Transição é uma grande melhoria na linguagem CSS. Tem implicações na criação a quase todos os aspectos arquitetônicos dos CSS. Esse grande impacto precisa ser profundamente exploradas e compreendidas antes da versão 2 ser efetivamente especificada.

Para finalizar, confira uma demonstração que usa @scope, aninhamento e @layer juntos. É tudo muito emocionante!

Um cartão claro em um fundo cinza. O cartão tem um título e texto,
  alguns botões de ação e uma imagem no estilo cyber punk.