CSS Condicional com :has e :nth-last-child

CSS Condicional é uma técnica de CSS moderno para alterar estilos conforme o número de elementos de um componente. Ela vai mudar sua maneira de ver CSS!

Ir para o artigo

Já ouviu falar em CSS Condicional? Pois saiba que é possível usar CSS puro para verificar se o número de um elemento de grupo é menor ou igual a uma determinada quantidade — por exemplo, verificar se uma grid tem 3 ou mais itens.

Isso permite fazer coisas como: um componente ou layout pode mudar com base no número de elementos-filho.

Essa técnica poderosa de CSS é possível graças à pseudo-classe :has, que pode ser combinada com o seletor :nth-last-child para fazer a mágica acontecer.

Se você ainda desconhece ou não está familiarizado com :has(), assista a nosso vídeo exclusivo:

Revisão de :nth-last-child

Um dos pontos-chave dessa técnica é entender que a pseudo-classe :nth-last-child pode ser usada para simular a contagem de elementos-filho.

Considere o seguinte wireframe de uma lista com 5 cards:

Wireframe de lista com 5 itens.

No seguinte CSS, tem-se n + 3:

Que significa: selecione os três primeiros itens do final, contando a partir do terceiro item.

Analisando em mais detalhes, primeiro, é preciso contar 3 itens a partir do final; com isso, o 3º item é, na verdade, o 1º item que é contado até o final da lista.

Explicações adicionais sobre o wireframe anterior, fazendo contagem de itens.

Quando se conta do 3º até o final, estes são os itens selecionados:

Explicações adicionais sobre o wireframe anterior, evidenciando que os itens selecionados serão os 3 primeiros.

Limitações de Quantity Queries em CSS

Conforme explicado no excelente artigo de Heydon Pickering, é possível usar o :nth-last-child como uma Quantity Query (ou Consulta de Quantidade) — tema importante para CSS Condicional, como será mostrado a seguir.

Considere o seguinte planejamento visual para quando houver 3 informações e para quando houver mais do que 3 informações:

Comparativo de layouts: com 3 itens e com 3 itens ou mais, mostrando um exemplo mais básico do quê é possível fazer com CSS Condicional.

Há uma lista de informações que é exibida de forma diferente quando se tem 5 ou mais itens.

Embora isso funcione, ainda é um pouco limitante em alguns aspectos.

Não é possível estilizar o elemento-pai com base no número de elementos

Imagine que seja preciso adicionar display: flex a cada <li> quando houver 5 ou mais itens. Não é possível fazer isso com somente :nth-last-child.

O motivo é que adicionar display: flex forçará cada item a ficar em sua própria linha, o que não corresponde ao planejamento visual a ser alcançado.

Comparativo mostrando lado-a-lado o resultado que se quer e o que se conseguiu chegar até o momento.

É possível corrigir isso com display: inline-flex, mas talvez ainda não seja a solução ideal. O motivo é que o navegador vai contabilizar o espaçamento entre os elementos HTML, que devem ficar assim:

Se isso não for feito, display: inline-flex terá o mesmo efeito que display: flex. Um truque para corrigir isso é reduzir a largura em 1%:

Funcionamento em diferentes tamanhos de viewport

Sem a capacidade de ter controle sobre o pai, não é tão simples estilizar o layout da listagem.

Por exemplo, quando a largura do container ou viewport é menor, é preciso mostrar 1 item por linha.

Mais trabalho para gerenciar o espaçamento

Quando há 3 itens ou menos, o espaçamento é horizontal, e quando são 5 ou mais, o espaçamento é vertical. É possível gerenciar isso manualmente invertendo a margem de horizontal para vertical ou usando a propriedade gap com Flexbox. Mas, novamente, isso força a usar inline-flex para esse caso.

A chave do sucesso

A pseudo-classe :nth-last-child é a chave para construir layouts condicionais. Ao combiná-lo com :has, é possível verificar se um elemento-pai possui, pelo menos, um número específico de itens e estilizá-lo de acordo.

As possibilidades são infinitas!

Casos de uso e exemplos de CSS Condicional com :has e :nth-last-child

Vamos a alguns exemplos e casos de uso CSS condicional com :has e :nth-last-child.

Grid que muda com base no número de elementos-filho

Comparativo de layouts: com 4 itens e com 5 itens ou mais.

Quando é preciso alterar uma grid com base no número de itens, isso não é possível com o CSS atual. Na grid CSS, é possível usar a função minmax() para ter uma grid dinâmica que muda com base no espaço disponível.

O resultado será algo como:

Comparativo mostrando o resultado que se conseguiu chegar até o momento.

O resultado não ficou ideal. Não é possível ter muito controle, já que é necessário ajustar o valor de 150px no minmax(). Pode funcionar muito bem quando tiver 4 itens ou menos e quebrar para 5 itens ou mais.

A solução? Verificar com :has se há 5 itens ou mais e alterar o valor minmax() com base nisso.

Perceba o uso de variáveis CSS, que facilitam a leitura do código, evitam duplicações e tornam manutenções futuras mais fáceis e eficientes.

