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 전체. 위가 강함.

순위분류설명
1Transition (active)진행 중인 transition (별도 라운드지만 최상위)
2UA !important브라우저가 강제하는 안전장치 (드묾)
3User !important접근성 사용자 스타일시트
4Author !important작성자의 !important
5Animation (active)진행 중인 @keyframes
6Author normal일반 작성자 CSS
7User normal일반 사용자 스타일시트
8UA 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: !importantanimation에 짐

.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로 풀어라.

다음: 캐스케이드를 마스터했으면 02-layout으로. 또는 README로 돌아가서 다른 챕터를 본다.