학습 공간 개념 · 판단 · 실험

Frontend Performance Lab

CSS

CSS 캐스케이드와 상태 선택자

선택자 명시도는 충돌하는 스타일 중 최종 선언을 가리는 여러 캐스케이드 단계 중 하나입니다.

이럴 때 필요해요

!important를 남발하거나 선택자를 끝없이 길게 겹쳐 문제를 덮지 않고, 스타일이 왜 덮어써졌는지 원인을 정확히 진단하기 위해 필요합니다.

어떻게 동작하나요?

버튼 색상을 바꿨는데 화면에 반영되지 않을 때 무작정 !important나 #id를 붙이면 나중에 스타일을 수정하기가 훨씬 힘들어집니다. 브라우저가 충돌하는 선언을 정리하는 캐스케이드(Cascade)는 선택자 점수를 보기 전에 먼저 출처(브라우저 기본, 사용자, 작성자), !important 중요도, 그리고 @layer 순서를 차례로 비교합니다. 이 앞선 조건들이 모두 같을 때만 비로소 선택자 명시도(Specificity)와 스코프 근접도, 작성 순서를 비교합니다.

선택자 명시도는 ID 선택자 수, 클래스·속성·가상 클래스 수, 태그(타입)·가상 요소 수를 세 범주로 나누어 왼쪽부터 비교합니다. 이때 :where()는 명시도가 항상 0이어서 언제든 덮어쓰기 좋은 기본 스타일에 유용하고, :is()나 :not()은 괄호 안 선택자 중 가장 높은 명시도를 따라갑니다. 또한 부모에게서 물려받은 상속(Inherited) 값은 요소에 직접 지정된 선언과 대등하게 경쟁하는 것이 아니라, 직접 지정된 선언이 없을 때만 적용됩니다.

상호작용 스타일을 줄 때는 요소의 상태 조건을 고르는 가상 클래스(:hover, :focus-visible, :checked)와 요소의 일부분이나 생성 박스를 다루는 가상 요소(::before, ::first-line)를 구분해 사용합니다. 특히 마우스를 올렸을 때(:hover)만 주요 정보를 보여 주면 키보드 탭 이동이나 터치 기기 사용자는 이용할 수 없으므로 :focus-visible과 클릭 상태를 함께 설계해야 합니다.

코드 예제

동작을 설명하는 읽기 전용 예제입니다.

example.css
@layer base, components;
@layer base { #save { color: gray; } }
@layer components { .action { color: navy; } }
.action:focus-visible { outline: 2px solid orange; }
css · 읽기 전용4줄

같은 출처의 일반 선언에서는 나중에 선언된 components 레이어의 .action이 앞선 base 레이어의 #save보다 우선합니다. 단, !important가 붙은 중요 선언은 레이어 우선순위가 반대로 적용됩니다.

자주 헷갈리는 포인트

  • 클래스 11개가 ID 1개를 이긴다는 식으로 명시도를 십진수 덧셈으로 계산하면 안 됩니다.
  • !important는 캐스케이드의 중요도 단계를 바꾸는 규칙이지 선택자 명시도 점수에 숫자를 더하는 것이 아닙니다.

내 말로 설명해 보기

선택자 명시도가 더 높은 규칙이 개발자 도구에서 취소선으로 밀려났다면 어떤 순서로 원인을 확인해야 할까요?

함께 읽으면 좋은 개념

관련 면접 질문 3개

CSS 선택자 명시도(Specificity)는 캐스케이드 과정에서 언제 비교하나요?

선택자 명시도는 한 요소의 같은 속성에 여러 스타일 규칙이 경합할 때, 출처(Origin), !important 여부, 그리고 @layer 순서 같은 앞선 우선순위 조건이 모두 동일한 선언들 사이에서 어느 선택자가 더 구체적인지 가리는 기준입니다. 비교할 때는 ID 선택자 수, 클래스·속성·가상 클래스 수, 타입·가상 요소 수를 왼쪽 범주부터 차례대로 대조합니다. 만약 이 명시도까지 같다면 스코프 근접도나 스타일시트에서 나중에 선언된 규칙이 최종적으로 적용됩니다.

꼬리질문과 참고자료 →

CSS 캐스케이드(Cascade)는 충돌하는 스타일 선언 중 최종 적용값을 어떻게 결정하나요?

CSS 캐스케이드는 한 요소의 동일한 속성에 여러 스타일 규칙이 동시에 걸릴 때 우선순위를 가려 최종 선언 하나를 선택하는 규칙입니다. 브라우저는 먼저 해당 요소에 적용되는 선언을 추린 뒤 출처와 !important 중요도, @layer 순서, 선택자 명시도, 스코프 근접도, 그리고 마지막으로 작성된 선언 순서를 차례대로 비교합니다. 이 과정에서 직접 지정된 값이 없으면 부모로부터의 상속(Inheritance)이나 속성의 초기값(Initial Value)이 사용됩니다.

꼬리질문과 참고자료 →

CSS의 가상 클래스(:hover 등)와 가상 요소(::before 등)는 어떻게 구분하나요?

가상 클래스(Pseudo-class)는 :hover, :focus-visible, :checked처럼 실제 DOM에 존재하는 요소가 특정 상태나 위치 조건에 놓였을 때 그 요소를 선택하는 방법입니다. 반면 가상 요소(Pseudo-element)는 ::before, ::after, ::first-line처럼 선택한 요소의 특정 일부분이나 새롭게 생성된 가상 박스를 스타일링 대상으로 삼습니다. 키보드나 터치 환경에서도 상태 변화가 잘 드러나도록 설계하고 선택자별 명시도 규칙도 함께 확인합니다.

꼬리질문과 참고자료 →

공식 참고 자료

← CSS