Uma das limitações mais enlouquecedoras do CSS foi por muito tempo sua incapacidade de selecionar elementos com base em seus filhos ou irmãos anteriores, principalmente, como selecionar irmãos anteriores com CSS.
Isso impossibilitou a construção de seletores CSS que pudessem ter como alvo irmãos anteriores de um elemento, mas a pseudoclasse has:()
(junto com :not()
, :where()
e :is()
dos seletores de nível 4) meio que fez com que as antigas limitações caíssem e abriu um novo mundo de possibilidades ao trabalhar com seletores CSS.
Como selecionar o irmão anterior
Imagine que existe uma série de elementos e se deseja selecionar e estilizar aquele que vem antes do círculo:
1 2 3 4 5 |
<div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="circle"></div> <div class="box"></div> |
O combinador irmão adjacente (+
) pode selecionar um elemento que segue imediatamente outro elemento, e podemos combiná-lo com :has()
para selecionar apenas o .box
imediatamente seguido por um .circle
(ou da perspectiva do círculo, seu anterior irmão):
1 2 3 4 |
.box:has(+ .circle) { height: 40px; width: 40px; } |
Você pode pensar neste seletor como (i) selecionando todas as caixas e, em seguida, (ii) filtrando os elementos apenas para aqueles que correspondem ao padrão “caixa + círculo”, que retornará apenas o irmão anterior do círculo.
Se ainda não conhece o seletor :has()
, confira nosso vídeo:
Como selecionar o enésimo (nth) irmão anterior
É possível usar o combinador irmão adjacente para selecionar qualquer elemento específico que precede outro.
Podemos selecionar o segundo irmão anterior usando 2 combinadores de irmãos adjacentes:
1 2 3 4 |
.box:has(+ * + .circle) { height: 40px; width: 40px; } |
Se desejar, você também pode definir o escopo do seletor para uma classe (em vez do universal *
). Neste caso, irmãos .box
:
1 2 3 4 |
.box:has(+ .box + .circle) { height: 40px; width: 40px; } |
Esse seletor pode ser difícil de lidar com o parse. Pode ajudar pensar nisso como selecionar todas as caixas (.box
) e, em seguida, filtrar esses elementos para que o .box
restante seja aquele que corresponda ao padrão “self + box + circle”, que será apenas o segundo irmão anterior .
Se você quiser selecionar o terceiro irmão anterior, você pode usar 3 combinadores de irmãos adjacentes:
1 2 3 4 |
.box:has(+ * + * + .circle) { height: 40px; width: 40px; } |
E assim por diante. Você pode continuar adicionando combinadores de irmãos adjacentes (+
) pelo tempo que desejar, para selecionar qualquer enésimo elemento anterior.
Como selecionar todos os irmãos anteriores
Se você quiser selecionar todos os irmãos anteriores, pode combinar :has()
com o combinador geral de irmãos (~
), que corresponde ao segundo elemento desde que siga o primeiro, independentemente de sua posição:
1 2 3 4 |
.box:has(~ .circle) { height: 40px; width: 40px; } |
Em outras palavras, desde que o .box
neste exemplo seja seguido por um .circle
em algum ponto, o .box
será selecionado e estilizado.
Como selecionar todos os irmãos anteriores, exceto o irmão adjacente
Finalmente, podemos combinar o combinador irmão geral (~
) com o combinador irmão adjacente (+
) e selecionar todos os elementos anteriores, exceto o mais adjacente:
1 2 3 4 |
.box:has(~ * + .circle) { height: 40px; width: 40px; } |
Este seletor seleciona qualquer .box
que corresponda ao padrão “auto seguido por em qualquer ponto uma caixa + círculo”.
Conclusão
Em qualquer tecnologia, em especial tecnologias Web, é de se esperar que antigas limitações sejam superadas com seu avanço e chegada de novas features.
Aqui no dpw já dissemos há muito tempo que :has() foi uma das principais features de CSS desde o surgimento da linguagem. Ainda levará anos para que seu potencial real de uso seja descoberto.
De qualquer maneira, agora você já sabe como selecionar irmãos anteriores com CSS usando :has()
e esse novo poder de CSS, certamente, será bastante útil em muitas situações de estilização.