같은 요소의 같은 속성에 여러 규칙이 값을 줄 때, 브라우저가 어느 값을 쓸지 정하는 규칙. 흔히 명시도(Specificity)만 떠올리지만 그보다 앞서 비교하는 기준들이 있다.
위에서부터 차례로 비교하고, 한 단계에서 승부가 나면 아래 단계는 보지 않는다.
- 출처와 중요도(Origin and Importance): 브라우저 기본 스타일 < 사용자 스타일 < 작성자 스타일.
!important가 붙으면 이 순서가 뒤집힌다. 애니메이션·트랜지션 값도 이 단계에서 따로 다룬다(아래 "출처와 중요도" 절) - 인라인 스타일(Inline Style):
style속성은 레이어·명시도와 상관없이 선택자 규칙보다 먼저 이긴다 - 캐스케이드 레이어:
@layer로 묶은 순서. 명시도보다 먼저 평가된다 - 명시도:
#id>.class·속성·가상 클래스 > 태그 - 선언 순서(Order of Appearance): 모두 같으면 나중에 나온 규칙이 이긴다
출처와 중요도
스타일시트는 누가 넣었는지에 따라 세 출처로 나뉜다.
- 브라우저 기본(User-Agent Stylesheet): 브라우저가 모든 문서에 기본으로 입히는 스타일.
<em>을 기울여 보여 주는 것이 예다. 브라우저마다 조금씩 달라서 리셋으로 맞추기도 한다 - 사용자(User Stylesheet): 사이트 방문자가 자기 취향대로 넣은 스타일. 브라우저에 따라 직접 설정하거나 확장 프로그램으로 넣는다
- 작성자(Author Stylesheet): 사이트를 만든 개발자가 쓴 스타일. 링크한 CSS 파일,
<style>블록,style속성까지 평소 쓰는 CSS가 모두 여기 든다
!important에서 순서가 뒤집히는 것은 명세가 말하는 작성자와 사용자 사이의 힘의 균형 때문이다. 평소에는 작성자가 이기지만, 큰 글자나 특정 색 조합이 필요한 사용자가 !important로 강제한 값은 사이트가 덮어쓰지 못한다. 명세는 이것이 접근성을 높인다고 적는다.
애니메이션(@keyframes)과 트랜지션 값도 별도 출처로 이 순서에 끼어든다. 약한 것에서 강한 것 순서로 보면 다음과 같다.
| 순서 | 출처 | 중요도 |
|---|---|---|
| 1 | 브라우저 기본 | 일반 |
| 2 | 사용자 | 일반 |
| 3 | 작성자 | 일반 |
| 4 | CSS 애니메이션 | |
| 5 | 작성자 | !important |
| 6 | 사용자 | !important |
| 7 | 브라우저 기본 | !important |
| 8 | CSS 트랜지션 |
애니메이션은 일반 선언을 모두 이기지만 !important에는 진다. @keyframes 안에 쓴 !important는 무시된다. 트랜지션 중인 값은 !important까지 이긴다.
자주 하는 오해:
- "클래스 문자열에서 뒤에 쓴 클래스가 이긴다"는 틀렸다.
class="a b"와class="b a"는 같다. 이기는 쪽은 스타일시트에서 나중에 선언된 규칙이고, Tailwind에서 tailwind-merge와 cn()가 필요한 이유가 이것이다 - 명시도 싸움(
!important덧칠,#id추가)으로 덮어쓰기보다, 레이어로 순서를 정하는 편이 깔끔하다 - 상속(Inheritance)되는 값(
color,font등)은 캐스케이드에서 이긴 값이 없을 때만 부모에게서 온다
명세: CSS Cascade 5 §6.1 — Cascade Sorting Order · CSS Cascade 5 §6.2 — Cascading Origins · CSS Cascade 5 §6.3 — Important Declarations 출처: MDN — Introducing the CSS Cascade: Cascading order · MDN — Introducing the CSS Cascade: Origin types · MDN — Introducing the CSS Cascade: CSS animations and the cascade