HTML 표 만들기: caption·scope로 비교표를 읽기 쉽게, 모바일에서는 표만 스크롤하기

2026.09.12·수정 2026.09.14·약 24분·작성: 해비·블로그 소개

이 글에서 만드는 것

caption과 th scope로 비교 관계를 표현하고, 모바일에서 표의 의미를 유지하며 키보드로 가로 이동하는 HTML 비교표를 완성합니다.

caption은 표의 제목을, th와 scope는 제목 셀과 데이터의 관계를 나타냅니다. 모바일에서는 표를 감싼 영역에 가로 스크롤을 적용합니다.
caption은 표의 제목을, th와 scope는 제목 셀과 데이터의 관계를 나타냅니다. 모바일에서는 표를 감싼 영역에 가로 스크롤을 적용합니다.

시작·완성 실습 파일 ZIP 내려받기

1. 표가 필요한 데이터인지 먼저 판단합니다

이 예제는 이용 유형마다 시간·요금·제공 항목을 같은 기준으로 비교합니다. 열을 따라 읽는 것이 의미 있으므로 table을 사용합니다. 문장 세 개나 카드 세 개를 배치하는 데 표를 쓰는 것은 다른 문제입니다. 먼저 종이에 행은 “이용 유형”, 열은 “비교 기준”이라고 적어 보세요. 둘의 교차점이 데이터 셀이 됩니다.

2. caption과 th는 서로 다른 역할입니다

caption은 표 전체의 이름입니다. 페이지 제목 h1이 있다고 해서 표 이름까지 자동으로 정해지는 것은 아닙니다. th는 각 데이터 셀이 무엇을 뜻하는지 알려 주는 머리글이고, scope=”col”은 같은 열을, scope=”row”는 같은 행을 가리킵니다. W3C는 단순한 행·열 머리글 표에서 이 관계를 명시하는 방법을 설명합니다. 병합 셀이 많은 복잡한 표는 이 예제의 범위를 넘어섭니다.

공식 근거: W3C WAI 행·열 머리글 표

다음은 차이만 보여 주는 부분 코드입니다. 전체 파일에 그대로 덧붙이지 마세요.

<!-- 의미가 없는 데이터 셀 -->
<td>팀 연습</td>
<!-- 행 전체의 이름을 나타내는 머리글 -->
<th scope="row">팀 연습</th>

3. 좁은 화면에서는 표 바깥 상자만 움직입니다

table에 최소 폭 36rem을 주면 글자를 억지로 한 글자씩 꺾지 않고 비교 관계를 유지할 수 있습니다. 대신 바깥 .table-scroll에 overflow-x: auto를 지정합니다. 표가 넓어지는 것과 페이지 전체가 넓어지는 것은 다릅니다. 본문 문장은 화면 폭 안에서 줄바꿈하고, 표 영역에서만 가로 이동해야 합니다. 각 행이나 셀의 display를 block으로 바꾸지 않습니다.

WCAG 리플로 설명은 의미상 2차원 배치가 필요한 데이터 표에 국소적인 양방향 스크롤을 허용하는 예외를 설명합니다. 예외가 표 내부 글자 잘림이나 페이지 전체 가로 넘침을 정당화하는 것은 아닙니다.

공식 근거: WCAG 2.2 리플로 설명과 데이터 표 예외

4. 스크롤 영역에도 이름과 키보드 진입점을 둡니다

tabindex=”0″은 일반 Tab 순서에 표의 바깥 영역을 넣습니다. role=”region”과 aria-labelledby는 그 영역을 표 제목으로 식별하고 aria-describedby는 가로 이동 안내를 연결합니다. 양수 tabindex로 순서를 새로 만들지 않습니다. 브라우저에서 키보드 초점이 들어온 다음 방향키로 이동되는지 직접 확인하세요. 화면 읽기 프로그램이 켜져 있으면 방향키를 문서 탐색에 사용할 수 있으므로 그때의 읽기·조작 검증은 별도로 진행합니다.

5. starter에서 고치고 결과를 비교합니다

  • ZIP을 풀고 starter/index.html을 브라우저로 엽니다. 두 행의 값을 먼저 읽어 봅니다.
  • caption, thead, tbody를 추가한 뒤 첫 행과 첫 열의 td를 목적에 맞는 th로 바꿉니다.
  • complete와 같은 스크롤 바깥 요소를 만들고 CSS를 적용합니다.
  • 발표 연습 행을 추가합니다. 새 행에서도 이용 유형이 scope=”row”인지 확인합니다.
  • 데스크톱과 320 CSS 픽셀 폭에서 확인합니다. 본문이 잘리지 않고 표 내부에서만 움직이는지 살펴봅니다.

