본문 바로가기

1주차

똑똑하게 CSS 선택자 사용하기 ~! :where() / :is()

1주차 과제를 진행하면서, 어김없이 공통된 css 효과를 쉼표로 연결하고 있던 도중.... 

이 번거로운 과정을 해결할 수 있는 방법은 없을까? 에 대한 의문이 들었습니다 !!!!!

/* 문제 상황 */
.header_menu li:hover,
.header_icons li:hover {
  cursor: pointer;
  transform: scale(1.1);
}

 

뭔가.. 뭔가..  번거로운데요, 개선 방법을 여러분들과 공유하고자 합니다 🤤

 

💡 CSS 선택자: :where(), :is()

 

1️⃣ where 선택자

<nav>
  <ul>
    <a href="#">요소 1</a>
  </ul>
</nav>

<footer>
  <ol>
    <a href="#">요소 2</a>
  </ol>
</footer>

<aside>
  <p>
    <a href="#">요소 3</a>
  </p>
</aside>

 

보통 Html이 위와 같이 적혀 있고, 공통의 스타일을 적용해야 할 때 저는 보통 다음과 같은 식으로 작성했었습니다.

nav > ul a:hover,
footer > ol a:hover,
aside > p a:hover {
  color: blue;
}

 

코드를 보면 문제상황과 마찬가지로 a:hover 부분이 무려 "3번"이나 반복해서 작성된 걸 확인하실 수 있는데요, 적용해야 할 요소가 많으면 많을수록가독성 및 유지보수도 힘들어지게 되고 쉼표로 이어진 이들 선택자중 하나가 잘못되면 전체가 적용되지 않는 문제가 발생할 수 있습니다. 이때 :where() 선택자를 사용하면 불필요한 코드 중복을 없애, 보다 똑똑하게 css를 작성할 수 있습니다.

 

:where(nav > ul, footer > ol, aside > p) a:hover {
  color: blue;
}

 

 

이렇게만 보면 그냥 적는 게 더 편할 것 같은데...라는 생각이 드실 수도 있습니다. 

 

이중 :where() 처리

다음 선택자들을 보면 section, article, aside, nav 선택자와 그의 자손인 h1 ~ h6 선택자가 반복되는 걸 볼 수 있습니다.

section h1, section h2, section h3, section h4, section h5, section h6, 
article h1, article h2, article h3, article h4, article h5, article h6, 
aside h1, aside h2, aside h3, aside h4, aside h5, aside h6, 
nav h1, nav h2, nav h3, nav h4, nav h5, nav h6 {
  color: #111111;
}

/* ↓ */

:where(section, article, aside, nav) :where(h1, h2, h3, h4, h5, h6) {
  color: #111111;
}

 

하지만 where을 사용하면 단 두줄로! 모두 작성할 수 있습니다.

 

⚠️ 단점

그러나 :where()은 DOM에 있는 요소만 선택이 가능하기 때문에, ::before  ::after와 같은 의사 요소는 묶을 수 없고 쉼표로 이어야 한다고 합니다 🥹 상황에 따라 적절하게 사용하기!

 

2️⃣ is 선택자

:is(선택리스트) 형태로 쓰이며, where처럼 여러 요소의 스타일을 지정할 수 있습니다.

// 변경 전
header p,
aside p, 
footer p {
color: red;
}
// 변경 후
:is(header, aside, footer) p {
color: red;
}

 

(눈으로 효과 확인하기)

3️⃣선택자 그룹화

:is()가 할 수 있는 그룹화라면 :where()도 할 수 있습니다. 그룹화는 선택자 어디에서나 사용할 수 있고, 중첩 및 결합도 가능합니다.

/* 선택자 처음 */
:where(h1,h2,h3,h4,h5,h6) > b {
  color: hotpink;
}

/* 선택자 중간 */
article :is(header,footer) > p {
  color: gray;
}

/* 선택자 끝 */
.dark-theme :where(button,a) {
  color: purple;
}

/* 여러 가지 사용 */
:is(.dark-theme, .dim-theme) :where(button,a) {
  color: purple;
}

/* 결합 */
:is(h1,h2):where(.hero,.subtitle) {
  text-transform: uppercase;
}

/* 중첩 */
.hero:is(h1,h2,:is(.header,.boldest)) {
  font-weight: 900;
}

 

4️⃣ :where()와 :is()의 차이점: 명시도

명시도는 요소에 적용되는 스타일의 우선 순위 결정하는 중요한 개념입니다. 동일한 요소에 여러 스타일이 적용될 때, 명시도가 높은 선택자가 우선 적용됩니다.

  • :is()의 명시도는 각 선택자 중 가장 구체적인 선택자의 명시도를 따릅니다.
  • :where()는 명시도가 없으며, 매개변수로 전달된 선택자 목록의 모든 명시도를 무시합니다. 이는 다른 선택자에서는 찾아볼 수 없는 특별한 기능입니다.

따라서, 스타일이 충돌할 때는 :is()가 적용됩니다, 왜냐하면 :is()의 명시도가 :where()보다 높기 때문입니다.

참고: 클래스, 의사 클래스, ID,! important는 :is()와 :where() 보다 명시도가 높으므로, 이 선택자들을 사용할 때는 주의가 필요합니다.

 

 

    정리하자면,

  • :where()는 명시도가 없다: 선택자 목록의 명시도를 무시하고, 항상 우선순위가 낮습니다.
  • :is()는 가장 구체적인 선택자의 명시도를 따른다: 예를 들어, :is(a, div, #id)의 명시도는 ID 선택자인 #id의 명시도인 100입니다.
  • 주의할 점: :is()는 선택자 목록에서 가장 높은 명시도를 따르기 때문에, 그룹화할 때는 높은 명시도를 가진 선택자가 불필요하게 영향을 미칠 수 있습니다. 높은 명시도의 선택자는 따로 분리하여 가독성을 높이고, 스타일 적용에 과도한 영향을 미치지 않도록 관리하는 것이 좋습니다.

 

 

 

 

참고 문헌: https://web.dev/articles/css-is-and-where? hl=ko

https://inpa.tistory.com/entry/%F0%9F%8C%9F-css-where-is-has-not

 

명시도 알아보기:

https://inpa.tistory.com/entry/CSS-%F0%9F%93%9A-%EC%83%81%EC%86%8D-%EA%B0%9C%EB%85%90-%EC%A0%81%EC%9A%A9-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84