Case study :has()

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

Il CSS è noto per la mancanza di un modo per selezionare direttamente un elemento principale in base ai relativi elementi secondari. Questa è una delle richieste più frequenti degli sviluppatori da molti anni. Il selettore :has(), ora supportato da tutti i principali browser, risolve questo problema. Prima di :has(), spesso concatenavi selettori lunghi o aggiungevi classi per gli hook di stile. Ora puoi applicare lo stile in base alla relazione di un elemento con i relativi discendenti. Scopri di più sul selettore :has() in CSS Wrapped 2023 e in 5 snippet CSS che ogni sviluppatore frontend dovrebbe conoscere.

Sebbene questo selettore sembri piccolo, può consentire un numero enorme di casi d'uso. Questo articolo mostra alcuni casi d'uso che le aziende di e-commerce hanno sbloccato con il selettore :has().

Dai un'occhiata alla serie completa di cui fa parte questo articolo, che spiega in che modo le aziende di e-commerce hanno migliorato il proprio sito web utilizzando nuove funzionalità CSS e UI.

Policybazaar

Con il selettore :has(), siamo riusciti a eliminare la convalida basata su JavaScript della selezione dell'utente e a sostituirla con una soluzione CSS che funziona perfettamente per noi con la stessa esperienza di prima.—Aman Soni, Tech Lead, Policybazaar

Il team di investimento di Policybazaar ha applicato in modo intelligente il selettore :has() per fornire un'indicazione visiva chiara agli utenti che confrontano i piani. L'immagine seguente mostra due tipi di piani all'interno dell'UI di confronto (giallo e blu). Ogni piano può essere confrontato solo con il proprio tipo. Utilizzando :has(), quando un utente seleziona un tipo di piano, l'altro tipo di piano non può essere selezionato.

Implementazione di :has() per applicare lo stile all'elemento principale e ai relativi elementi secondari per creare una funzionalità di selezione vincolata alla categoria.

Codice

:has() ti consente di applicare lo stile agli elementi principali e ai relativi elementi secondari. Il seguente codice controlla se un container principale ha impostato una classe .disabled-group. In caso affermativo, la scheda viene visualizzata in grigio e il pulsante "Aggiungi" non reagisce ai clic impostando pointer-events su 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);
}

Il team sanitario di Policybazaar ha implementato un caso d'uso leggermente diverso. Ha un quiz in linea per l'utente e utilizza :has() per controllare lo stato della casella di controllo della domanda per verificare se è stata data una risposta. In caso affermativo, viene applicata un'animazione per passare alla domanda successiva.

health.policybazaar.com/

Codice

Nell'esempio di confronto dei piani, :has() è stato utilizzato per verificare la presenza di una classe. Puoi anche controllare lo stato di un elemento di input, ad esempio una casella di controllo, utilizzando :has(input:checked). Nell'immagine che mostra il quiz, ogni domanda nel banner viola è una casella di controllo. Policybazaar verifica se è stata data una risposta alla domanda utilizzando :has(input:checked) e, in caso affermativo, attiva un'animazione utilizzando animation: quesSlideOut 0.3s 0.3s linear forwards per passare alla domanda successiva. Scopri come funziona nel seguente codice.

.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

Tokopedia ha utilizzato :has() per creare un'immagine di overlay se la miniatura del prodotto contiene un video. Se la miniatura del prodotto contiene una classe .playIcon, viene aggiunto un overlay CSS. In questo caso, il selettore :has() viene utilizzato insieme al selettore di nidificazione & all'interno della classe .thumbnailWrapper generale che si applica a tutte le miniature. In questo modo si crea un CSS più modulare e leggibile.

Screenshot della pagina Tokopedia prima e dopo l'utilizzo del selettore has.
Prima e dopo l'utilizzo di :has().

Codice

Il seguente codice utilizza i selettori e i combinatori CSS (& e >) e la nidificazione con :has() per applicare lo stile alla miniatura. Per i browser non supportati, viene utilizzata la regola della classe CSS aggiuntiva normale come fallback. Viene utilizzata anche la regola @supports selector(:has(*)) per verificare il supporto del browser. Di conseguenza, l'esperienza complessiva è la stessa nelle versioni del browser.

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;
    }
  }
`;

Aspetti da considerare quando si utilizza :has()

Combina :has() con altri selettori per creare una condizione più complessa. Dai un'occhiata ad alcuni esempi in has() the family selector.

Risorse:

Esplora gli altri articoli di questa serie che spiegano in che modo le aziende di e-commerce hanno tratto vantaggio dall'utilizzo di nuove funzionalità CSS e UI come animazioni basate sullo scorrimento, transizioni di visualizzazione, popover e query sui container.