:has() 우수사례

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

CSS에는 하위 요소를 기반으로 상위 요소를 직접 선택하는 방법이 없었습니다. 이는 수년 동안 개발자들이 가장 많이 요청했던 개선사항이었습니다. 이제 모든 주요 브라우저에서 지원되는 :has() 선택자를 사용하면 이 문제를 해결할 수 있습니다. :has() 이전에는 긴 선택자를 연결하거나 스타일 지정 후크를 위한 클래스를 추가해야 했습니다. 이제 하위 요소와의 관계를 기반으로 스타일을 지정할 수 있습니다. :has():has() 선택자에 관한 자세한 내용은 CSS Wrapped 2023모든 프런트엔드 개발자가 알아야 할 5가지 CSS 스니펫을 참고하세요.

이 선택자는 작아 보이지만 다양한 사용 사례를 지원할 수 있습니다. 이 도움말에서는 전자상거래 회사에서 :has() 선택자를 사용하여 해결한 몇 가지 사용 사례를 보여줍니다.

이 도움말이 포함된 전체 시리즈를 확인하여 이커머스 회사에서 새로운 CSS 및 UI 기능을 사용하여 웹사이트를 개선한 방법을 알아보세요.

Policybazaar

:has() 선택자를 사용하면 사용자의 선택에 대한 자바스크립트 기반 유효성 검사 를 삭제하고 CSS 솔루션으로 대체할 수 있었습니다. 이 솔루션은 이전과 동일한 환경에서 원활하게 작동합니다.—Aman Soni, Tech Lead, Policybazaar

Policybazaar의 투자팀은 :has() 선택자를 영리하게 적용하여 요금제를 비교하는 사용자에게 명확한 시각적 표시를 제공했습니다. 다음 이미지는 비교 UI 내에서 두 가지 유형의 요금제 (노란색 및 파란색)를 보여줍니다. 각 요금제는 자체 유형과만 비교할 수 있습니다. :has()를 사용하면 사용자가 한 가지 유형의 요금제를 선택할 때 다른 요금제 유형을 선택할 수 없습니다.

:has()를 구현하여 상위 요소와 하위 요소의 스타일을 지정하여 카테고리 바운드 선택 기능을 만듭니다.

코드

:has()를 사용하면 상위 요소와 하위 요소의 스타일을 지정할 수 있습니다. 다음 코드는 상위 컨테이너에 .disabled-group 클래스가 설정되어 있는지 확인합니다. 설정되어 있으면 카드가 회색으로 표시되고 pointer-eventsnone으로 설정하여 '추가' 버튼이 클릭에 반응하지 않도록 합니다.

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

Policybazaar의 건강팀은 약간 다른 사용 사례를 구현했습니다. 사용자를 위한 인라인 퀴즈가 있으며 :has()를 사용하여 질문 체크박스 상태를 확인하여 질문에 답변했는지 확인합니다. 답변한 경우 애니메이션이 적용되어 다음 질문으로 전환됩니다.

health.policybazaar.com/

코드

요금제 비교 예시에서는 :has()를 사용하여 클래스의 존재를 확인했습니다. :has(input:checked)를 사용하여 체크박스와 같은 입력 요소의 상태를 확인할 수도 있습니다. 퀴즈를 보여주는 시각적 자료에서 보라색 배너의 각 질문은 체크박스입니다. Policybazaar는 :has(input:checked)를 사용하여 질문에 답변했는지 확인하고 답변한 경우 animation: quesSlideOut 0.3s 0.3s linear forwards를 사용하여 애니메이션을 트리거하여 다음 질문으로 슬라이드합니다. 다음 코드에서 작동 방식을 확인하세요.

.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는 :has()를 사용하여 제품 미리보기에 동영상이 포함된 경우 오버레이 이미지를 만들었습니다. 제품 미리보기에 .playIcon 클래스가 포함되어 있으면 CSS 오버레이가 추가됩니다. 여기서 :has() 선택자는 모든 미리보기에 적용되는 포괄적인 .thumbnailWrapper 클래스 내에서 & 중첩 선택자와 함께 사용됩니다. 이렇게 하면 더 모듈화되고 읽기 쉬운 CSS가 만들어집니다.

has 선택기 사용 전후의 Tokopedia 페이지 스크린샷
:has() 사용 전후

코드

다음 코드는 CSS 선택자 및 결합자 (&>)와 :has()를 사용한 중첩을 사용하여 미리보기의 스타일을 지정합니다. 지원되지 않는 브라우저의 경우 일반 추가 CSS 클래스 규칙이 대체로 사용됩니다. @supports selector(:has(*)) 규칙도 브라우저 지원을 확인하는 데 사용됩니다. 따라서 브라우저 버전 전반에서 전반적인 환경이 동일합니다.

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

:has() 사용 시 고려사항

:has()를 다른 선택자와 결합하여 더 복잡한 조건을 만듭니다. 가족 선택자 has()에서 몇 가지 예를 확인해 보세요.

리소스:

스크롤 기반 애니메이션, 뷰 전환, 팝오버, 컨테이너 쿼리와 같은 새로운 CSS 및 UI 기능을 사용하여 이커머스 회사가 얻은 이점을 설명하는 이 시리즈의 다른 도움말을 살펴보세요.