본문으로 건너뛰기

이름표를 맞춘 HTML

HTML·CSS 목차할 일 목록 화면 만들기레슨 91 / 93

목차

이름표를 맞춘 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>
결과 화면탭: 오늘 할 일
검사기Error · Warning 0

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의 읽는 이름(없음)
검사기Error · Warning 0

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>
결과 화면
검사기Error · Warning 0

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가 나무에 있는지 봅니다.

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

HTML·CSS 목차로