한 줄 정답 — 여러 규칙이 한 요소를 두고 부딪히면, 브라우저는 선택자를 세 칸(ID 개수 · 클래스/속성/가상클래스 개수 · 타입/가상요소 개수) 으로 점수 매겨 더 높은 쪽을 적용한다. 왼쪽 칸이 우선이라 ID 하나(1,0,0)가 클래스 백 개(0,100,0)를 이긴다. 인라인 style 속성은 그보다 위, !important는 그 모두를 뒤집는다. 점수가 완전히 같으면 나중에 온 규칙이 이긴다.

핵심 요약#

  • 우선순위(명시도)는 숫자 하나가 아니라 세 칸의 점수다. 왼쪽 칸부터 비교해 큰 쪽이 이긴다.
  • 칸 배정: ID → 첫째 칸, 클래스·속성·가상 클래스(:hover 등) → 둘째 칸, 타입(요소)·가상 요소(::before 등) → 셋째 칸.
  • 인라인 style="..."는 어떤 선택자보다 강하다. *와 결합자(>, +, ~, 공백)는 점수에 더해지지 않는다.
  • !important는 점수 싸움 자체를 건너뛰고 일반 선언을 덮어쓴다. 남용하면 나중에 손쓰기 어려우니 최후의 수단이다.
  • 점수가 완전히 같으면 스타일시트에서 더 아래(나중)에 온 규칙이 이긴다.

CSS 선택자 우선순위를 점수 세 칸으로 계산하기#

같은 요소에 여러 규칙이 걸리면 브라우저는 그중 하나를 골라야 한다. 이때 기준이 명시도(specificity), 흔히 말하는 선택자 우선순위다. 핵심은 우선순위가 단일 숫자가 아니라 (ID, 클래스, 타입) 세 칸짜리 점수라는 것이다. 이 세 칸을 셀 줄 알면 "왜 내 CSS가 안 먹지"의 대부분이 풀린다.

세 칸은 이렇게 센다#

