:heeft() casestudy's

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

CSS miste tot voor kort een manier om direct een ouderelement te selecteren op basis van zijn kinderen. Dit was al jaren een veelgevraagde functie door ontwikkelaars. De :has() ` selector, die nu door alle belangrijke browsers wordt ondersteund, lost dit probleem op. Vóór :has() moest je vaak lange selectors aan elkaar koppelen of klassen toevoegen voor styling. Nu kun je stylen op basis van de relatie van een element met zijn afstammelingen. Lees meer over de :has() ` selector in CSS Wrapped 2023 en 5 CSS-codefragmenten die elke frontend-ontwikkelaar zou moeten kennen .

Hoewel deze selector klein lijkt, kan hij een enorm aantal toepassingsmogelijkheden bieden. Dit artikel laat enkele voorbeelden zien van toepassingen die e-commercebedrijven hebben gerealiseerd met de :has() selector.

Bekijk de volledige serie waar dit artikel deel van uitmaakt, waarin wordt besproken hoe e-commercebedrijven hun website hebben verbeterd met behulp van nieuwe CSS- en UI-functies.

Policybazaar

Met de :has() ` selector konden we de JavaScript-gebaseerde validatie van de gebruikersselectie elimineren en vervangen door een CSS-oplossing die naadloos werkt en dezelfde gebruikerservaring biedt als voorheen. — Aman Soni , Tech Lead, Policybazaar

Het investeringsteam van Policybazaar heeft de selector :has() slim toegepast om gebruikers een duidelijke visuele indicatie te geven bij het vergelijken van verzekeringsplannen. De volgende afbeelding toont twee soorten plannen in de vergelijkingsinterface (geel en blauw). Elk plan kan alleen met zijn eigen type worden vergeleken. Door :has() te gebruiken, kan, wanneer een gebruiker één type plan selecteert, het andere type plan niet worden geselecteerd.

Het implementeren van ` :has() om het ouderelement en zijn kinderen te stylen, om zo een categoriegebonden selectiefunctie te creëren.

Code

:has() krijg je toegang tot de stijl van ouderelementen en hun kinderen. De volgende code controleert of een oudercontainer de klasse ` .disabled-group heeft. Zo ja, dan wordt de kaart grijs weergegeven en reageert de knop "Toevoegen" niet meer op klikken door pointer-events op ` none in te stellen.

.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);
}

Het gezondheidsteam van Policybazaar heeft een iets andere toepassing geïmplementeerd. Ze hebben een inline quiz voor de gebruiker en gebruiken :has() om de status van het selectievakje bij een vraag te controleren en te zien of de vraag is beantwoord. Zo ja, dan wordt een animatie toegepast om naar de volgende vraag over te gaan.

health.policybazaar.com/

Code

In het voorbeeld van de planvergelijking werd :has() gebruikt om de aanwezigheid van een klasse te controleren. Je kunt ook de status van een invoerelement, zoals een selectievakje, controleren met :has(input:checked) . In de visualisatie van de quiz is elke vraag in de paarse banner een selectievakje. Policybazaar controleert of de vraag is beantwoord met :has(input:checked) en zo ja, activeert het een animatie met animation: quesSlideOut 0.3s 0.3s linear forwards om naar de volgende vraag te schuiven. Zie hoe dit werkt in de volgende code.

.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 gebruikt :has() om een ​​overlay-afbeelding te creëren als de productthumbnail een video bevat. Als de productthumbnail de klasse .playIcon bevat, wordt een CSS-overlay toegevoegd. Hier wordt de `:has()`-selector gebruikt in combinatie met de geneste & -selector binnen de overkoepelende klasse .thumbnailWrapper , die van toepassing is op alle thumbnails. Dit zorgt voor een meer modulaire en leesbare CSS.

Screenshot van de Tokopedia-pagina voor en na het gebruik van de 'has'-selector.
Voor en na het gebruik van :has() .

Code

De volgende code gebruikt CSS-selectors en combinatoren ( & en > ) en nesting met :has() om de miniatuur te stylen. Voor browsers die dit niet ondersteunen, wordt de reguliere extra CSS-klasseregel als fallback gebruikt. De @supports selector(:has(*)) regel wordt ook gebruikt om te controleren of de browser ondersteuning biedt. De algehele ervaring is daarom hetzelfde in alle browserversies.

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

Aandachtspunten bij het gebruik van :has()

Combineer :has() met andere selectors om een ​​complexere voorwaarde te creëren. Bekijk enkele voorbeelden in de `has()` familieselector .

Bronnen:

Ontdek de andere artikelen in deze serie over hoe e-commercebedrijven profiteerden van nieuwe CSS- en UI-functies zoals scroll-gestuurde animaties, weergaveovergangen, popovers en containerqueries.