명시도(specificity)는 선택자가 요소를 얼마나 좁혀 고르는지를 ID · 클래스 · 태그 세 칸의 점수로 센 것입니다. 우리 규칙 여럿이 한 요소의 같은 속성에 닿으면, 브라우저는 명시도가 높은 쪽의 값을 씁니다.
할 일 화면에는 모든 단추에 닿는 공통 button 규칙이 있고, 삭제 단추에는 .delete 규칙도 닿습니다. 두 규칙이 같은 배경을 다르게 적으면 하나만 이겨야 합니다. 4단원에서는 우리 규칙이 기본 스타일을 이기는 것까지 봤습니다. 이 레슨은 우리 규칙끼리 겨룰 때 무엇을 보는지와, 이긴 값을 손으로 찾는 표를 봅니다.
이 단원을 마치면 공통 단추 규칙과 제출 단추 규칙이 겹칠 때 이기는 값을 찾고, 규칙 차례를 바꿔 결과를 뒤집어 볼 수 있습니다. 이 단원(규칙이 겹칠 때)을 이미 안다면 단원 연습 문제부터 풀고 틀린 레슨만 보세요. 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다.
그림 준비 중
1한 속성에 선언이 여럿 닿으면
4단원 브라우저 기본 스타일과 Styles 창에서 세운 규칙에 한 문장을 잇습니다.
브라우저 규칙 5. 한 요소의 한 속성에 선언이 여럿 닿으면 하나만 이깁니다. 기본 스타일보다 우리 CSS가 이기고, 그다음은 명시도가 높은 쪽이 이깁니다.
<button>추가</button>
<button class="delete">
삭제
</button>
button {
background: #9ac7ff;
font-size: 16px;
cursor: pointer;
}
.delete {
background: transparent;
}button의background-colorrgb(154, 199, 255).delete의background-colorrgba(0, 0, 0, 0).delete의font-size16px.delete의cursorpointer
- 삭제 단추의 배경에는 선언이 둘 닿아
.delete의transparent가 이깁니다. 삭제 단추만 배경이 비칩니다. - 글자 크기와
cursor(마우스를 올렸을 때 모양)는button규칙에만 있어 그 값을 씁니다. 이기고 지는 것은 규칙 통째가 아니라 속성 하나씩입니다.
background는 배경을 한 줄로 정하는 짧게 적기입니다 — 한 줄이 속성 여럿을 정합니다(10단원 여백 짧게 적기에서 자세히). 이 단원의 예는 background끼리만 겨룹니다.
2명시도 세 칸 세기
선택자 안의 조각을 세 칸에 나눠 셉니다.
| 칸 | 세는 것 | 예 |
|---|---|---|
| ID | #이름 | #count → 1-0-0 |
| 클래스 | .이름 · 속성 선택자 · 가상 클래스 | .filters button.active → 0-2-1 |
| 태그 | 태그 이름 · 가상 요소(::before) | nav a → 0-0-2 |
- 전체 선택자
*와 결합자(빈칸 ·>·+)는 0입니다.div > p는 0-0-2입니다. :not()·:has()는 괄호 안 선택자 가운데 가장 높은 점수를 셉니다.li:has(.done)은 0-1-1입니다.- 견줄 때는 왼쪽 칸부터 봅니다. ID 칸이 큰 쪽이 나머지 칸과 상관없이 이기고, 같으면 클래스 칸, 그다음 태그 칸을 봅니다. 칸끼리 받아올림은 없습니다.
3출처가 명시도보다 먼저
명시도는 같은 출처 안에서만 견줍니다. 우리 CSS와 기본 스타일 사이에서는 명시도를 보지 않습니다.
<h1>김치볶음밥</h1>
* {
margin: 0;
}body의margin-top0px
*는 모든 요소를 고르는 전체 선택자라 명시도가 0-0-0입니다. 기본 스타일에는 body { margin: 8px; }(0-0-1)이 있는데도 페이지 가장자리 틈이 사라집니다. 출처를 먼저 봐서 우리 CSS가 이겼습니다. margin은 바깥 여백의 짧게 적기입니다(10단원 '박스 모델'에서 자세히).
4손 점수판 — 이긴 값을 손으로 찾기
규칙이 많으면 머릿속으로 견주다 놓칩니다. 위 점수판을 종이에 옮긴 표가 손 점수판입니다. 한 요소를 정하고 이 차례로 칸을 채웁니다.
- 닿는 선언 모으기 — 속성마다 한 줄씩
- 출처 · 중요도 — 기본 스타일인가 우리 CSS인가(중요도는 !important 대신에서)
- 명시도 세 칸
- 나중 — 명시도까지 같을 때(다음 레슨)
- 닿는 선언이 없으면 물려받기 · 처음 값(물려받기에서)
1절의 삭제 단추를 표로 쓰면 이렇습니다. '차례'는 코드에 쓴 차례입니다.
| 속성 | 선언 | 출처 | 명시도 | 차례 | 이긴 값 |
|---|---|---|---|---|---|
background | .delete · transparent | 우리 CSS | 0-1-0 | 2 | transparent |
button · #9ac7ff | 우리 CSS | 0-0-1 | 1 | ||
font-size | button · 16px | 우리 CSS | 0-0-1 | 1 | 16px |
cursor | button · pointer | 우리 CSS | 0-0-1 | 1 | pointer |
반만 쓴 표는 안 쓴 것과 같습니다. 한 속성이라도 빼면 그 값이 어디서 왔는지 놓칩니다.
예제
할 일 화면의 필터 단추
필터 단추 가운데 고른 단추(.active)만 진한 파랑이어야 합니다.
<div class="filters">
<button class="active">
전체
</button>
<button>남은 일</button>
</div>
button {
background: #ffffff;
}
.filters button {
background: #f5f5f7;
}
.filters button.active {
background: #005bb5;
color: #ffffff;
}.active의background-colorrgb(0, 91, 181).active의 글자색rgb(255, 255, 255)button:last-child의background-colorrgb(245, 245, 247)
'전체' 단추의 background를 손 점수판으로 씁니다.
| 속성 | 선언 | 출처 | 명시도 | 차례 | 이긴 값 |
|---|---|---|---|---|---|
background | .filters button.active · #005bb5 | 우리 CSS | 0-2-1 | 3 | #005bb5 |
.filters button · #f5f5f7 | 우리 CSS | 0-1-1 | 2 | ||
button · #ffffff | 우리 CSS | 0-0-1 | 1 |
'남은 일' 단추에는 .active가 없어 셋째 규칙이 닿지 않습니다. 남은 두 줄에서 0-1-1인 .filters button의 #f5f5f7이 이깁니다.
자주 틀리는 곳
틀린 생각: 나중에 쓴 규칙이 늘 이긴다.
<button class="delete">
삭제
</button>
.delete {
color: #d70015;
}
button {
color: #1d1d1f;
}.delete의 글자색rgb(215, 0, 21)
button 규칙이 뒤에 있어도 0-1-0인 .delete가 이깁니다.
맞는 규칙: 명시도를 먼저 견주고, 쓴 차례는 명시도까지 같을 때만 봅니다(브라우저 규칙 5).
틀린 생각: 명시도는 세 칸을 더한 점수다.
<p id="t" class="a b c">가</p>
#t {
color: #005bb5;
}
.a.b.c {
color: #d70015;
}p의 글자색rgb(0, 91, 181)
.a.b.c는 0-3-0, #t는 1-0-0입니다. 더하면 3 대 1이지만, 왼쪽 ID 칸에서 이미 #t가 이깁니다. 클래스를 열 개 넘게 붙여도 ID 칸으로 넘어가지 않습니다.
맞는 규칙: 세 칸을 왼쪽부터 하나씩 견주고, 칸끼리 받아올리지 않습니다.
틀린 생각: 이긴 규칙이 그 요소의 모양을 통째로 정한다.
1절의 삭제 단추는 배경만 .delete를 따르고, 글자 크기와 cursor는 진 button 규칙의 값입니다.
맞는 규칙: 겨루기는 속성마다 따로 합니다.
확인 문제
1. 아래 코드의 1번 줄 p를 #count로 바꾸면 글자색은 무엇이 될까요? 코드에 적힌 꼴로 쓰세요.
<p id="count" class="count">
전체 3개 중 2개 남음
</p>
p {
color: #6e6e73;
}
.count {
color: #005bb5;
}힌트
바꾼 뒤 두 선택자의 명시도를 세 칸으로 적어 보세요.
정답
#6e6e73입니다.
<p id="count" class="count">
전체 3개 중 2개 남음
</p>
#count {
color: #6e6e73;
}
.count {
color: #005bb5;
}p의 글자색rgb(110, 110, 115)
| 속성 | 선언 | 출처 | 명시도 | 차례 | 이긴 값 |
|---|---|---|---|---|---|
color | #count · #6e6e73 | 우리 CSS | 1-0-0 | 1 | #6e6e73 |
.count · #005bb5 | 우리 CSS | 0-1-0 | 2 |
- 바꾸기 전에는 0-1-0인
.count가 0-0-1인p를 이겨 파랑이었습니다. 바꾼 뒤에는 ID 칸에서#count가 이깁니다(브라우저 규칙 5). - 흔한 오답은
#005bb5입니다. 뒤에 쓴.count가 이긴다고 본 것입니다(뒤가 늘 이긴다는 생각).
CSS 1번 줄의 p를 #count로 바꿔 보세요. 글자색을 보세요.
<p id="count" class="count">
전체 3개 중 2개 남음
</p> {
color: #6e6e73;
}
.count {
color: #005bb5;
}여기서 고친 코드는 저장하지도 보내지도 않습니다. 새로 열면 처음 코드입니다.
2. 할 일 한 줄의 글자색을 손 점수판으로 찾습니다. ㉠ · ㉡ · ㉢ 자리에 쓰세요.
<li class="done">
<span class="text">
우유 사기
</span>
</li>
.done .text {
color: #6e6e73;
}
li span {
color: #1d1d1f;
}
| 속성 | 선언 | 출처 | 명시도 | 차례 | 이긴 값 |
|---|---|---|---|---|---|
color | .done .text · #6e6e73 | 우리 CSS | ㉠ | 1 | ㉢ |
li span · #1d1d1f | 우리 CSS | ㉡ | 2 |
힌트
선택자마다 # · . · 태그 이름이 몇 개인지 세어 칸에 적어 보세요.
정답
㉠ 0-2-0 · ㉡ 0-0-2 · ㉢ #6e6e73입니다.
.text의 글자색rgb(110, 110, 115)
.done .text는 클래스 둘,li span은 태그 둘입니다. 사이의 빈칸(결합자)은 세지 않습니다.- ID 칸이 같아 클래스 칸에서
.done .text가 이깁니다. 뒤에 쓴li span은 집니다(브라우저 규칙 5). - ㉡을 0-0-3처럼 빈칸까지 세었다면 결합자를 조각으로 센 것입니다.
3. 여행 일정입니다. 오늘 일정(.today)만 빨갛게 하려 했는데 그대로입니다. 그 li를 고르니 Styles 창에서 .today의 color에 취소선만 그어져 있습니다. CSS 5번 줄의 선택자를 어떻게 고치면 될까요?
<ul id="plan">
<li>강릉</li>
<li class="today">속초</li>
</ul>
#plan li {
color: #1d1d1f;
}
.today {
color: #d70015;
}.today의 글자색rgb(29, 29, 31)
힌트
취소선만 그어진 선언이 찾는 차례 몇 번에 걸리는지 정하고, 두 선택자의 세 칸을 적어 보세요.
힌트 둘
두 선택자는 ID 칸에서 이미 갈립니다. .today 쪽 선택자에도 ID가 들어가야 같은 칸에서 겨룰 수 있습니다.
정답
5번 줄을 #plan .today {로 고칩니다. #plan li.today처럼 써도 됩니다.
<ul id="plan">
<li>강릉</li>
<li class="today">속초</li>
</ul>
#plan li {
color: #1d1d1f;
}
#plan .today {
color: #d70015;
}.today의 글자색rgb(215, 0, 21)
찾는 차례 4번(이겼나)에서 찾습니다. 취소선만 그어진 선언은 버린 것이 아니라 진 것입니다.
#plan li는 1-0-1,.today는 0-1-0이라 ID 칸에서 앞 규칙이 이겼습니다.#plan .today는 1-1-0입니다. ID 칸이 같아지고 클래스 칸에서 이깁니다(브라우저 규칙 5).li.today(0-1-1)로 고치면 여전히 ID 칸에서 집니다.- 흔한 오답은
color: #d70015 !important;처럼 값에 힘을 주는 것입니다. 지금은 빨개지지만 다음 규칙을 고치기 어렵게 만듭니다 — !important 대신에서 봅니다.
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
1절 예제를 index.html과 style.css로 저장하고 link로 이어 엽니다(문서 뼈대의 body 안에 예제 HTML을 넣습니다). 개발자 도구에서 삭제 단추를 고르면 Styles 창의 button 규칙에서 background에만 취소선이 있고 font-size · cursor에는 없는 것을 찾습니다. 그다음 HTML의 삭제 단추에 id="d"를 더하고 style.css의 button을 #d로 바꾸면 삭제 단추 배경이 어떻게 될지 먼저 적고, 저장한 뒤 새로고침합니다.