CSS Nesting nativamente nos browsers

CSS Nesting é umas das features que muita esperava suporte nativo, o recurso é possível via pre-processadores CSS como, por exemplo, SASS e LESS. O suporte nativo veio com algumas particularidades e nesse post nos iremos cobrir-las.

O que é CSS Nesting?

Antes precisamos responder esta pergunta, se você ainda não conhece este recurso ajuda a organizar seu código aninhando seletores, assim reduzindo a quantidade de código escrito. Agora vamos compara as duas formas em antes e depois do css nesting:

Antes:

.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}Code language: CSS (css)

Depois

.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Com os dois códigos acima o resultado é o mesmo a quantidade de linhas são similares mas a repetição dos seletores é menor pois trabalhamos com referências aninhadas. Além disso é muito mais fácil a organização do escopo do CSS sabemos que todo os CSS relacionado ao .nesting está delimitado pela as chaves relacionadas, e por fim, relacionado a manutenção do código, caso o elemento for removido do projeto é muito mais fácil realizar a remoção do cógido do elemento .nesting.

Em resumo, o nesting CSS vai ajudar você com:

  • Organização
  • Reduzindo o tamanho do arquivo
  • reestruturação

O recurso de CSS nesting está disponível na versão 112 e também disponível na versão 162 do Safari.

Como trabalhar com CSS nesting

Agora vejamos como trabalhar como recurso do CSS nesting, para isso utilizaremos a seguinte estrutura CSS:

    <header class="main-header">
      <div class="triangle-right"></div>
      <h1 class="title">Brasil...</h1>
      <div class="circle"></div>
    </header>

    <div class="brazilian-flag">
      <div class="lozenge">
        <div class="triangle-left"></div>
        <div class="triangle-right"></div>
      </div>
      <div class="circle"></div>
    </div>

    <footer class="main-footer">
      <div class="circle"></div>
      <h2 class="title">sil...sil!!!</h2>
      <div class="triangle-left"></div>
    </footer>Code language: HTML, XML (xml)

E o seguinte CSS:


.main-footer,
.main-header {
  display: flex;
  gap: 1rem;
  justify-content: center;
  align-items: center;
}

.title {
  color: #2800ff;
  font-family: HK Grotesk;
  font-style: normal;
  font-weight: bold;
  font-size: 100px;
  line-height: 105%;
  margin: 0;
}

.triangle-left,
.triangle-right {
  width: 0;
  height: 0;
  border-top: 50px solid transparent;
  border-bottom: 50px solid transparent;
}

.triangle-left {
  border-right: 100px solid yellow;
}

.triangle-right {
  border-left: 100px solid yellow;
}

.circle {
  overflow: hidden;
  z-index: 2;
  background-color: blue;
  width: 80px;
  height: 80px;
  border-radius: 100%;
  aspect-ratio: 1 / 1;
}

.brazilian-flag {
  position: relative;
  background-color: green;
  width: 250px;
  height: 150px;
  margin: 5em auto;
}Code language: CSS (css)

Até o momento o resultado parece arte abstrata:

Exemplo inicial para ser trabalhado com CSS nesting

Isso porque não definimos nenhuma regra específica, por exemplo caso queiramos mover o círculo para o centro da bandeira aplicamos o seguinte CSS:

.brazilian-flag .circle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%)
}Code language: CSS (css)

Para se adaptar a diversas situações, o nesting CSS tem dois formatos válidos:

formato 1:

.brazilian-flag {
  .circle {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%)
  }
}

formato 2:

.brazilian-flag {
  & .circle {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%)
  }
}

Inicialmente pode aparecer muita complicação para pouco resultado, mas isso é num único seletor o problema de repetição do CSS, vai a acontecer a medida que o nosso arquivo cresce aplicando estilo a mais elementos.

Caso queiramos alinhar ao centro o .circle e o .lozenge faremos da seguinte forma:

.brazilian-flag {
  .circle,
  .lozenge {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%)
  }
}

