Rafael Camargo

Usando CSS :has para estilizar um elemento pai no foco de um elemento filho

Há um bom tempo, uma enxurrada de artigos sobre a pseudo classe :has pipocam na internet. A maioria deles, porém, usa péssimos exemplos de aplicação — como estes apresentados na documentação da MDN. A distância destes exemplos em relação às necessidades reais do dia a dia de um programador desestimula a adoção do :has, que acaba sendo rebaixado a um recurso periférico e secundário.

Diferente daquilo que você encontra aos montes pela internet afora, o caso de uso apresentado neste post é bastante corriqueiro, já que se baseia em uma lista de elementos que contêm um link como elemento filho.

Veja o que acontece quando se navega pelos links desta lista usando a tecla Tab:

Links sendo destacados pelo contorno padrão aplicado pelo Browser

Se quiséssemos destacar todo o item da lista no momento em que o link recebe foco, dando a ele a aparência de card, ao invés do destaque padrão do próprio link, precisaríamos recorrer ao JavaScript até pouco tempo atrás. Removeríamos o estilo de outline padrão do link, definiríamos listeners para os eventos de foco e desfoque do link, e então adicionaríamos uma classe CSS ao pai do link no momento do foco, removeando-a no momento do desfoque. Uma trabalheira danada.

Uma outra opção seria embrulhar todo o conteúdo do item com o link, antes restrito apenas ao título do post. Mas se por um lado esta opção elimina o trabalho pesado com JavaScript, por outro, traz alguns desconfortos a nível de CSS, já que os estilos padrão de link, como o sublinhado, seriam aplicados ao excerto e à data do post, exigindo alguns ajustes adicionais de estilo. Além disso, esta estratégia faria com que o clique em qualquer parte do item da lista disparasse a navegação em direção ao respectivo post, um comportamento que poderia soar contra-intuitivo.

Com o advento da pseudo classe :has, que conta atualmente com suporte global de mais de 93%, este trabalho se tornou infinitamente mais simples, demandando agora apenas algumas linhas de CSS:

li {
  padding: 20px;
  box-shadow: 0 0 0 0 #29303D;
  border-radius: 12px;
  box-sizing: border-box;
  transition: all 300ms ease-out;
}

li a {
  outline: 0;
}

li:has(h2 > a:focus) {
  box-shadow: 0 0 0 6px #29303D;
}

O último seletor definido no código acima explicita a seguinte condição: quando o link contido no elemento h2 receber foco, aplique os seguintes estilos ao item da lista li.

Destaque do item da lista a partir do foco sobre o link contigo nele

Mão na massa: Neste Gist você tem acesso, em um único arquivo HTML, a todo o código necessário para rodar localmente o exemplo apresentado neste post.

Saiba mais: Se você curtiu este post, talvez se interesse em saber como usar CSS flexbox para fazer um elemento ocupar todo o espaço restante disponível.