Resumo

  • No rascunho Selectors Level 4 de novembro de 2018, o W3C descreveu :has() para selecionar um elemento conforme um filho ou irmão seguinte, mas deixou a função fora do perfil ativo de CSS.
  • Em maio de 2022, os perfis foram eliminados e :has() passou a ser opcional e em risco; a revisão de novembro proibiu aninhar :has() e restringiu pseudo-elementos em seu argumento.

Na capa de um jornal digital, alguns cartões trazem uma foto e outros sobrevivem só de manchete. A imagem pede espaço. O contorno do cartão precisa mudar. Selecionar a imagem dentro dele é trabalho antigo para CSS; selecionar o contorno por causa da imagem exigia mandar um recado extra. O template acrescentava uma classe, um script vasculhava os filhos ou alguém marcava em duplicidade aquilo que o documento já dizia. A família estava sentada à mesa, mas o pai pedia um relatório para descobrir quem tinha chegado.

O rascunho do W3C de 21 de novembro de 2018 trazia o verbo dessa pergunta: :has(). No exemplo a:has(> img), o link é selecionado porque possui uma imagem como filha direta. O link é o assunto da regra; a imagem é a prova. Outro exemplo, dt:has(+ dt), seleciona um termo de definição seguido imediatamente por outro termo. O apelido «seletor de pai» vende bem a ideia, mas o segundo caso mostra que há mais gente na reunião. A relação também pode apontar para o irmão seguinte.

Em 2018, essa pergunta ainda tinha horário de visita restrito. O documento dividia os seletores em perfil ativo, adequado à correspondência CSS do navegador, e perfil de instantâneo, adequado a uma árvore estática examinada num momento específico. querySelector() aparecia como exemplo do segundo. :has() estava no instantâneo e entre as exceções do perfil ativo. Era possível formular a pergunta sobre a imagem numa consulta; a folha de estilo viva ficava sem essa ferramenta segundo o rascunho. O próprio texto convidava implementadores a revisar a divisão. A fechadura ainda precisava de engenheiros.

O rascunho de 7 de maio de 2022 mudou o desenho da porta. O histórico de alterações registra a remoção dos perfis e a classificação de :has() como opcional e «at-risk». Desapareceu a regra geral que colocava a pergunta relacional no lado das consultas paradas e fora do CSS ativo. Cada implementação conservou a escolha de oferecer a função naquele texto. O convite estava na mesa; os navegadores decidiriam se compareceriam.

O mecanismo é mais amplo que uma árvore genealógica. Em a:has(> img), > exige a filha imediata. Em dt:has(+ dt), + exige o irmão que vem logo depois. Uma moldura de cartão pode olhar para uma foto interna; um termo pode olhar para o próximo termo. O sujeito continua antes dos dois pontos. O argumento entrega a condição relativa a ele. O documento permanece com as mesmas peças, e a moldura ganha liberdade para se vestir segundo as peças que realmente abriga.

O texto de maio de 2022 inclui um teste de pontuação que faria um revisor parar o café. section:not(:has(h1, h2, h3, h4, h5, h6)) seleciona uma seção sem títulos descendentes. section:has(:not(h1, h2, h3, h4, h5, h6)) pergunta se a seção contém qualquer descendente que não seja um título. Uma seção com belo título e um parágrafo comum satisfaz a segunda frase. Um parêntese trocado muda a pergunta inteira. Quando o CSS vira editor, a pontuação ganha crachá de chefe.

A revisão de 11 de novembro de 2022 estabeleceu limites para a curiosidade. Não permite :has() dentro de :has() e, de modo geral, impede pseudo-elementos no argumento. O texto explica a razão dos pseudo-elementos: alguns existem conforme o estilo de seus ancestrais. Se o ancestral passasse a decidir o próprio estilo consultando uma peça criada por aquele estilo, a conversa poderia girar em círculo. A reunião de família precisa terminar antes da próxima edição do jornal.

O histórico de publicação do W3C põe as versões de 2018 e 2022 em sequência. O navegador recebe a tarefa comum de testar relações na árvore do documento. A redação decide qual relação deve alterar a leitura: uma foto que pede respiro, termos vizinhos que formam uma sequência, uma seção sem título que precisa ser localizada. O contorno do cartão pode reagir ao conteúdo que já existe, em vez de depender de uma ficha duplicada colada do lado de fora.

O pai abriu a correspondência. Havia uma foto dos filhos e, para surpresa de todos, um bilhete do vizinho.