선택자 하나를 보고 종류별 개수를 칸에 적는다.

  • 첫째 칸 — ID 선택자(#header) 개수
  • 둘째 칸 — 클래스(.btn), 속성([type="text"]), 가상 클래스(:hover, :nth-child) 개수
  • 셋째 칸 — 타입/요소(div, a), 가상 요소(::before, ::after) 개수

예를 들어 #nav .item a:hover는 ID 1개(#nav), 클래스·가상 클래스 2개(.item, :hover), 타입 1개(a)라서 점수가 1,2,1이다.

#nav .item a:hover { color: red; }   /* 1,2,1 */
nav ul li a       { color: blue; }   /* 0,0,4 */

위 둘이 같은 링크에 부딪히면, 타입 4개짜리(0,0,4)가 아니라 ID가 든 1,2,1이 이겨 빨강이 적용된다.

왼쪽 칸이 먼저, 자리올림은 없다#

비교는 왼쪽 칸부터 한다. 첫째 칸이 크면 그걸로 끝이고, 같을 때만 둘째 칸을, 또 같을 때만 셋째 칸을 본다. 중요한 건 자리올림이 없다는 점이다. 클래스를 아무리 많이 붙여도 ID 하나를 못 넘는다.

.a.b.c.d.e.f.g.h.i.j { color: black; }   /* 0,10,0 */
#title               { color: green; }   /* 1,0,0  → 이쪽이 이긴다 */

클래스 열 개(0,10,0)보다 ID 하나(1,0,0)가 강하다. 10이 1로 올라가는 십진수 계산이 아니라, 칸을 따로따로 비교하기 때문이다.

인라인 style과 !important는 어디에 있나#

선택자 점수 위에 두 단계가 더 있다.

  • 인라인 style 속성 — HTML 태그에 직접 쓴 style="color:red"는 어떤 선택자보다 강하다. 칸 밖, 더 위에 있는 1,0,0,0이라고 보면 된다. 그래서 인라인 스타일을 선택자로 덮으려면 보통 !important가 필요하다.
  • !important — 선언 끝에 붙이면(color: red !important;) 점수 싸움을 통째로 건너뛰고 일반 선언을 덮어쓴다. !important끼리 부딪힐 때만 다시 평소의 명시도·순서 규칙으로 가린다.

!important는 강력한 만큼 한번 쓰면 그 값을 또 !important로만 이길 수 있어 규칙이 엉킨다. 라이브러리 스타일을 어쩔 수 없이 누를 때 정도로 아끼는 게 좋다.

점수가 같으면 — 나중에 온 규칙이 이긴다#

세 칸 점수가 완전히 같으면 마지막으로 캐스케이드의 순서 규칙이 정한다. 같은 출처·같은 점수라면 스타일시트에서 더 아래에 쓴(나중에 선언한) 규칙이 이긴다.

.btn { color: blue; }
.btn { color: green; }   /* 점수 같음 → 나중 규칙이 이겨 초록 */

CSS 파일을 여러 개 불러올 때는 <link> 순서도 곧 선언 순서다. 나중에 불러온 파일이 앞선 같은-점수 규칙을 덮는다.

한눈 비교#

선택자 종류들어가는 칸점수
타입(요소)·가상 요소셋째 칸p, h1, ::before0,0,1
클래스·속성·가상 클래스둘째 칸.btn, [type="text"], :hover0,1,0
ID첫째 칸#header1,0,0
인라인 style 속성칸 밖, 더 위style="color:red"1,0,0,0
*·결합자(> + ~ 공백)점수에 안 더해짐*, div > p0,0,0

!important는 위 모든 점수를 무시하고 일반 선언을 덮어쓴다. 표의 점수 싸움은 같은 중요도(일반 또는 !important끼리)일 때 이야기다.

CSS가 안 먹을 때, 우선순위로 진단하기#

분명히 쓴 스타일이 적용되지 않는다면, 다음 순서로 짚으면 대개 원인이 잡힌다.

  1. 브라우저 개발자도구로 확인한다. 요소를 검사하면 적용된 규칙과 함께, 더 센 규칙에 눌려 취소선이 그어진 선언이 보인다. 무엇이 이기고 있는지부터 눈으로 본다.
  2. 이긴 규칙의 점수를 센다. 그 선택자에 ID가 섞여 있지 않은지(첫째 칸), 클래스가 더 많지 않은지 본다. 내 규칙보다 왼쪽 칸이 크면 진 것이다.
  3. 점수가 같다면 순서를 본다. 같은 점수면 나중에 온 규칙이 이긴다. 내 규칙을 더 아래로 옮기거나 선언 순서를 바꾼다.
  4. 점수를 올려 이긴다. 무작정 !important를 붙이기 전에, 선택자를 한 단계 구체적으로(예: .card .title처럼 클래스 하나 추가) 만들어 점수로 정정당당히 이기는 쪽을 먼저 시도한다.
  5. 인라인 스타일·!important를 의심한다. 상대가 인라인 style이나 !important라면 일반 선택자로는 못 이긴다. 가능하면 그 인라인/!important를 걷어내고, 정 안 되면 같은 무기로 맞선다.

오타나 선택자 범위 착오(있지도 않은 자식을 가리키는 등)도 흔한 원인이다. 점수가 분명히 높은데도 안 먹으면 선택자가 실제로 그 요소를 가리키는지부터 다시 본다.

자주 묻는 질문#

Q. CSS 우선순위는 어떻게 계산하나요?

A. 선택자에 든 ID 개수, 클래스·속성·가상 클래스 개수, 타입·가상 요소 개수를 각각 세어 (ID, 클래스, 타입) 세 칸 점수를 만듭니다. 왼쪽 칸부터 비교해 큰 쪽이 이기고, 같으면 다음 칸을 봅니다. 자리올림이 없어서 클래스를 아무리 많이 붙여도 ID 하나를 넘지 못합니다.

Q. !important는 써도 되나요?

A. 됩니다만 최후의 수단입니다. !important는 점수 싸움을 건너뛰고 일반 선언을 덮어쓰는데, 한번 쓰면 그 값을 또 다른 !important로만 이길 수 있어 스타일이 금방 엉킵니다. 라이브러리나 인라인 스타일을 어쩔 수 없이 눌러야 할 때만 쓰고, 평소엔 선택자를 한 단계 구체적으로 만들어 점수로 이기는 편이 낫습니다.

Q. 인라인 스타일이 제일 강한가요?

A. 선택자 중에서는 가장 강합니다. 태그에 직접 쓴 style="..."는 ID·클래스 어떤 선택자보다 우선해서, 외부 CSS로 덮으려면 보통 !important가 필요합니다. 다만 !important가 붙은 일반 선언은 인라인 스타일도 이깁니다. 그래서 강함의 순서는 대략 일반 선택자 < 인라인 style < !important입니다.

Q. CSS가 안 먹는데 우선순위 문제인지 어떻게 아나요?

A. 개발자도구로 요소를 검사하면 적용된 규칙 목록에서, 더 센 규칙에 눌린 선언에 취소선이 그어져 보입니다. 취소선이 있으면 우선순위(또는 선언 순서) 문제이고, 선언 자체가 목록에 아예 없으면 선택자가 그 요소를 못 가리키는 것이라 오타나 범위를 다시 봐야 합니다.

관련 글#

우선순위는 선택자를 어떻게 쓰느냐에서 시작한다. 점수 계산이 잡혔다면, 선택자 자체와 캐스케이드를 강의 흐름으로 더 깊이 보면 좋다.

더 알아보기#