Estudos de caso de :has()

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

O CSS notoriamente não possuía uma maneira de selecionar diretamente um elemento pai com base no os filhos. Essa tem sido uma das principais solicitações dos desenvolvedores há muitos anos. A O seletor :has(), agora compatível com todos os principais navegadores, resolve isso. Antes :has(), muitas vezes você encadearia seletores longos ou adicionaria classes para definir o estilo de ganchos. Agora é possível estilizar com base na relação de um elemento com os descendentes. Ler mais sobre o seletor :has() Resumo do CSS 2023 e Cinco snippets de CSS que todos os desenvolvedores de front-end deveriam conhecer.

Embora esse seletor pareça pequeno, ele pode permitir muitos casos de uso. Este artigo mostra alguns casos de uso que as empresas de e-commerce revelaram com a Seletor de :has().

:has() faz parte do Valor de referência recém-disponível.

Compatibilidade com navegadores

  • Chrome: 105
  • Borda: 105.
  • Firefox: 121
  • Safari: 15.4.

Origem

Confira a série completa da qual este artigo faz parte, que discute como as empresas de e-commerce aprimoraram o site usando novos recursos de CSS e interface.

Politicas

Com o seletor :has(), conseguimos eliminar a validação baseada em JavaScript. da seleção do usuário e a substituir por uma solução de CSS que funcione para nós com a mesma experiência de antes.Aman Soni, líder de tecnologia, Policybazaar

A equipe de investimentos da Policybazaar aplicou de forma inteligente o seletor :has() para fornecer uma uma indicação visual clara para os usuários que estão comparando planos. A imagem a seguir mostra dois tipos de planos na interface de comparação (amarelo e azul). Cada plano só pode ser comparado com o próprio tipo. Usando :has(), quando um usuário selecionar uma tipo de plano que o outro tipo de plano não pode ser selecionado.

Implementar :has() para estilizar o elemento pai e os filhos dele para criar uma funcionalidade de seleção vinculada à categoria.

Código

Com :has(), você pode definir o estilo dos elementos pais e dos filhos deles. A o código a seguir verifica se um contêiner pai tem uma classe .disabled-group definida. Se isso acontecer, o cartão ficará esmaecido e a opção "Adicionar" é impedido de que reagem a cliques definindo pointer-events como none.

.plan-group-container:has(.disabled-group) {
  opacity: 0.5;
  filter: grayscale(100%);
}

.plan-group-container:has(.disabled-section) .button {
  pointer-events: none;
  border-color: #B5B5B5;
  color: var(--text-primary-38-color);
  background: var(--input-border-color);
}

A equipe de saúde do Policybazaar implementou um caso de uso um pouco diferente. Eles têm um teste inline para o usuário e usam :has() para marcar o status da caixa de seleção da pergunta e confirmar se ela foi respondeu. Se foi, uma animação é aplicada para fazer a transição para a próxima pergunta.

health.policybazaar.com/

Código

No exemplo de comparação dos planos, :has() foi usado para verificar a presença de um . Também é possível verificar o estado de um elemento de entrada, como uma caixa de seleção, usando :has(input:checked): Na imagem que mostra o teste, cada pergunta da um banner roxo é uma caixa de seleção. O Policybazaar verifica se a pergunta foi respondida usando :has(input:checked) e, se tiver, acione uma animação usando animation: quesSlideOut 0.3s 0.3s linear forwards para deslizar para a próxima pergunta. Confira como isso funciona no código a seguir.

.segment_banner__wrap__questions {
 position: relative;
 animation: quesSlideIn 0.3s linear forwards;
}

.segment_banner__wrap__questions:has(input:checked) {
 animation: quesSlideOut 0.3s 0.3s linear forwards;
}


@keyframes quesSlideIn {
 from {
   transform: translateX(50px);
   opacity: 0;
 }
 to {
   transform: translateX(0px);
   opacity: 1;
 }
}

@keyframes quesSlideOut {
 from {
   transform: translateX(0px);
   opacity: 1;
 }
 to {
   transform: translateX(-50px);
   opacity: 0;
 }
}

Tokopedia

A Tokopedia usou :has() para criar uma imagem de sobreposição se a miniatura do produto contém um vídeo. Se a miniatura do produto tiver uma classe .playIcon, um CSS é adicionada. Aqui, o seletor :has() é usado com o & seletor de aninhamento dentro da classe .thumbnailWrapper abrangente que se aplica a todas as miniaturas. Isso cria um CSS mais modular e legível.

Captura de tela da página da Tokopedia antes e depois de usar o seletor "tem".
Antes e depois de usar o :has().

Código

O código a seguir usa Seletores e combinadores de CSS (& e >) e aninhamento com :has() para estilizar a miniatura. Para não apoio navegadores, a regra de classe CSS extra normal será usada como substituta. A A regra @supports selector(:has(*)) também é usada para verificar a compatibilidade com o navegador. Portanto, a experiência geral é a mesma em todas as versões do navegador.

export const thumbnailWrapper = css`
  padding: 0;
  margin-right: 7px;
  border: none;
  outline: none;
  background: transparent;

  > div {
    width: 64px;
    height: 64px;
    overflow: hidden;
    cursor: pointer;
    border-color: ;
    position: relative;
    border: 2px solid ${NN0};
    border-radius: 8px;
    transition: border-color 0.25s;

    &.active {
      border-color: ${GN500};
    }

    @supports selector(:has(*)) {
      &:has(.playIcon) {
        &::after {
          content: '';
          display: block;
          background: rgba(0, 0, 0, 0.2);
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
        }
      }
    }

    & > .playIcon {
      position: absolute;
      top: 25%;
      left: 25%;
      width: 50%;
      height: 50%;
      text-align: center;
      z-index: 1;
    }
  }
`;

Considerações ao usar a :has()

Combine :has() com outros seletores para criar uma condição mais complexa. Marca de seleção alguns exemplos em has() no seletor de família.

Recursos:

Confira os outros artigos desta série que abordam como o comércio eletrônico empresas que se beneficiaram do uso de novos recursos de CSS e interface do usuário, como os recursos de rolagem animações, transições de visualização, pop-over e consultas de contêiner.