본문으로 건너뛰기

자리로 고르기

HTML·CSS 목차선택자레슨 47 / 93

목차

자리로 고르는 가상 클래스 :first-child · :last-child · :nth-child()는 부모 안에서 몇째 자식인지로 요소를 고르고, :not()은 괄호 안 조건에 맞는 것을 뺍니다. 줄이 늘거나 줄면 브라우저가 자리를 다시 셉니다.

재료 목록의 마지막 줄만 아래 선을 지우거나 표의 짝수 줄만 칠하려면, 그 줄마다 클래스를 붙이는 대신 자리로 고르면 됩니다. 클래스는 줄을 더할 때마다 옮겨 붙여야 하지만, 자리는 브라우저가 그때그때 셉니다. 다만 '마지막'이 무엇의 마지막인지 잘못 읽으면 규칙이 아무 데도 닿지 않습니다.

7단계 중 1단계. 이 그림 읽는 법: 나무 줄 앞 번호는 부모 안 자리입니다. :first-child는 1번을 고릅니다.

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-stylesolid
  • li: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-stylesolid
  • li: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
  1. li:last-child — li이면서 제 부모 안 마지막 자식인 것: ul 안 셋째 '산책하기'입니다.
  2. 결합자를 따라 왼쪽으로 — 조상에 #todo-list가 있으니 고릅니다.
  3. 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>를 넣어 보세요. 굵은 줄을 보세요.

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> 줄을 지우고 저장하고 새로고침해 재료 목록이 파랑이 되는지 봅니다. 그 줄을 다시 끝에 넣으면 어떻게 될지 먼저 적고, 저장하고 새로고침해 맞춰 봅니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

HTML·CSS 목차로