6. 자주 실패하는 지점

  • 모든 셀을 th로 만들면 데이터와 머리글 구분이 흐려집니다. 이름 셀만 th로 지정하세요.
  • caption을 table 밖에 두면 표 제목 관계가 만들어지지 않습니다. table의 첫 자식으로 넣습니다.
  • body에 overflow-x: hidden을 주면 넘침을 고치지 않고 가릴 수 있습니다. 표 바깥 상자의 폭과 overflow부터 봅니다.
  • 스크롤 상자에 outline: none을 넣으면 현재 위치를 놓치기 쉽습니다. 예제의 :focus-visible 표시를 유지합니다.

7. 완료 기준과 추가 과제

현재 파일에 표 제목 한 개, 네 개의 열 머리글, 세 개의 행 머리글이 있는지 확인하세요. Tab으로 표에 들어가고 다시 Tab으로 다음 링크에 나올 수 있어야 합니다. 가능한 환경에서는 화면 읽기 프로그램의 표 탐색 명령으로 요금 셀의 이용 유형과 열 이름을 함께 확인합니다. 이 읽기 결과는 일반 브라우저 키보드 확인만으로 대신할 수 없습니다.

추가 과제는 “예약 가능 요일” 열 추가입니다. 데이터와 열 머리글을 같은 순서에 넣고 좁은 화면에서 끝 열까지 접근되는지 다시 확인하세요. 이 샘플에 없는 복잡한 rowspan·colspan부터 추가하지 말고 단순한 비교 관계를 먼저 완성해 보세요.

완성 코드: complete/index.html 전체

아래 코드는 부분 예제가 아니라 HTML 파일 전체입니다. 같은 폴더에 이어지는 style.css를 저장하세요.

실습 파일

파일 경로를 확인하고 같은 프로젝트 안에 저장하세요. 이미지 등 소스 목록에 없는 파일과 실행 안내는 실습 ZIP에 포함되어 있습니다.

표 제목과 헤더 관계를 보완하고 좁은 화면에서는 표 영역만 스크롤합니다. 수정 전은 시작 상태, 수정 후는 비교할 완성 상태입니다.

수정 전

index.html

<!doctype html>
<html lang="ko">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>
      HTML 표 만들기: caption·scope로 비교표를 읽기 쉽게, 모바일에서는 표만 스크롤하기
    </title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <main>
      <h1>연습 공간 요금 비교</h1>
      <p>가상 정보입니다. 아래 표에 제목과 머리글의 방향을 추가하세요.</p>
      <!-- TODO 1: caption을 추가하세요. -->
      <!-- TODO 2: 첫 행은 열 머리글, 첫 열은 행 머리글로 바꾸세요. -->
      <!-- TODO 3: 표 바깥에 이름과 tabindex가 있는 가로 스크롤 영역을 만드세요. -->
      <table>
        <tr>
          <td>이용 유형</td>
          <td>기본 시간</td>
          <td>가상 요금</td>
          <td>포함 항목</td>
        </tr>
        <tr>
          <td>개인 연습</td>
          <td>1시간</td>
          <td>10,000원</td>
          <td>책상 1개, 의자 1개</td>
        </tr>
        <tr>
          <td>팀 연습</td>
          <td>2시간</td>
          <td>30,000원</td>
          <td>책상 1개, 의자 4개</td>
        </tr>
      </table>
    </main>
  </body>
</html>

style.css

* {
  box-sizing: border-box;
}
html {
  color: #222;
  background: #f1f1f1;
  font-family: system-ui, sans-serif;
}
body {
  margin: 0;
  line-height: 1.7;
}
input {
  accent-color: #555;
}
main,
.site-header,
.site-footer {
  width: min(70rem, 100%);
  margin-inline: auto;
  padding: 1.5rem;
}
h1,
h2,
h3,
p {
  margin-top: 0;
}
a {
  color: #222;
  text-underline-offset: 0.2em;
}
:focus-visible {
  outline: 3px solid #111;
  outline-offset: 3px;
}
section {
  margin-block: 2rem;
}
.notice {
  padding: 1rem;
  background: #e5e5e5;
  border: 1px solid #666;
}
table {
  width: 100%;
  border-collapse: collapse;
}
td {
  border: 1px solid #777;
  padding: 0.75rem;
}

수정 방법

index.html

index.html에서 아래 차이가 있는 위치를 수정하세요. -는 삭제할 줄, +는 추가할 줄이며 표시는 실제 코드에 넣지 않습니다.

표 제목과 헤더 관계를 보완하고 좁은 화면에서는 표 영역만 스크롤합니다.

--- 수정 전/index.html
+++ 수정 후/index.html
@@ -11,30 +11,60 @@
   <body>
     <main>
       <h1>연습 공간 요금 비교</h1>
