이름표를 맞춘 HTML은 앞 레슨에서 나눈 영역 일곱을 HTML로 쓰고, id · class · data-filter를 자바스크립트 과목의 할 일 앱과 한 글자도 다르지 않게 붙이는 일입니다. 그 과목의 코드는 이 이름표로 요소를 찾습니다. 이름표가 한 글자만 달라도 요소를 찾지 못해 동작이 붙지 않습니다.
이 레슨은 40분 안팎입니다. 영역 하나를 쓸 때마다 저장하고 새로고침해, 앞 레슨 확인 목록의 그 줄을 맞춰 봅니다. 영역마다 멈췄다가 이어 써도 됩니다. 폰으로만 보고 있다면 코드를 읽으며 확인 문제로 따라옵니다.
앞 레슨의 확인 목록 — 영역마다 다 되면 보이는 것
| 영역 | 다 되면 보이는 것 | 볼 곳 |
|---|---|---|
| 문서 | 탭에 '오늘 할 일' | 화면 |
| ① 제목 | 맨 위에 '오늘 할 일' 한 줄 | 화면 |
| ② 한마디 | '오늘도 한 걸음씩.' 한 줄 | 화면 |
| ③ 폼 | 입력 칸에 '예: 장보기'가 흐리게, 옆에 '추가' 단추 · 칸의 읽는 이름 '할 일' | 화면 · Elements 패널 |
| ④ 필터 | 단추 셋 '전체' · '진행 중' · '완료' | 화면 |
| ⑤ 목록 | 세 줄 '우유 사기' · 'HTML·CSS 복습하기' · '산책하기', 둘째 줄만 체크 | 화면 |
| ⑥ 빈 안내 | 화면에는 없고, 나무에는 '할 일이 없습니다.' | Elements 패널 |
| ⑦ 아랫줄 | '전체 3개 중 2개 남음'과 '완료한 일 지우기' 단추 | 화면 |
| 전체 | 검사기 Error 0 | 검사기 |
그림 준비 중
1이름표 한눈에 — 자바스크립트 과목이 찾는 이름
id는 여덟입니다. 자바스크립트 과목은 이 이름으로 요소를 하나씩 찾아 동작을 붙입니다.
id | 붙는 요소 | 자바스크립트 과목에서 |
|---|---|---|
quote | ② 한마디 p | 받아 온 한마디를 넣는다 |
todo-form | ③ form | 제출을 받는다 |
todo-input | ③ 입력 칸 | 친 글을 읽는다 |
filters | ④ 필터 단추 묶음 | 누른 필터를 받는다 |
todo-list | ⑤ ul | 할 일 목록을 다시 그린다 |
empty | ⑥ 빈 안내 p | 목록이 비면 보인다 |
count | ⑦ 개수 p | 남은 개수를 쓴다 |
clear-done | ⑦ 지우기 단추 | 끝낸 줄을 지운다 |
class는 열둘입니다 — app · quote · sr-only · filters · active · empty · footer · count · clear · done · text · delete. 대부분 CSS가 꾸밀 자리이고, active와 done은 상태를 나타내 JavaScript가 붙였다 뗍니다. 필터 단추 셋에는 data-filter로 all · active · done을 적습니다.
이름표는 글자 그대로 씁니다. 하이픈 하나, 대문자 하나만 달라도 다른 이름입니다. id는 한 페이지에 하나라(id와 class), 줄마다 붙는 text · delete · done은 class입니다.
2① ~ ③ 뼈대 · 제목 · 한마디 · 폼
index.html을 새로 만들어 문서 뼈대를 쓰고, title 아래 style.css를 잇는 줄을 넣습니다. style.css는 아직 없어도 됩니다. 브라우저는 받지 못한 파일을 건너뛰고 기본 스타일로 그립니다(CSS 연결하기).
<head>
…
<title>오늘 할 일</title>
<link
rel="stylesheet"
href="style.css"
/>
</head>
<body>
<main class="app">
<h1>오늘 할 일</h1>
</main>
</body>
영역 일곱은 모두 main.app 안, h1 아래에 차례로 넣습니다. 다음은 ② 한마디입니다.
<p id="quote" class="quote">
오늘도 한 걸음씩.
</p>한마디처럼 id와 class를 같은 글자로 둘 다 붙인 요소가 넷입니다 — 한마디 · 필터 · 빈 안내 · 개수. 자바스크립트 과목은 id로 찾고, CSS는 class로 꾸밉니다.
③ 폼은 바깥 form과 제출 단추부터 씁니다.
<form id="todo-form">
<button type="submit">
추가
</button>
</form>form 안, 단추 앞에 숨긴 라벨과 입력 칸을 넣습니다.
<label
class="sr-only"
for="todo-input"
>
할 일
</label>
<input
id="todo-input"
type="text"
placeholder="예: 장보기"
autocomplete="off"
maxlength="100"
/>#todo-input의 읽는 이름할 일
- 칸의 읽는 이름은 라벨의 '할 일'입니다.
placeholder의 '예: 장보기'는 칸이 빈 동안 흐리게 보이는 보기 글일 뿐 이름이 아닙니다(label로 칸에 이름 붙이기). autocomplete="off"는 브라우저가 저장해 둔 글을 칸에 채우라고 띄우지 않게 하고,maxlength="100"은 100자보다 길게 쳐지지 않게 막습니다(브라우저가 해 주는 검사).- 라벨은 지금 결과 화면에 보입니다.
sr-only는 아직 이름표일 뿐이고, 숨기는 규칙은 CSS에 둡니다(글자 없는 단추와 숨긴 라벨).
3④ ~ ⑦ 필터 · 목록 · 빈 안내 · 아랫줄
④ 필터는 div#filters.filters 안에 단추 셋입니다. 앞 두 단추입니다.
<button
type="button"
data-filter="all"
class="active"
>
전체
</button>
<button
type="button"
data-filter="active"
>
진행 중
</button>.active의 고른 글전체[data-filter="active"]의 고른 글진행 중
active라는 글자가 두 곳에 있지만 하는 일이 다릅니다. data-filter="active"는 이 단추가 보일 줄의 종류(진행 중인 줄)를 적은 값이고, class="active"는 지금 골라 둔 단추라는 표시입니다. 처음에는 '전체'를 골라 둔 상태라 class="active"가 '전체'에 붙습니다. 자바스크립트 과목에서 다른 단추를 누르면 이 클래스를 그 단추로 옮깁니다.
셋째 단추 '완료'는 data-filter="done"이고, 셋을 div로 감쌉니다.
<div
id="filters"
class="filters"
>
…
<button
type="button"
data-filter="done"
>
완료
</button>
</div>
필터 단추는 form 밖에 있어 type을 빼도 지금은 눌러서 아무 일이 없습니다. 그래도 type="button"을 적어 둡니다. 단추를 나중에 form 안으로 옮기면 type 없는 단추는 제출 단추가 되기 때문입니다(단추의 type).
⑤ 목록은 ul#todo-list 안에 할 일 한 줄씩 li입니다. 첫 줄 li 안에 넣는 자식 셋 — 체크박스 · 글 · × 단추입니다.
<input
type="checkbox"
aria-label="완료 표시"
/>
<span class="text">
우유 사기
</span>
<button
type="button"
class="delete"
aria-label="삭제"
>
×
</button>input의 읽는 이름완료 표시button의 읽는 이름삭제
체크박스는 옆에 글자 라벨을 둘 자리가 없어 aria-label로 이름을 붙이고, × 단추도 기호 대신 '삭제'로 읽히게 합니다.
둘째 줄 'HTML·CSS 복습하기'는 끝낸 일입니다. 끝낸 일은 두 곳에 적습니다.
<li class="done">
<input
type="checkbox"
aria-label="완료 표시"
checked
/>
<span class="text">
HTML·CSS 복습하기
</span>
…
</li>
checked는 체크박스에 체크 표시를 그리고, li의 class="done"은 이 줄이 끝낸 줄이라는 이름표입니다. 끝낸 줄의 취소선은 CSS가 .done이 붙은 줄에 긋습니다. 자바스크립트 과목도 체크 표시와 이 클래스를 함께 바꿉니다.
⑥ 빈 안내는 hidden으로 숨겨 둡니다.
<p
id="empty"
class="empty"
hidden
>
할 일이 없습니다.
</p>#empty의 접근성 나무빠짐
화면에도 화면 읽기 프로그램에도 나오지 않지만, 요소 나무에는 그대로 있습니다.
⑦ 아랫줄은 footer 안에 개수 문단과 지우기 단추입니다.
<footer class="footer">
<p id="count" class="count">
전체 3개 중 2개 남음
</p>
<button
type="button"
id="clear-done"
class="clear"
>
완료한 일 지우기
</button>
</footer>예제
완성한 index.html
영역 일곱을 다 쓴 index.html입니다. 바깥 요소 안에 들어가 들여쓰기가 깊어진 줄은 32칸에 들게 속성을 한 줄에 하나씩 나눴습니다. 검사기 칸은 이 파일을 W3C 검사기에 넣은 결과입니다.
index.html 전체 보기
<!-- index.html -->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width"
/>
<title>오늘 할 일</title>
<link
rel="stylesheet"
href="style.css"
/>
</head>
<body>
<main class="app">
<h1>오늘 할 일</h1>
<p id="quote" class="quote">
오늘도 한 걸음씩.
</p>
<form id="todo-form">
<label
class="sr-only"
for="todo-input"
>
할 일
</label>
<input
id="todo-input"
type="text"
placeholder="예: 장보기"
autocomplete="off"
maxlength="100"
/>
<button type="submit">
추가
</button>
</form>
<div
id="filters"
class="filters"
>
<button
type="button"
data-filter="all"
class="active"
>
전체
</button>
<button
type="button"
data-filter="active"
>
진행 중
</button>
<button
type="button"
data-filter="done"
>
완료
</button>
</div>
<ul id="todo-list">
<li>
<input
type="checkbox"
aria-label="완료 표시"
/>
<span class="text">
우유 사기
</span>
<button
type="button"
class="delete"
aria-label="삭제"
>
×
</button>
</li>
<li class="done">
<input
type="checkbox"
aria-label="완료 표시"
checked
/>
<span class="text">
HTML·CSS 복습하기
</span>
<button
type="button"
class="delete"
aria-label="삭제"
>
×
</button>
</li>
<li>
<input
type="checkbox"
aria-label="완료 표시"
/>
<span class="text">
산책하기
</span>
<button
type="button"
class="delete"
aria-label="삭제"
>
×
</button>
</li>
</ul>
<p
id="empty"
class="empty"
hidden
>
할 일이 없습니다.
</p>
<footer class="footer">
<p
id="count"
class="count"
>
전체 3개 중 2개 남음
</p>
<button
type="button"
id="clear-done"
class="clear"
>
완료한 일 지우기
</button>
</footer>
</main>
</body>
</html>Document checking completed. No errors or warnings to show.
아직 style.css가 없어 기본 스타일로 그려집니다. 앞 레슨의 확인 목록은 모양 줄이 없어 이 상태로 모두 맞습니다.
짧은 길로 간다면
1~9단원과 이 레슨까지 하고 자바스크립트 과목으로 넘어가는 길이 짧은 길입니다. 짧은 길로 간다면 완성 style.css를 받아 같은 폴더에 둡니다. 그 과목에서 끝낸 줄에 긋는 취소선과 골라 둔 필터 단추의 표시를 이 CSS가 그립니다.
자주 틀리는 곳
틀린 생각: 이름표는 내가 알아보기 좋게 바꿔 써도 된다.
<ul id="todoList">
<li>우유 사기</li>
</ul>
#todo-list {
color: #d70015;
}li의 글자색rgb(0, 0, 0)
#todo-list가 고를 요소가 없어 규칙이 닿지 않았습니다. 오류 메시지도 없습니다. 자바스크립트 과목의 코드도 #todo-list로 목록을 찾으므로, 이 이름이면 목록을 찾지 못해 줄을 그리지 못합니다.
맞는 규칙: 이름표는 1절 표의 글자 그대로 씁니다. 다 쓴 뒤 1절 표와 한 줄씩 대어 봅니다.
틀린 생각: 체크박스는 보이니까 이름 없이 둬도 된다.
<ul>
<li>
<input type="checkbox" />
<span class="text">
산책하기
</span>
</li>
</ul>input의 읽는 이름(없음)
Document checking completed. No errors or warnings to show.
검사기는 Error를 내지 않지만, 화면 읽기 프로그램에는 이름 없는 체크박스입니다. 무엇을 끝냈다고 표시하는 칸인지 들리지 않습니다.
맞는 규칙: 글자 라벨을 둘 자리가 없는 칸에는 aria-label로 이름을 붙입니다 — 할 일 화면은 aria-label="완료 표시"(브라우저 규칙 3).
틀린 생각: class="active"와 data-filter="active"는 같은 것이다.
<button
data-filter="all"
class="active"
>
전체
</button>
<button data-filter="active">
진행 중
</button>
.active {
color: #d70015;
}.active의 글자색rgb(215, 0, 21)[data-filter="active"]의 글자색rgb(0, 0, 0)
'진행 중' 단추를 칠하려고 .active를 썼는데 '전체'가 칠해졌습니다. .active는 class가 active인 요소를 고릅니다.
맞는 규칙: class="active"는 지금 골라 둔 단추, data-filter="active"는 진행 중인 줄을 보일 단추입니다. 속성 값을 고를 때는 [data-filter="active"]처럼 속성 선택자로 씁니다(조건 겹치기와 속성 선택자).
확인 문제
1. '산책하기'를 끝낸 일로 바꾸려고 li에만 class="done"을 붙였습니다. 결과 화면의 체크박스는 어떻게 그려질까요?
<li class="done">
<input
type="checkbox"
aria-label="완료 표시"
/>
<span class="text">
산책하기
</span>
</li>
- ① 체크되어 그려진다
- ② 빈칸으로 그려진다
- ③ 칸이 그려지지 않는다
힌트
li에 붙은 속성과 체크박스(input)에 붙은 속성을 나눠 적어 보세요.
힌트 둘
체크 표시는 체크박스 요소의 속성이 정합니다. 체크박스 요소의 속성만 보세요.
정답
② — 체크박스에 checked가 없어 빈칸입니다.
li input의 :checked꺼짐
class="done"은 이름표일 뿐 체크박스 모양을 바꾸지 않습니다. 체크 표시는 체크박스의checked가 그립니다. 끝낸 일은li의class="done"과 체크박스의checked두 곳에 적습니다.- ①은
done이라는 이름이 체크까지 해 준다고 본 것입니다. 이름표는 고르고 찾는 데 쓰는 이름입니다.
2. 할 일 화면을 다시 조립합니다.
(가) 할 일 한 줄 li의 자식 셋이 섞였습니다. 앞에서부터 차례로 기호를 늘어놓으세요.
- ㉠
span.text— 할 일 글 - ㉡
button.delete—×단추 - ㉢
input— 체크박스
(나) 필터 단추 '완료'에서 비운 속성 하나를 ____ 자리에 쓰세요.
<button
type="button"
____
>
완료
</button>
힌트
(가)는 완성 화면의 한 줄을 왼쪽부터 읽습니다. (나)는 1절 끝 문단에서 필터 단추 셋에 적는 값을 찾습니다.
정답
(가) ㉢ ㉠ ㉡ — 체크박스 · 할 일 글 · × 단추입니다.
(나) data-filter="done" — 끝낸 줄을 보일 단추라 done입니다.
<button
type="button"
data-filter="done"
>
완료
</button>[data-filter="done"]의 고른 글완료
- 흔한 오답은
class="done"입니다.done클래스는 끝낸 줄li에 붙는 이름표라, 단추에 붙이면 자바스크립트 과목에서 이 단추를 끝낸 줄로 읽습니다.
3. 여행 일정 화면을 할 일 화면과 같은 이름표로 만들어, 자바스크립트 과목의 할 일 앱 코드를 그대로 붙이려 합니다. 그 코드는 끝낸 줄을 li의 class="done"으로 가립니다. 아래 줄에서 고칠 곳 둘을 찾아 고친 줄을 쓰세요.
<ul id="todo-list">
<li>
<input
type="checkbox"
class="done"
checked
/>
<span class="text">
기차표 사기
</span>
</li>
</ul>Document checking completed. No errors or warnings to show.
힌트
검사기 Error는 0입니다. 할 일 화면의 끝낸 줄(3절)과 한 줄씩 대어 보세요.
힌트 둘
class="done"이 어느 요소에 붙어야 하는지, 체크박스의 읽는 이름이 무엇인지 보세요.
정답
class="done"을 체크박스에서 li로 옮기고, 체크박스에 aria-label="완료 표시"를 붙입니다.
<ul id="todo-list">
<li class="done">
<input
type="checkbox"
aria-label="완료 표시"
checked
/>
<span class="text">
기차표 사기
</span>
</li>
</ul>li.done .text의 보이는 글기차표 사기li input의 읽는 이름완료 표시
- 끝낸 줄의 이름표는 줄 전체인
li에 붙습니다. 체크박스에 붙이면 앱 코드가li에서done을 찾지 못해 끝낸 줄을 놓칩니다. - 체크박스는 이름이 없어 화면 읽기 프로그램에 무엇을 표시하는 칸인지 들리지 않았습니다.
- 둘 다 검사기가 잡지 못합니다. 이름표와 읽는 이름은 1절 표와 잰 값으로 맞춰 봅니다.
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
W3C 검사기의 칸의 글을 모두 지우고(전체 선택 → 지우기) 내 index.html을 붙여 넣어 Error 0을 봅니다. Elements 패널에서는 화면에 없는 p#empty가 나무에 있는지 봅니다.