Assim temos os dois elementos alinhados ao centro:

Primeiras alterações utilizando CSS nesting.

Estamos quase lá agora temos duas setas que precisam formar o losango na bandeira, mas nesse caso não queremos afetar as setas que estão no header e no footer.

Para isso vamos adicionar o seguinte código:

.brazilian-flag {
  .circle,
  .lozenge {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%)
  }

 .triangle-right,
 .triangle-left {
   position: absolute;
   transform: translateY(-50%);
 }

 .triangle-left {
   right:100%;
 } 
}

Com essas alterações, temos as modificações aplicadas apenas nos triângulos da bandeira, assim temos a nossa bandeira feita com CSS:

elementos alinhados utilizando css nesting

Quando o & é importante?

Nos exemplos que utilizamos até o momento não tinha nenhuma utilidade especial do &, simplesmente uma variação dos formatos, mas existem alguns casos específicos que o uso do & é interessante.

Uso de nesting CSS com pseudo-seletores

Por exemplo, caso queiramos incluir uma animação na nossa bandeira, podemos fazer da seguinte forma:

/* primeiro criamos uma animação */
@keyframes beat {
  to {
    transform: translate(-50%, -50%) scale(1.1);
  }
}

.brazilian-flag {
  &:hover .circle {
    animation: beat 200ms infinite alternate;
  }

  &:hover .lozenge {
    animation: beat 400ms infinite alternate;
  }
}Code language: JavaScript (javascript)

Outro exemplo também pode ser utilizado com os seletores before e after.

.brazilian-flag {
 .circle {
    &:after {
      content: "ordem e diamantes";
      background-color: white;
      white-space: nowrap;
      display: block;
      width: 100%;
      font-size: 0.4rem;
      top: 50%;
      position: absolute;
      text-align: center;
      transform: translateY(-50%) rotate(10deg);
      padding: 0.1rem;
    }
  }
}Code language: JavaScript (javascript)

E o que mais podemos fazer?

Combinação com media queries

.card {
  font-size: 1rem;

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

Mudança de ordem de seletores:

.card {
  .featured & {
    /* .featured .card */
  }
}Code language: JavaScript (javascript)

Cenários inválidos com CSS nesting

Existem alguns cenários de sintaxe de aninhamento que são inválidos e podem surpreendê-lo até se você utiliza pre-processadores. Uma folha de dicas para a sintaxe de aninhamento válida são os items:

& @ : . > ~ + # [ *Code language: PHP (php)

Esses simbolos são válidos quando adicionados dentro de um seletor principal. Outro caso que é muito comum em pre-processadores é a concatenação de seletores, neste caso com nesting CSS no exemplo abaixo, não gera um novo seletor:

.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}Code language: JavaScript (javascript)

Nomes de tags aninhada com seletores precisam vir acompanhada do & para ser um seletor válido. Exemplo:

Caso inválido:

.card {
  h1 {
    /* 🛑 h1 does not start with a symbol */
  }
}Code language: JavaScript (javascript)

Caso válido:

.card {
  & h1 {
    /* ✅ now h1 starts with a symbol */
  }

  /* or */

  :is(h1) {
    /* ✅ now h1 starts with a symbol */
  }
}Code language: JavaScript (javascript)

Como verificar se o browser tem suporte?

Para realizar a detecção de suporte ao CSS nesting há duas maneiras, uma utilizando o próprio recurso de aninhamento para conferir o suporte ou utilizando o seletor @supports.

@supports (selector(&)) {
  /* css nesting parsing available */
}Code language: CSS (css)

Com isso vamos fechando o nosso artigo, espero que tenha gostado de saber mais sobre o recurso de CSS nesting, essa será sua primeira versão numa versão 2 serão introduzidos novos recursos para melhorar a produtividade dos desenvolvedores front-end. Esse post foi baseado no post da documentação oficial do Chrome.

Para mais artigos sobre CSS confira:


Publicado

em

,

por

Tags:

Comentários

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *