FNSP Web Page

O seletor que faltava ao CSS: :has()

O CSS sempre soube descer: escolher os filhos de um elemento, os irmãos a seguir, os descendentes. Nunca soube subir — não havia forma de dizer "o cartão que tem uma imagem lá dentro".

O :has() resolve isso, e está em todos os browsers atuais.

1. Ler ao contrário

/* Um cartão que tenha imagem fica com o texto centrado */
.cartao:has(img) {
  text-align: center;
}

/* Um formulário com um campo inválido acende a moldura */
form:has(:invalid) {
  border-color: crimson;
}

/* Uma lista sem itens nenhuns desaparece */
ul:not(:has(li)) {
  display: none;
}

O que o seletor escolhe é sempre o que está à esquerda do :has(). O que vai lá dentro é a condição.

2. Onde poupa mesmo JavaScript

O caso clássico é a etiqueta de um campo que reage ao estado dele. Antes, era um listener no change e uma classe posta à mão:

/* A etiqueta de uma opção escolhida */
label:has(input:checked) {
  font-weight: 600;
  background: #e8f5e9;
}

/* Um campo obrigatório por preencher, mas só depois de a pessoa lhe tocar */
label:has(input:required:invalid:not(:placeholder-shown)) {
  color: crimson;
}

3. Combinar com os irmãos

Dentro do :has() cabe qualquer seletor, incluindo os de irmãos — o que dá coisas que não tinham como se escrever:

/* Um título seguido imediatamente de uma imagem cola-se a ela */
h2:has(+ figure) {
  margin-bottom: 0.25rem;
}

/* O artigo que contém o elemento em foco */
article:has(:focus-visible) {
  outline: 2px solid;
}

4. Uma nota de cautela

O :has() obriga o browser a reavaliar estilos de um antepassado quando um descendente muda. É rápido, mas não é grátis: usá-lo numa regra que apanhe muitos elementos e que dependa de estados que mudam a cada tecla é a forma de o notar. Para o resto — a esmagadora maioria dos casos — é o seletor que faltava há vinte anos.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.