":has() 의사 클래스는 '부모 선택자'로 불리며, 단순히 요소의 조상을 스타일링하는 것 이상의 범위를 가지고 있습니다. Safari 15.4+ 및 Chromium 105+에서 사용 가능하며, Firefox에서는 플래그로 사용됩니다.
가상 클래스로서, :has()의 기본적인 기능은 해당 요소인 '대상' 요소를 스타일링하는 것입니다. 이는 다른 가상 클래스인 :hover 또는 :active와 유사합니다.
하지만 :has()는 :is(), :where(), :not()와 유사하게 괄호 내에서 상대적인 선택자 목록을 받아들이기 때문에 복잡한 기준을 테스트할 수 있습니다. 이를 통해 :has()는 매우 강력한 선택자가 됩니다.
:has()가 어떻게 작동하는지 이해하기 위해 예제를 살펴보겠습니다.
다음 선택자에서는 <article> 요소가 <img> 요소를 자식으로 가지는지 테스트 합니다.
article:has(img) {}
article:has(img) {
background-color: #81D4FA;
padding: 0 0 2rem;
img {
border-radius: 0.5rem 0.5rem 0 0;
}
> *:not(img) {
padding-inline: 1.5rem;
}
}
아래 이미지는 이 선택자의 가능한 결과 중 하나를 보여줍니다.
세 개의 article 요소가 표시되며, 이미지를 포함한 두 개의 요소는 푸른색 배경과 이미지가 없는 요소와는 다른 패딩을 가지고 있습니다.
위의 선택자는 <img> 요소가 <article> 요소 내에서 어디에 있든지 상관없이 적용됩니다. 직접적인 자식으로 존재하거나 다른 중첩 요소의 하위 요소로 존재하는 경우에도 해당합니다.
만약 <img>가 <article> 요소의 직접적인 (중첩되지 않은) 자식인 경우에만 규칙이 적용되도록 하려면, 자식 조합자를 추가할 수도 있습니다:
article:has(> img) {}
article:has(> img) {
background-color: #81D4FA;
padding: 0 0 2rem;
img {
border-radius: 0.5rem 0.5rem 0 0;
}
> *:not(img) {
padding-inline: 1.5rem;
}
}
이 변경 사항의 결과는 아래 이미지에서 확인할 수 있습니다. 동일한 세 개의 카드가 표시되지만, 이번에는 이미지가 <article>의 직접 자식인 경우에만 푸른색 배경과 패딩이 적용됩니다.
두 선택자 모두 정의한 스타일이 대상 요소인 <article>에 적용됩니다.
이것이 사람들이 종종 :has()를 "부모" 선택자라고 부르는 이유입니다. 특정 요소가 특정한 방식으로 존재하는 경우에는 해당 "부모"가 지정된 스타일을 받습니다.
:has() 의사 클래스 자체는 선택자에 특수성 가중치를 추가하지 않습니다.
:is()와 :not()과 마찬가지로 :has()의 특수성은 선택자 목록에서 가장 높은 특수성을 가진 선택자와 동일합니다.예를 들어, :has(#id, p, .class)는 id에 할당된 특수성을 갖습니다.
우리는 인접 형제 결합자 (+)를 사용하여 특정 인접 형제 요소가 뒤따라오는 경우에도 대상 요소를 선택할 수 있습니다. 다음 예제에서는 <h1> 요소가 직접적으로 <h2> 다음에 따라오는 경우에만 선택합니다:
h1:has(+ h2) {}
h1:has(+ h2) {
font-size: 3rem;
background-color: #81D4FA;
+ h2 {
margin-block-start: 0.15em;
color: #797979;
font-weight: 500;
font-style: italic;
}
}
아래 이미지에서는 두 개의 <article> 요소가 표시됩니다. 첫 번째 요소에서는 <h1> 뒤에 <h2>가 따라오기 때문에 <h1>에 연한 푸른색 배경이 적용됩니다.
일반 형제 결합자 (~)를 사용하면 대상 이후에 특정 요소가 형제로 어디에 있는지 확인할 수 있습니다. 여기에서는 <ul>의 형제로 어딘가에 <p> 요소가 있는지 확인하고 있습니다:
ul:has(~ p) {}
ul:has(~ p) {
background-color: #81D4FA;
margin-block-end: 2rem;
}
아래 이미지에서는 두 개의 <article> 요소가 표시됩니다. 각각의 <article> 요소는 순서 없는 목록을 포함하고 있습니다. 두 번째 <article> 요소의 목록 뒤에는 단락이 따라오기 때문에 푸른색 배경이 적용됩니다.
지금까지 사용한 선택자는 :has()에 연결된 대상 요소인 <ul>과 같은 요소를 스타일링했습니다. 일반적인 선택자와 마찬가지로 :has() 선택자를 더 복잡하게 확장하여 직접적으로 :has() 선택자에 연결되지 않은 요소에 대한 스타일링 조건을 설정할 수 있습니다.
다음 선택자에서는 스타일이 <h3>를 인접한 형제로 가지는 <h2>의 형제인 모든 <p> 요소에 적용됩니다:
h2:has(+ h3) ~ p
h2:has(+ h3) ~ p {
background-color: #81D4FA;
margin-inline-start: 2em;
}
아래 이미지에서는 두 개의 <article> 요소가 표시됩니다. 두 번째 <article>에서는 단락들이 푸른색 배경과 왼쪽 여백이 증가된 스타일이 적용되는데, 이는 단락들이 <h2> 뒤에 <h3>가 따라오는 형제 요소들입니다.
참고: :has()를 사용하는 데는 사용 가능한 CSS 선택자에 대한 충분한 이해가 필요합니다. MDN은 선택자에 대한 간결한 개요를 제공하며, 추가적인 실용적인 예제와 함께 선택자에 대한 두 부분 시리즈를 작성했습니다.
기억하세요, :has()는 선택자 목록을 받아들일 수 있으며, 이는 OR 조건으로 생각할 수 있습니다. <a> 또는 <strong> 또는 <em>을 포함하는 단락을 선택해 보겠습니다:
p:has(a, strong, em) {}
p:has(a, strong, em) {
background-color: #81D4FA;
}
아래 이미지에서는 두 개의 단락이 있습니다. 두 번째 단락에 <strong> 요소가 포함되어 있기 때문에 푸른색 배경이 적용됩니다.
우리는 :has() 선택자를 연결하여 AND 조건을 만들 수도 있습니다. 다음 복합 선택자에서는 <img>가 <article>의 첫 번째 자식인지를 테스트하고, <article>이 <h1> 다음에 <h2>를 포함하는지도 확인하고 있습니다:
article:has(> img:first-child):has(h1 + h2) {}
article:has(> img:first-child):has(h1 + h2) {
background-color: #81D4FA;
padding: 0 0 2rem;
img {
border-radius: 0.5rem 0.5rem 0 0;
}
> *:not(img) {
padding-inline: 1.5rem;
}
:is(h1, h2) {
font-weight: 500;
}
h1 {
font-family: NotoSans, Georgia, serif;
font-size: 1.75rem;
font-style: italic;
}
h2 {
margin-block-start: 0.15em;
font-size: 1.25rem;
}
}
아래 이미지에서는 세 개의 <article> 요소가 표시됩니다. 두 번째 <article>에는 이미지가 첫 번째 자식으로 있고, <h1> 다음에 <h2>가 따라오는 경우에 푸른색 배경(및 기타 스타일링)이 적용됩니다.
'HTML, CSS' 카테고리의 다른 글
HTML Input 기본 버튼 아이콘 숨기기 (0) | 2023.06.22 |
---|---|
CSS var() 함수 변수의 자바스크립트 동적 생성 (0) | 2023.06.17 |
CSS 미디어쿼리 Level 4 입력방식으로 기기 구분하기 (0) | 2023.06.16 |
터치화면의 자연스러운 스크롤을 위한 webkit-overflow-scrolling (0) | 2023.06.15 |
브라우저 플래그 지원 이란? (0) | 2023.06.01 |
댓글