06 — !important & Origins
한 줄 답:
!important는 cascade의 origin 순서를 뒤집는 단 하나의 메커니즘이다. 원래 정신은 사용자(독자)의 접근성 보호 — 그래서 사용자의!important가 작성자의!important를 이긴다. 작성자가 이걸 만능 망치로 쓰는 순간 자기 사용자를 무력화한다.
Why — 왜 !important가 있는가
CSS1 명세(1996) Section 3.1:
“Designers must balance their own desires with those of their readers. The cascading mechanism allows readers to override designer rules where this is necessary.”
CSS는 처음부터 3주체의 협상으로 설계됐다.
| 주체 | 역할 | 예 |
|---|---|---|
| UA (User Agent) | 브라우저의 기본 스타일 | h1 { font-size: 2em }, 링크 파랑 밑줄 |
| User (독자) | 자기 필요에 맞춘 사용자 스타일시트 | 시각장애인의 폰트 키움, 색약자의 색 변경 |
| Author (개발자) | 웹페이지 작성자 | body { background: #fff } |
기본 순서: author > user > UA. 작성자가 디자인을 책임지므로 가장 강하다.
하지만 사용자에겐 양보할 수 없는 영역이 있다 — 접근성. 시각장애인이 폰트를 24px로 키운 걸 작성자가 12px로 덮으면 그 사이트는 못 쓰는 사이트다.
1998년 CSS2가 !important를 추가하면서, 사용자가 작성자를 이기는 비상구를 열었다.
normal: author > user > UA
important: user > author > UA ← 역전!이게 *원래의 !important*다. 작성자가 자기 코드에 !important를 쓰는 건 부수효과다.
How — Origin과 Importance의 전체 매트릭스
1) 완전 우선순위표
cascade의 라운드 1 전체. 위가 강함.
| 순위 | 분류 | 설명 |
|---|---|---|
| 1 | Transition (active) | 진행 중인 transition (별도 라운드지만 최상위) |
| 2 | UA !important | 브라우저가 강제하는 안전장치 (드묾) |
| 3 | User !important | 접근성 사용자 스타일시트 |
| 4 | Author !important | 작성자의 !important |
| 5 | Animation (active) | 진행 중인 @keyframes |
| 6 | Author normal | 일반 작성자 CSS |
| 7 | User normal | 일반 사용자 스타일시트 |
| 8 | UA normal | 브라우저 기본 |
2) 두 그룹의 비대칭
normal 분류 안: Author > User > UA (높은 권한이 이김)
important 분류 안: User > Author > UA (낮은 권한이 이김 — 역전)UA !important는 매우 드물지만 존재한다 — 예: :focus의 outline (브라우저가 사용자 접근성을 위해 끄지 못하게).
3) 작성자 안에서 !important의 의미
작성자 코드 안에서만 보면 !important는 단지 normal보다 강함. specificity와 무관.
.btn { color: red !important; } /* important */
#cta { color: blue; } /* normal — specificity 더 높지만 짐 */
/* → red */4) @layer와 만나면 역전
이전 문서에서 본 그 규칙:
- normal: 나중 layer가 이김.
- important: 먼저 layer가 이김.
@layer base, theme;
@layer base {
.btn { color: red !important; } /* 먼저 layer, important */
}
@layer theme {
.btn { color: blue !important; } /* 나중 layer, important */
}
/* → red */논리: !important는 근본적 안전장치이므로 reset/base의 보호장치를 후속 layer가 못 깨도록.
What — 실전 케이스
케이스 1: 사용자 스타일시트의 폰트 강제
(Chrome: 고급 사용자가 자체 CSS 적용 가능. Firefox: userContent.css)
/* 사용자가 쓴 거 */
* {
font-family: "Atkinson Hyperlegible" !important;
font-size: 18px !important;
}이건 모든 사이트의 어떤 !important도 이긴다 (사용자 important > 작성자 important).
작성자로서 어떻게 해야 하나: !important를 최소화하고, :where()로 specificity 0의 base만 만들면 사용자가 더 쉽게 덮을 수 있다.
케이스 2: 라이브러리가 !important로 박은 걸 풀기
/* bootstrap.css */
.text-center { text-align: center !important; }이걸 덮으려면:
/* 옵션 1: 같은 important 더 늦게 */
.my-text-center-override { text-align: left !important; }/* 옵션 2 (권장): @layer로 격리 */
@layer framework, app;
@import url("bootstrap.css") layer(framework);
@layer app {
.text-center { text-align: left; }
/* important 없이도 이김 — app layer가 더 늦음, normal에서 비교 */
}
/* 잠깐 — bootstrap이 .text-center에 !important면 framework의 important다. */
/* app의 normal은 framework의 normal보다 강하지만 framework의 important에 진다. */
/* → 결국 app도 important 필요 */실용 결론: 라이브러리가 !important를 박으면 우리도 !important. 그래서 !important를 안 쓰는 라이브러리(Tailwind v4)가 모던 표준이 되었다.
케이스 3: animation을 !important로 정지
.shake {
animation: shake 0.5s infinite;
}
@media (prefers-reduced-motion) {
.shake {
animation: none !important;
}
}prefers-reduced-motion 사용자가 사이트 안에서 애니메이션 강제 끄기. 이 use case는 !important가 정당하게 쓰이는 거의 유일한 케이스.
케이스 4: 인라인 style을 덮기
<div style="color: red;">...</div>인라인 style은 normal이지만 specificity (1,0,0,0)으로 최강. 일반 selector로는 못 덮는다.
div { color: blue !important; } /* normal author이 important로 올라가 이김 */!important로만 가능. (또는 style=을 JS로 빼는 것.)
케이스 5: print 스타일
@media print {
* {
background: white !important;
color: black !important;
box-shadow: none !important;
}
}인쇄 시 어떤 작성자 스타일도 무시하고 안전한 기본으로 — !important의 정당한 용도. (잉크/토너 절약, 가독성.)
케이스 6: 다크모드 강제
@media (prefers-color-scheme: dark) {
:root {
--bg: #111 !important;
}
}!important로 사용자의 OS 설정을 작성자의 자체 토글보다 강하게 두는 패턴. 다만 권장은 toggle UI가 있으면 그쪽이 우선하도록 안 쓰는 것.
What-if — !important 안티패턴
사고 1: 모든 줄에 !important
.btn-primary {
background: blue !important;
color: white !important;
padding: 8px 16px !important;
border: none !important;
}증상:
- 어떤 변형(
.btn-primary.outline)을 만들어도 못 덮어 또!important. - 사용자의 접근성 설정을 무력화.
- 디버깅 시 “왜 안 먹히지”의 후순위 단서가 사라짐.
해결:
@layer로 우선순위를 구조적으로 표현.- 정 못 풀면 문제의 selector specificity를 낮춰서
!important를 뺀다.
사고 2: 한 줄 !important로 시작 → 폭주
.modal { z-index: 999 !important; }
/* 1주일 후, 다른 모달이 위에 떠야 한다 */
.modal-top { z-index: 9999 !important; }
/* 또 1주일 후 */
.modal-toast { z-index: 99999 !important; }z-index는 !important 폭주의 단골. 해결: 토큰 정의.
:root {
--z-base: 0;
--z-dropdown: 100;
--z-modal: 200;
--z-toast: 300;
}
.modal { z-index: var(--z-modal); }사고 3: !important가 animation에 짐
.box { background: red !important; animation: pulse 1s; }
@keyframes pulse {
to { background: blue; }
}가정: !important니까 red 고정?
현실: !important(author) > animation. red 고정 맞음.
하지만:
.box { background: red; animation: pulse 1s; }(important 없음) → animation이 author normal보다 위 → blue로 변함.
!important는 animation도 멈출 정도로 강하다는 걸 알아두자.
사고 4: !important가 transition을 못 막음
.box { background: red !important; transition: background 1s; }
.box:hover { background: blue !important; }hover하면 transition이 발동 — important 분류와 무관하게 transition active가 모든 걸 이긴다. red → blue로 부드럽게 변함.
transition은 cascade의 별도 라운드임을 잊지 말자.
Insight — !important는 디자이너의 망치가 아니라 사용자의 비상구
CSS1을 만든 Håkon Wium Lie(노르웨이)의 박사논문(2005)을 읽으면, cascade의 핵심 동기가 명확하다:
“The user should have the final say.” — Cascading Style Sheets, Designing for the Web (Lie, 1999)
cascade는 디자이너가 모든 걸 결정하는 워드 처리 방식과 다르게, 읽는 사람과 협상하는 방식이어야 했다. !important는 그 협상의 비상 신호다.
그런데 2000년대 web의 폭발과 함께 본래 의도가 반전됐다.
- 사용자 스타일시트 = 거의 안 씀 (모르거나, UI가 숨겨져 있거나)
- 작성자 =
!important를 디자인 시스템 충돌 해결의 망치로 사용
이는 cascade의 정치적 균형이 무너진 결과다. 작성자의 모든 !important는 어딘가의 시각장애인 사용자의 폰트 확대를 막을 가능성이 있다. 우리는 이걸 거의 의식하지 않는다.
@layer(2022)와 :where()(2021)의 등장은 이 균형의 복원 시도다.
:where(): 작성자가 자발적으로 specificity 0을 선언 — 내가 양보한다.@layer: 작성자가 자기 코드 내 우선순위를 표현 —!important로 origin을 침범하지 않아도 된다.
2000년대: !important로 뭐든 이긴다
2020년대: @layer로 자기들끼리 정리하고, :where()로 사용자에 양보한다이건 단순한 기능 추가가 아니라 CSS의 윤리적 복원이다. 우리가 다시 사용자의 비상구로서의 !important를 존중하는 방향.
요약 + Mermaid
!important는 cascade 라운드 1에서 origin 순서를 뒤집는다.- 정상 순서: author > user > UA. important 순서: user > author > UA.
- 라이브러리의
!important를 풀려면 우리도!important필요 → 라이브러리는 안 쓰는 게 정답 (Tailwind v4). @layer+!important는 먼저 선언된 layer가 이긴다 (직관 반대).!important의 정당한 용도: print, reduced-motion, 인라인 style 덮기. 그 외엔 @layer로 풀어라.