:has() – studia przypadków

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

CSS od dawna nie miał możliwości bezpośredniego wybierania elementu nadrzędnego na podstawie jego elementów podrzędnych. Od wielu lat deweloperzy prosili o dodanie tej funkcji. Rozwiązuje to selektor :has(), który jest teraz obsługiwany przez wszystkie główne przeglądarki. Zanim pojawił się selektor :has(), często trzeba było łączyć długie selektory lub dodawać klasy do stylizowania. Teraz możesz stylizować na podstawie relacji elementu z jego elementami potomnymi. Więcej informacji o selektorze :has() znajdziesz w artykułach CSS Wrapped 2023 i 5 CSS snippets every frontend developer should know.

Ten selektor może się wydawać niewielki, ale może umożliwić wiele przypadków użycia. W tym artykule pokazujemy niektóre przypadki użycia, które firmy e-commerce odblokowały za pomocą selektora :has().

Zapoznaj się z pełną serią, której częścią jest ten artykuł. Omówiono w niej, jak firmy e-commerce ulepszyły swoje witryny za pomocą nowych funkcji CSS i interfejsu.

Policybazaar

Dzięki selektorowi :has() mogliśmy wyeliminować walidację wyboru użytkownika opartą na JavaScript i zastąpić ją rozwiązaniem CSS, które działa bezproblemowo i zapewnia takie same wrażenia jak wcześniej – Aman Soni, Tech Lead, Policybazaar

Zespół ds. inwestycji w Policybazaar sprytnie zastosował selektor :has(), aby zapewnić użytkownikom porównującym plany wyraźne wskazanie wizualne. Na ilustracji poniżej w interfejsie porównania widać 2 typy planów (żółty i niebieski). Każdy plan można porównać tylko z planem tego samego typu. :has()Gdy użytkownik wybierze jeden typ planu, nie będzie mógł wybrać innego typu planu.

Implementowanie selektora :has() do stylizowania elementu nadrzędnego i jego elementów podrzędnych w celu utworzenia funkcji wyboru powiązanej z kategorią.

Kod

Selektor :has() umożliwia stylizowanie elementów nadrzędnych i ich elementów podrzędnych. Poniższy kod sprawdza, czy kontener nadrzędny ma ustawioną klasę .disabled-group. Jeśli tak, karta jest wyszarzona, a przycisk „Dodaj” nie reaguje na kliknięcia, ponieważ ustawiono wartość pointer-events na 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);
}

Zespół ds. zdrowia w Policybazaar wdrożył nieco inny przypadek użycia. Użytkownik ma do dyspozycji quiz w tekście, a zespół używa selektora :has(), aby sprawdzić stan pola wyboru pytania i zobaczyć, czy pytanie zostało udzielone. Jeśli tak, do przejścia do następnego pytania stosowana jest animacja.

health.policybazaar.com/

Kod

W przykładzie porównania planów selektor :has() został użyty do sprawdzenia obecności klasy. Możesz też sprawdzić stan elementu wejściowego, takiego jak pole wyboru, za pomocą selektora :has(input:checked). Na ilustracji przedstawiającej quiz każde pytanie na fioletowym banerze jest polem wyboru. Policybazaar sprawdza, czy pytanie zostało udzielone, za pomocą selektora :has(input:checked), a jeśli tak, wywołuje animację za pomocą kodu animation: quesSlideOut 0.3s 0.3s linear forwards, aby przejść do następnego pytania. Zobacz, jak to działa, w poniższym kodzie.

.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 użyła selektora :has(), aby utworzyć nakładkę, jeśli miniatura produktu zawiera film. Jeśli miniatura produktu zawiera klasę .playIcon, dodawana jest nakładka CSS. W tym przypadku selektor :has() jest używany razem z selektorem zagnieżdżania & w nadrzędnej klasie .thumbnailWrapper, która ma zastosowanie do wszystkich miniatur. Dzięki temu kod CSS jest bardziej modułowy i czytelny.

Zrzut ekranu strony Tokopedia przed użyciem selektora „has” i po jego użyciu.
Przed i po użyciu selektora :has().

Kod

Poniższy kod używa selektorów i kombinatorów CSS (& i >) oraz zagnieżdżania z :has() do stylizowania miniatury. W przypadku przeglądarek, które nie obsługują tej funkcji, jako rezerwa używana jest zwykła reguła dodatkowej klasy CSS. Do sprawdzania obsługi przeglądarki używana jest też reguła @supports selector(:has(*)). Dzięki temu ogólne wrażenia są takie same we wszystkich wersjach przeglądarki.

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

Co należy wziąć pod uwagę podczas używania selektora :has()

Połącz selektor :has() z innymi selektorami, aby utworzyć bardziej złożony warunek. Przykłady znajdziesz w artykule has() the family selector.

Zasoby:

Zapoznaj się z innymi artykułami z tej serii, w których opisujemy, jak firmy e-commerce korzystały z nowych funkcji CSS i interfejsu, takich jak animacje oparte na przewijaniu, przejścia między widokami, wyskakujące okienka i zapytania o kontenery.