// css · Web Platform Advent #17
O seletor CSS :has(): o seletor de pai, explicado (2026)
A pseudo-classe relacional :has() permite estilizar um elemento com base no que ele contem ou no que vem depois dele - o tao esperado seletor de pai. Como funciona, exemplos reais, suporte dos navegadores e as armadilhas.
A pseudo-classe :has() e o recurso que os autores de CSS pediram durante duas decadas: uma forma de estilizar um elemento com base no que esta dentro dele, ou no que vem depois dele. Costuma ser chamada de "seletor de pai", embora seja na verdade mais poderosa do que isso - trata-se de um seletor relacional. Ela agora esta presente em todos os navegadores modernos, entao voce pode usa-la em producao hoje.
A ideia basica
Um seletor CSS comum mira um elemento pelo seu proprio tipo, classe ou estado. O :has() inverte isso: ele mira um elemento por causa dos elementos que ele contem. Voce escreve o pai e, em seguida, :has(...) com um seletor para aquilo que deve estar dentro.
/* Style any .card that contains an <img> */
.card:has(img) {
padding: 0;
}
/* Style a <figure> only when it has a caption */
figure:has(figcaption) {
border: 1px solid #ddd;
} O elemento que de fato recebe o estilo e aquele que vem antes do :has() - o .card e o figure, e nao a imagem ou a legenda dentro dele. Esse e todo o truque: a condicao e sobre os descendentes, mas o alvo e o ancestral.
Ele e relacional, nao apenas "de pai"
Como voce pode colocar combinadores dentro de :has(), ele faz muito mais do que olhar para os filhos. Voce pode reagir a irmaos, algo que era impossivel em CSS antes.
/* A heading that is immediately followed by a paragraph */
h2:has(+ p) {
margin-bottom: 0.25rem;
}
/* A form that contains an invalid field */
form:has(input:invalid) {
border-left: 3px solid crimson;
}
/* A label whose related required input is empty and focused */
.field:has(input:required:placeholder-shown) .hint {
opacity: 1;
} Esse segundo exemplo e o tipo de coisa para a qual as pessoas costumavam recorrer ao JavaScript: mudar a aparencia de um formulario inteiro (ou de qualquer contêiner) com base no estado de um controle dentro dele. Com :has() e uma linha de CSS, e ele se atualiza ao vivo conforme o usuario digita.

Padroes praticos
- Consultas de quantidade e conteudo: estilize uma galeria de forma diferente quando ela tem exatamente uma imagem em vez de muitas -
.gallery:has(img:only-child). - Estilizacao do irmao anterior: o CSS so conseguia olhar para frente com
+e~; o:has()permite que um elemento anterior reaja a um posterior, por exemplolabel:has(+ input:checked). - Layout que se adapta ao conteudo: de a um card um layout de duas colunas apenas quando ele realmente contem uma imagem, e uma unica coluna quando nao contem.
- Estados de formulario e validacao: destaque um fieldset inteiro quando qualquer controle dentro dele for invalido, sem uma linha de script.
Suporte dos navegadores
O suporte e amplo em 2026. O :has() chegou ao Chrome e ao Edge 105 (agosto de 2022) e ao Safari 15.4, com o Firefox se juntando na versao 121 (dezembro de 2023). Isso significa que ele agora esta disponivel nas versoes atuais de todos os principais navegadores, e e seguro confiar nele para a maioria dos publicos. Para navegadores mais antigos voce pode tratar os estilos com :has() como uma melhoria progressiva, ja que um navegador que nao entende o seletor simplesmente ignora a regra.
Armadilhas que vale conhecer
- Voce nao pode corresponder pseudo-elementos dentro de :has(). Seletores como
::beforenao sao permitidos como argumento. - O proprio :has() nao e permitido dentro de :has(). Voce nao pode aninhar uma verificacao relacional dentro de outra.
- Mantenha o escopo razoavel. Seletores muito amplos como
body:has(...)que forcam o navegador a reverificar grandes partes da pagina podem custar desempenho em documentos grandes e que se atualizam com frequencia. Na pratica, seletores com escopo em componentes estao bem; os motores otimizaram os casos comuns. - O alvo e o sujeito, nao a correspondencia. Se uma regra nao esta se aplicando, verifique se voce esta estilizando o elemento antes do
:has(), e nao o que esta dentro dele.
FAQ
O :has() e realmente o seletor de pai do CSS? Na pratica sim, e mais. Ele seleciona um ancestral com base em seus descendentes, que e o caso classico de uso do "seletor de pai", mas como aceita combinadores tambem pode selecionar com base em irmaos seguintes, entao e melhor descrito como um seletor relacional.
Posso usar :has() em producao em 2026? Para a maioria dos sites, sim - ele e suportado nas versoes atuais de todos os principais navegadores. Use-o como uma melhoria progressiva se precisar dar suporte a navegadores muito antigos.
O :has() prejudica o desempenho? Raramente, se voce mantiver os seletores com escopo. Verificacoes :has() extremamente amplas, em toda a pagina, em documentos grandes e em constante mudanca podem adicionar custo, mas o uso em nivel de componente esta bem.
Para mais CSS moderno, veja nossos guias sobre aninhamento nativo de CSS e container queries.