-      <p>가상 정보입니다. 아래 표에 제목과 머리글의 방향을 추가하세요.</p>
-      <!-- TODO 1: caption을 추가하세요. -->
-      <!-- TODO 2: 첫 행은 열 머리글, 첫 열은 행 머리글로 바꾸세요. -->
-      <!-- TODO 3: 표 바깥에 이름과 tabindex가 있는 가로 스크롤 영역을 만드세요. -->
-      <table>
-        <tr>
-          <td>이용 유형</td>
-          <td>기본 시간</td>
-          <td>가상 요금</td>
-          <td>포함 항목</td>
-        </tr>
-        <tr>
-          <td>개인 연습</td>
-          <td>1시간</td>
-          <td>10,000원</td>
-          <td>책상 1개, 의자 1개</td>
-        </tr>
-        <tr>
-          <td>팀 연습</td>
-          <td>2시간</td>
-          <td>30,000원</td>
-          <td>책상 1개, 의자 4개</td>
-        </tr>
-      </table>
+      <p>모든 금액과 조건은 HTML 표 연습을 위한 가상 정보입니다.</p>
+      <p id="scroll-help">
+        표가 화면보다 넓으면 표 영역을 선택한 뒤 좌우 방향키로 이동하세요. 터치로도
+        가로로 움직일 수 있습니다.
+      </p>
+      <div
+        class="table-scroll"
+        role="region"
+        aria-labelledby="price-caption"
+        aria-describedby="scroll-help"
+        tabindex="0"
+      >
+        <table>
+          <caption id="price-caption">
+            연습 공간 1회 이용 요금과 제공 항목
+          </caption>
+          <thead>
+            <tr>
+              <th scope="col">이용 유형</th>
+              <th scope="col">기본 시간</th>
+              <th scope="col">가상 요금</th>
+              <th scope="col">포함 항목</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr>
+              <th scope="row">개인 연습</th>
+              <td>1시간</td>
+              <td>10,000원</td>
+              <td>책상 1개, 의자 1개</td>
+            </tr>
+            <tr>
+              <th scope="row">팀 연습</th>
+              <td>2시간</td>
+              <td>30,000원</td>
+              <td>책상 1개, 의자 4개</td>
+            </tr>
+            <tr>
+              <th scope="row">발표 연습</th>
+              <td>2시간</td>
+              <td>40,000원</td>
+              <td>책상 1개, 의자 4개, 발표 화면</td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+      <section id="conditions">
+        <h2>비교표 읽는 방법</h2>
+        <p>
+          행 제목에서 이용 유형을 고르고 열 제목에서 비교할 항목을 찾습니다. 요금만 떼어
+          읽으면 이용 시간이 다르다는 조건을 놓칠 수 있습니다.
+        </p>
+        <a href="#scroll-help">표 이동 안내로 돌아가기</a>
+      </section>
     </main>
   </body>
 </html>

수정 후 탭의 전체 파일과 비교한 뒤 본문의 확인 절차를 실행하세요.

style.css

style.css에서 아래 차이가 있는 위치를 수정하세요. -는 삭제할 줄, +는 추가할 줄이며 표시는 실제 코드에 넣지 않습니다.

표 제목과 헤더 관계를 보완하고 좁은 화면에서는 표 영역만 스크롤합니다.

--- 수정 전/style.css
+++ 수정 후/style.css
@@ -42,11 +42,31 @@
   background: #e5e5e5;
   border: 1px solid #666;
 }
+.table-scroll {
+  max-width: 100%;
+  overflow-x: auto;
+  border: 1px solid #666;
+  padding: 0.5rem;
+}
 table {
   width: 100%;
+  min-width: 36rem;
   border-collapse: collapse;
+  background: #fff;
 }
+caption {
+  text-align: left;
+  font-weight: 700;
+  padding: 0.75rem;
+}
+th,
 td {
   border: 1px solid #777;
   padding: 0.75rem;
+  text-align: left;
+  vertical-align: top;
 }
+thead,
+tbody th {
+  background: #e5e5e5;
+}

수정 후 탭의 전체 파일과 비교한 뒤 본문의 확인 절차를 실행하세요.

수정 후

index.html

