자리로 고르는 가상 클래스 :first-child · :last-child · :nth-child()는 부모 안에서 몇째 자식인지로 요소를 고르고, :not()은 괄호 안 조건에 맞는 것을 뺍니다. 줄이 늘거나 줄면 브라우저가 자리를 다시 셉니다.
재료 목록의 마지막 줄만 아래 선을 지우거나 표의 짝수 줄만 칠하려면, 그 줄마다 클래스를 붙이는 대신 자리로 고르면 됩니다. 클래스는 줄을 더할 때마다 옮겨 붙여야 하지만, 자리는 브라우저가 그때그때 셉니다. 다만 '마지막'이 무엇의 마지막인지 잘못 읽으면 규칙이 아무 데도 닿지 않습니다.
1부모 안의 자리 — 1부터 센다
자리는 부모 안 자식을 위에서부터 1, 2, 3으로 셉니다.
<ul>
<li>밥 2공기</li>
<li>잘 익은 김치 1컵</li>
<li>달걀 2개</li>
<li>참기름 1큰술</li>
<li>김가루 조금</li>
</ul>
li:first-child {
font-weight: bold;
}
li:nth-child(even) {
background-color: #f5f5f7;
}li:first-child의 고른 글밥 2공기li:last-child의 고른 글김가루 조금li:nth-child(2)의 고른 글잘 익은 김치 1컵li:nth-child(even)의 고른 글잘 익은 김치 1컵 · 참기름 1큰술li:nth-child(odd)의 고른 글밥 2공기 · 달걀 2개 · 김가루 조금
| 가상 클래스 | 고르는 자식 |
|---|---|
:first-child | 첫째 |
:last-child | 마지막 |
:nth-child(2) | 둘째 — 번호는 1부터 |
:nth-child(even) | 짝수째(2 · 4 · 6 …) |
:nth-child(odd) | 홀수째(1 · 3 · 5 …) |
표의 줄무늬도 같은 길입니다 — tr:nth-child(even)은 짝수째 줄을 고릅니다. 목록에 줄을 더하거나 빼면 브라우저가 나무를 다시 지은 뒤 자리를 다시 세어 다시 고릅니다(브라우저 규칙 4).
2:not() — 괄호 안 조건을 뺀다
재료 줄 사이에 아래 선을 긋고 마지막 줄만 지우는 길은 둘입니다. 선은 CSS가 그립니다 — 10단원 '박스 모델'에서 자세히 봅니다.
<ul>
<li>밥 2공기</li>
<li>달걀 2개</li>
<li>김가루 조금</li>
</ul>
li {
border-bottom:
1px solid #d2d2d7;
}
li:last-child {
border-bottom: none;
}li:first-child의border-bottom-stylesolidli:last-child의border-bottom-stylenone
모든 줄에 선을 그은 뒤 마지막 줄에서 지웠습니다. 같은 결과를 규칙 하나로 쓸 수도 있습니다.
<ul>
<li>밥 2공기</li>
<li>달걀 2개</li>
<li>김가루 조금</li>
</ul>
li:not(:last-child) {
border-bottom:
1px solid #d2d2d7;
}li:first-child의border-bottom-stylesolidli:last-child의border-bottom-stylenone
:not(:last-child)는 '마지막 자식이 아닌 것'을 고릅니다. 처음부터 마지막 줄을 빼고 그었습니다. 레시피 노트처럼 목록이 여럿인 페이지는 .ingredient-list li:last-child처럼 목록의 클래스를 앞에 붙여 그 목록 안으로 좁힙니다.
3가상 요소 — 요소의 한 부분
콜론 둘(::)로 시작하는 선택자 조각은 가상 요소(pseudo-element — 자료에 따라 의사 요소)입니다. 요소 전체가 아니라 그 한 부분을 고릅니다. ::placeholder는 입력 칸의 placeholder 글을, ::before는 요소 내용 바로 앞에 CSS가 content로 넣는 글을 고릅니다. 이 단원에서는 이름만 알아 둡니다.
예제
할 일 목록 — 마지막 줄 선 지우기
할 일 화면의 #todo-list li:last-child를 오른쪽부터 읽습니다.
<ul id="todo-list">
<li>우유 사기</li>
<li class="done">책 읽기</li>
<li>산책하기</li>
</ul>
<p>전체 3개 중 2개 남음</p>
#todo-list li {
border-bottom:
1px solid #d2d2d7;
}
#todo-list li:last-child {
border-bottom: none;
}#todo-list li:last-child의 고른 글산책하기#todo-list li:last-child의border-bottom-stylenone
li:last-child—li이면서 제 부모 안 마지막 자식인 것:ul안 셋째 '산책하기'입니다.- 결합자를 따라 왼쪽으로 — 조상에
#todo-list가 있으니 고릅니다. ul뒤에p가 있어도 상관없습니다.li의 부모는ul이고, 자리는 그 부모 안에서 셉니다.
자주 틀리는 곳
틀린 생각: :last-child는 '그 종류 가운데 마지막'이다 — ul:last-child는 마지막 ul을 고른다.
<section>
<h2>재료</h2>
<ul>
<li>밥 2공기</li>
</ul>
<p>2인분입니다.</p>
</section>
section ul:last-child {
color: #005bb5;
}ul의 color 선언(없음)ul의 글자색rgb(0, 0, 0)
section의 마지막 자식은 ul이 아니라 p입니다. ul:last-child는 'ul이면서 마지막 자식'이라 아무것도 고르지 않습니다. 끝에 문단을 더하자 잘 먹던 규칙이 조용히 떨어집니다.
맞는 규칙: :last-child는 종류를 가리지 않고 부모 안 모든 자식 가운데 마지막입니다(브라우저 규칙 4). 그 종류 가운데 마지막을 고르는 :last-of-type도 있습니다(이름만).
틀린 생각: 자리 번호는 0부터 센다 — :nth-child(2)는 셋째, even은 첫째 줄부터다.
<ol>
<li>김치 썰기</li>
<li>김치 볶기</li>
<li>밥 넣기</li>
</ol>
li:nth-child(even) {
color: #005bb5;
}li:nth-child(even)의 고른 글김치 볶기
둘째 줄 하나만 파랑입니다. 첫째 줄은 1이라 홀수입니다.
맞는 규칙: 자리 번호는 1부터 셉니다. even은 2 · 4 · 6째, odd는 1 · 3 · 5째입니다.
틀린 생각: ::before로 넣은 글은 꾸밈이라 화면 읽기 프로그램이 읽지 않는다.
<button class="new">저장</button>
.new::before {
content: "새 ";
}button의 읽는 이름새 저장
단추의 읽는 이름이 '새 저장'입니다. CSS로 넣은 글도 그려지는 글이라 읽는 이름에 듭니다.
맞는 규칙: ::before · ::after로 넣은 글도 읽힙니다. 뜻이 있는 글은 HTML에 쓰고, CSS로는 꾸밈만 넣습니다(브라우저 규칙 3).
확인 문제
1. 1절 예제의 목록을 한 줄로 줄였습니다. 빈 2번 줄에 <li>대파 조금</li>를 넣으면 굵게 그려지는 줄을 모두 고르세요. 기호를 다 쓰세요.
<ul>
<li>밥 2공기</li>
</ul>
li:first-child {
font-weight: bold;
}- ㉠
li대파 조금 - ㉡
li밥 2공기 - ㉢ 없음
힌트
넣은 뒤의 ul 안 자식을 위에서부터 1, 2, 3으로 적어 보세요.
정답
㉠ — '대파 조금' 하나입니다.
<ul>
<li>대파 조금</li>
<li>밥 2공기</li>
</ul>
li:first-child {
font-weight: bold;
}li:first-child의 고른 글대파 조금li:nth-child(2)의 font-weight 선언(없음)
- 줄을 넣으면 브라우저가 자리를 다시 셉니다. 첫째 자식이 '대파 조금'으로 바뀌어 굵은 모양도 그리로 옮겨 갑니다(브라우저 규칙 4).
- 흔한 오답은 ㉡입니다. 모양이 처음 고른 줄에 붙어 남는다고 본 것입니다. 규칙은 자리로 고를 뿐 줄에 붙지 않습니다.
빈 2번 줄에 <li>대파 조금</li>를 넣어 보세요. 굵은 줄을 보세요.
<ul>
<li>밥 2공기</li>
</ul>li:first-child {
font-weight: bold;
}여기서 고친 코드는 저장하지도 보내지도 않습니다. 새로 열면 처음 코드입니다.
2. 마지막 줄을 뺀 줄에만 파랑을 칠하려 합니다. ____ 자리를 채우세요.
li:not(____) {
color: #005bb5;
}
힌트
1절 표에서 빼고 싶은 줄을 고르는 조각을 찾아보세요.
힌트 둘
'마지막 줄'을 고르는 가상 클래스를 괄호 안에 넣어 보세요.
정답
:last-child
<ul>
<li>밥 2공기</li>
<li>김가루 조금</li>
</ul>
li:not(:last-child) {
color: #005bb5;
}li:not(:last-child)의 고른 글밥 2공기
- 흔한 오답은 괄호 안에 콜론을 빼고
last-child만 쓰는 것입니다. 그러면last-child라는 태그를 찾는 말이 되어, 마지막 줄까지 모두 칠합니다.
3. 여행 일정 페이지입니다. 굵게 그려지는 요소를 모두 고르세요. 기호를 다 쓰세요.
<div class="day">
<h2>첫날</h2>
<p>바다에 갑니다.</p>
<p>저녁은 회입니다.</p>
<a href="#photo">사진 보기</a>
</div>
.day p:last-child {
font-weight: bold;
}
- ㉠
h2첫날 - ㉡
p바다에 갑니다. - ㉢
p저녁은 회입니다. - ㉣
a사진 보기 - ㉤ 없음
힌트
.day 안 자식을 위에서부터 적고, 마지막 자식이 무엇인지 표시해 보세요.
정답
㉤ — 굵어지는 요소가 없습니다.
.day p의 font-weight 선언(없음).day a의 font-weight 선언(없음)
p:last-child는 'p이면서 부모 안 마지막 자식'입니다..day의 마지막 자식은a라 두 조건을 다 갖춘 요소가 없습니다(브라우저 규칙 4).- ㉢을 고른 것은
:last-child를 'p가운데 마지막'으로 본 것입니다. 그 뜻은:last-of-type입니다. - ㉣을 고른 것은 앞 조각
p를 빼고 '마지막 자식'만 본 것입니다. 붙여 쓴 조건은 모두 맞아야 합니다.
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
자주 틀리는 곳 첫째 예제를 style 요소로 한 파일에 담아 section.html로 저장해 엽니다. 먼저 <p>2인분입니다.</p> 줄을 지우고 저장하고 새로고침해 재료 목록이 파랑이 되는지 봅니다. 그 줄을 다시 끝에 넣으면 어떻게 될지 먼저 적고, 저장하고 새로고침해 맞춰 봅니다.