Veja o vídeo a seguir e observe como as colunas da grid mudam conforme itens são adicionados ou removidos:

Cabeçalho com layout dinâmico

No wireframe a seguir, há um cabeçalho que deve mudar de layout caso seu menu tenha 4 ou mais itens.

Agora você já sabe que com as pseudo-classes CSS :has e :nth-last-child, é possível detectar isso e alterar o layout conforme seja necessário.

Comparativo de layouts: com 2 itens no menu e com 4 itens ou mais, mostrando o quão impressionante a técnica de CSS Condicional pode ser.

A mágica é feita usando esse CSS:

Se estranhou essa sintaxe, assista a nosso vídeo sobre aninhamento nativo (nesting) de CSS:

Seria possível fazer um código melhor? Sim! Mas usando features de CSS que não são bem suportadas (ainda).

O macete seria adicionar uma variável CSS booleana que seria alternada quando o cabeçalho tiver 4 itens ou mais e, em seguida, usar uma style query para alterar o cabeçalho.

E, com isso, definir a variável –layout-2 quando houver 4 ou mais itens de navegação.

É uma solução igualmente elegante e, para alguns, muito melhor do que aninhar todos os estilos CSS num seletor com :has.

Veja a demo em ação:

Seção dinâmica de notícias

Esse é um wireframe de seção de notícias que deve mudar seu layout quando o número de itens for 3 ou mais.

Comparativo de layouts: com 3 itens e com mais de itens, mostrando que CSS Condicional pode ser usado em muitos casos de uso diferentes.

Ao combinar CSS :has e :nth-last-child, torna-se possível criar uma variável CSS de alternância que será verificada por uma style query.

Assumindo que o estilo de card padrão é o horizontal:

Checando o número de elementos .card:

A variável --layout-4 será alternada somente quando se tiver 4 itens ou mais. É possível verificar isso usando uma style query e atualizar .card de acordo.

Veja a demo em ação:

Botões de um modal

Neste exemplo, é preciso controlar dinamicamente o alinhamento dos botões de um modal com base em quantas ações é preciso mostrar.

Considere o seguinte:

Comparativo de layouts: modal com 1 botão e com 2 botões.

Ou seja, quando houver 1 ação, o botão deve ser centralizado; caso contrário, os botões devem ficar alinhados à direita.

E aqui está o CSS:

Achou simples, né? Então você já está pegando o jeito. :)

Veja a demo em ação:

Avatars

Neste exemplo de um projeto editorial, um artigo pode ser escrito por vários autores.

Um padrão comum é empilhar as imagens do autor com espaçamento negativo quando se tem vários autores.

Comparativo de layouts: apresentação de avatar para 1 autor e para 3 ou mais autores.

Usando apenas quantity queries, é possível conseguir o mínimo, que é:

  • Adicionar espaçamento negativo (“empilhar” os avatares);
  • Reduzir o tamanho do avatar quando houver vários.

O CSS acima funciona, mas tem suas limitações. E se for preciso estilizar o próprio contêiner? Bem, é aí que o CSS :has entra com o seu poder.

Primeiro, é preciso verificar e alternar uma variável CSS:

Se essa variável CSS (simulando um booleano) for verdadeira, aplica-se os estilos para avatares múltiplos:

Veja a demo em ação:

Linha do tempo

Outro exemplo interessante em que o CSS Condicional funciona bem é um componente de linha do tempo.

Comparativo de layouts: linha do tempo com 3 itens e com mais de 3 itens, evidenciando que Conditional CSS pode ser usada até para casos difíceis.

Neste exemplo, a linha do tempo deve mudar de uma listagem vertical para um estilo alternado quando tiver 4 ou mais itens.

Primeiro, a técnica de usar :nth-last-child com :has:

Se a condição for atendida, adiciona-se mais estilos, conforme a necessidade:

Usar style queries aqui torna possível reutilizar esse estilo em outra página, favorecendo a componentização:

Código escrito só uma vez que funciona e pode ser usado em todo o projeto.

Veja a demo em ação:

Grid de logos

Uma das complicações de se lidar em CSS é alinhar vários logos e garantir que todos tenham uma boa aparência.

A técnica de CSS condicional torna possível, por exemplo, detectar o número de logos e reduzir um pouco o tamanho deles.

Comparativo de layouts: com 7 logos e com 8 logos ou mais.

O seguinte CSS já dá conta do recado:

Veja a demo em ação:

Conclusão

A combinação de recursos CSS modernos pode levar a novas maneiras empolgantes de criar layouts, e os exemplos deste artigo não foram exceção.

Como foi visto, alterar estilos com base no número de itens pode ser útil em muitos casos de uso diferentes. Além de ser muito legal. :)

Style Queries permitem escrever uma vez e reutilizar em qualquer lugar, favorecendo bastante a componentização.

Usamos cookies para melhorar sua experiência e para ajudar a entender como nosso site é usado. Ao utilizar este site, você aceita o uso de cookies. Consulte nossa política de privacidade para obter mais informações.