<!doctype html>
<html lang="ko">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>
      HTML 표 만들기: caption·scope로 비교표를 읽기 쉽게, 모바일에서는 표만 스크롤하기
    </title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <main>
      <h1>연습 공간 요금 비교</h1>
      <p>모든 금액과 조건은 HTML 표 연습을 위한 가상 정보입니다.</p>
      <p id="scroll-help">
        표가 화면보다 넓으면 표 영역을 선택한 뒤 좌우 방향키로 이동하세요. 터치로도
        가로로 움직일 수 있습니다.
      </p>
      <div
        class="table-scroll"
        role="region"
        aria-labelledby="price-caption"
        aria-describedby="scroll-help"
        tabindex="0"
      >
        <table>
          <caption id="price-caption">
            연습 공간 1회 이용 요금과 제공 항목
          </caption>
          <thead>
            <tr>
              <th scope="col">이용 유형</th>
              <th scope="col">기본 시간</th>
              <th scope="col">가상 요금</th>
              <th scope="col">포함 항목</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">개인 연습</th>
              <td>1시간</td>
              <td>10,000원</td>
              <td>책상 1개, 의자 1개</td>
            </tr>
            <tr>
              <th scope="row">팀 연습</th>
              <td>2시간</td>
              <td>30,000원</td>
              <td>책상 1개, 의자 4개</td>
            </tr>
            <tr>
              <th scope="row">발표 연습</th>
              <td>2시간</td>
              <td>40,000원</td>
              <td>책상 1개, 의자 4개, 발표 화면</td>
            </tr>
          </tbody>
        </table>
      </div>
      <section id="conditions">
        <h2>비교표 읽는 방법</h2>
        <p>
          행 제목에서 이용 유형을 고르고 열 제목에서 비교할 항목을 찾습니다. 요금만 떼어
          읽으면 이용 시간이 다르다는 조건을 놓칠 수 있습니다.
        </p>
        <a href="#scroll-help">표 이동 안내로 돌아가기</a>
      </section>
    </main>
  </body>
</html>

style.css

* {
  box-sizing: border-box;
}
html {
  color: #222;
  background: #f1f1f1;
  font-family: system-ui, sans-serif;
}
body {
  margin: 0;
  line-height: 1.7;
}
input {
  accent-color: #555;
}
main,
.site-header,
.site-footer {
  width: min(70rem, 100%);
  margin-inline: auto;
  padding: 1.5rem;
}
h1,
h2,
h3,
p {
  margin-top: 0;
}
a {
  color: #222;
  text-underline-offset: 0.2em;
}
:focus-visible {
  outline: 3px solid #111;
  outline-offset: 3px;
}
section {
  margin-block: 2rem;
}
.notice {
  padding: 1rem;
  background: #e5e5e5;
  border: 1px solid #666;
}
.table-scroll {
  max-width: 100%;
  overflow-x: auto;
  border: 1px solid #666;
  padding: 0.5rem;
}
table {
  width: 100%;
  min-width: 36rem;
  border-collapse: collapse;
  background: #fff;
}
caption {
  text-align: left;
  font-weight: 700;
  padding: 0.75rem;
}
th,
td {
  border: 1px solid #777;
  padding: 0.75rem;
  text-align: left;
  vertical-align: top;
}
thead,
tbody th {
  background: #e5e5e5;
}

index.html 전체 코드 보기

완성 코드: complete/style.css 전체

style.css 전체 코드 보기

이 글이 도움이 되었나요?

조회 중

웹 퍼블리싱 학습 순서

필수 13개 · 전체 15개

읽음 기록 관리

전체 과정 목차 (15개)
  1. 필수 학습 · HTML 입문: 시맨틱 문서와 접근 가능한 폼 만들기
  2. 필수 학습 · CSS 입문: 박스 모델·선택자·캐스케이드 직접 확인하기
  3. 필수 학습 · CSS Flex와 미디어 쿼리 입문: 반응형 카드 페이지 만들기
  4. 필수 학습 · CSS position 완전 이해: relative·absolute·fixed·sticky 실습
  5. 필수 학습 · HTML details와 summary로 접근 가능한 FAQ 만들기
  6. 필수 학습 · CSS Grid 실습: Flex 학습 카드로 열 맞추기와 auto-fit 비교
  7. 필수 학습 · CSS overflow 해결: 긴 텍스트·min-width: 0·말줄임 실습
  8. 필수 학습 · HTML 표 만들기: caption·scope로 비교표를 읽기 쉽게, 모바일에서는 표만 스크롤하기 현재 글
  9. 필수 선수 · HTML CSS 이미지 문제 해결 실습: 경로·비율·잘림·흐림·CLS
  10. 필수 학습 · Container Query 실습: 같은 카드를 본문과 사이드바에 배치하기
  11. 선택 참고 · CSS Baseline 보는 법: 지원 범위와 폴백을 직접 확인하기
  12. 필수 학습 · CSS z-index가 안 먹힐 때: stacking context와 부모 층 디버깅
  13. 필수 선수 · 웹 접근성 기초 점검: 키보드 순서·초점 표시·확대 화면을 직접 확인하는 체크리스트
  14. 필수 학습 · HTML CSS 종합 실습: 소개·카드·이미지·요금표·문의 폼·FAQ가 있는 반응형 서비스 페이지
  15. 선택 참고 · 프론트엔드 SEO 기초: HTML 구조와 이미지 성능 진단하기

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기