Skip to content
This page has been auto-translated and may contain errors.View in English

docs.scrimba.com

어떤 정보들은 격자 형태입니다. 기차 시간표, 요금제 표, 리그 테이블, 영양 정보: 이들 각각은 행과 열을 가지고 있으며, 의미는 이들이 어떻게 정렬되는지에서 비롯됩니다. HTML은 정확히 이러한 종류의 콘텐츠를 위한 전용 요소 집합을 가지고 있으며, 이를 사용하면 격자를 화면과 페이지를 큰 소리로 읽는 소프트웨어 모두에서 읽을 수 있게 유지할 수 있습니다.

표의 기본

****는 스프레드시트와 같은 모양의 행과 열의 격자입니다. 4개의 요소로 만듭니다. <table>은 전체 격자를 감싸줍니다. 각 <tr>은 한 행입니다(tr은 table row의 약자입니다). 행 내에서 각 <td>는 데이터의 한 셀입니다(td는 table data입니다). 셀이 열이나 행을 레이블하면 대신 <th>를 사용합니다(th는 table header입니다). 브라우저는 이를 굵게 표시하고 중앙 정렬하여 데이터와 구분되게 보여줍니다.

표를 행 단위로 만들어 나가지, 열 단위로는 절대 아닙니다. <table>은 컨테이너이고, 각 <tr>은 행이며, 셀들은 페이지에 나타나는 순서 그대로 행 내에 앉습니다. 데이터 셀은 <td>이고; **헤더 셀**은 <th>입니다. 열 요소는 없습니다. 열은 모든 행이 같은 순서로 셀을 유지한다는 사실의 부산물이므로, 한 행이 틀어지면 격자가 정렬되지 않습니다.

<th><td>의 차이는 단순한 스타일 문제가 아닙니다. <th>는 셀을 자신이 속한 행이나 열의 헤더로 표시합니다. 브라우저의 기본 스타일인 굵게와 중앙 정렬은 이것의 눈에 띄는 절반일 뿐입니다. 다른 절반은 다른 소프트웨어가 읽을 수 있는 의미입니다.

표의 소스는 **행 우선**입니다: 한 번에 한 행씩 작성하며, 각 셀의 열은 순전히 행 내의 위치로 결정됩니다. 브라우저는 이 행 단위 소스를 읽고 2차원 격자를 만들어, 셀을 열로 매칭하면서 가로로 셉니다. 마크업에서 열을 명명하는 것이 없으므로, 격자는 행이 일관성 있을 정도로만 정렬됩니다.

<th><td>는 스타일이 아닌 의미 구분입니다. <th>(헤더 셀)는 브라우저와 페이지를 읽는 보조 기술(화면 낭독기처럼 볼 수 없는 사람을 위해 페이지를 큰 소리로 읽는 소프트웨어)에 이 셀이 주변 데이터에 대한 레이블임을 알려줍니다. 기본 굵게 및 중앙 정렬 모양은 부수적입니다: CSS로 제거해도 헤더는 여전히 "헤더"를 의미합니다. 의미가 모양이 아닌 요소에 있기 때문입니다. 이것이 다른 방식으로 격자를 그리는 대신 실제 표를 사용하는 전체 이유입니다.

html
<table>
  <tr>
    <th>요일</th>
    <th>운영 시간</th>
  </tr>
  <tr>
    <td>월요일</td>
    <td>8:00 ~ 18:00</td>
  </tr>
  <tr>
    <td>토요일</td>
    <td>9:00 ~ 14:00</td>
  </tr>
</table>

위에는 2개의 헤더 셀, 그 다음에는 2개의 데이터 행입니다. 브라우저가 격자를 그리고, 각 열을 콘텐츠에 맞게 크기 조정하며, 2개의 <th> 셀을 굵게 표시합니다.

Juno표의 기본 4개의 요소가 격자를 만듭니다: 전체를 감싸는 <table>, 각 행을 위한 <tr>, 셀을 위한 <td>, 헤더 셀을 위한 <th>입니다. 헤더 셀은 굵게 표시되고 중앙 정렬되어 데이터와 구분됩니다. 한 번에 한 행씩 만들면 열이 자동으로 정렬됩니다.
Juno표의 기본<tr>로 표를 행 단위로 배치하면 모든 행이 같은 순서로 셀을 유지한다는 사실에서 열이 나옵니다. 헤더는 <th>, 데이터는 <td>이며, 이 선택은 굵은 모양뿐만 아니라 의미입니다. 한 행에서 셀을 잘못 세면 전체 격자가 틀어집니다.
Juno표의 기본 마크업은 행 우선이므로 열은 각 행이 셀을 단계적으로 유지하기 때문에만 존재합니다. 신중하게 세십시오. <th>는 화면 낭독기에 셀이 레이블임을 알려줌으로써 자신의 자리를 얻으므로, CSS 굵게 처리가 할 수 없는 것입니다. 이 의미 구분이 실제 표를 사용하는 이유입니다.

표 구조화

행의 순서는 사람들이 읽는 순서이므로, <th> 셀로 만든 **헤더 행**을 맨 위에 놓으십시오. 그러면 모든 행을 같은 길이로 유지하십시오: 헤더 행에 3개의 셀이 있으면, 그 아래의 모든 <tr>도 3개의 <td> 셀이 필요합니다. 셀이 빠진 행은 격자에 간격을 남기고 열이 정렬되지 않습니다. 여기서 배울 새로운 것은 없고, 이미 알고 있는 행들에 주의만 기울이면 됩니다.

표가 커지면 행을 **행 그룹**으로 그룹화하여 구조를 명시적으로 만드십시오. 헤더 행을 <thead>로, 데이터 행을 <tbody>로, 합계 줄 같은 요약 행을 <tfoot>으로 감싸십시오. 이 그룹들은 자체적으로 레이아웃을 많이 변경하지는 않지만, 스타일 지정, 인쇄 및 보조 소프트웨어를 위해 표의 부분에 레이블을 붙입니다.

<caption>으로 표에 제목을 붙이고, <table>의 첫 번째 자식으로 배치하십시오. 격자 위에 렌더링되며, 표 옆에 놓는 헤더와 달리 마크업의 표에 연결되어 있습니다.

셀이 한 개 이상의 열이나 행을 커버해야 할 때는 colspan 또는 rowspan을 사용하십시오. colspan="2"는 셀을 2개 열만큼 넓게 만들고; rowspan="2"는 2개 행만큼 높게 만듭니다. 커버하는 위치는 그 공간이 이미 점유되어 있으므로 그 행에서 제외됩니다:

html
<thead>
  <tr>
    <th rowspan="2">지역</th>
    <th colspan="2">2024</th>
  </tr>
  <tr>
    <th>Q1</th>
    <th>Q2</th>
  </tr>
</thead>

"지역"은 2개의 헤더 행을 채우고, "2024"는 2개의 열을 채우며, Q1과 Q2는 두 번째 행에서 그 아래에 앉습니다.

행 그룹은 장식이 아닙니다. <thead><tfoot>은 긴 표가 인쇄될 때 모든 페이지에서 반복되도록 정의되어 있으므로, 헤더가 페이지 나눔에서 표시 상태를 유지하며, <tbody>가 스크롤될 때 고정 헤더나 바닥글을 유지할 수 있게 합니다. 표는 여러 <tbody> 그룹을 가질 수 있으므로, 단일 격자를 깨지 않고도 긴 데이터셋을 레이블된 섹션으로 깔끔하게 분할할 수 있습니다.

colspanrowspan셀 스팬 (한 셀이 한 개 이상의 열이나 행을 커버)을 제어하며, 이것이 표가 가장 자주 조용히 깨지는 지점입니다. 모든 행은 여전히 격자의 전체 너비를 차지해야 합니다. colspan="2"인 셀은 2개의 열을 채우므로, 그것이 겹치는 행은 자신의 셀을 제공하는 대신 그 위치를 비워두어야 합니다. 세기를 잘못 세면 브라우저는 여전히 무언가를 렌더링하지만, 의도한 격자는 아닙니다. <caption>은 표의 접근 가능한 이름입니다: 보조 소프트웨어(페이지를 큰 소리로 읽는 화면 낭독기 같은 도구)는 독자가 표에 도달할 때 이를 공지하므로, 표 근처의 헤더가 할 수 없는 일을 합니다.

html
<table>
  <caption>지역별 분기 매출</caption>
  <thead>
    <tr>
      <th>지역</th>
      <th>Q1</th>
      <th>Q2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>북부</th>
      <td>£12,000</td>
      <td>£15,400</td>
    </tr>
    <tr>
      <th>남부</th>
      <td>£9,800</td>
      <td>£11,200</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th>합계</th>
      <td>£21,800</td>
      <td>£26,600</td>
    </tr>
  </tfoot>
</table>
Juno표 구조화 행은 위에서 아래로 읽으므로 <th> 셀의 헤더 행으로 시작하십시오. 그러면 모든 행을 같은 길이로 유지하십시오: 위에 3개의 헤더가 있으면 아래의 각 행에 3개의 <td> 셀이 필요합니다. 빠진 셀은 격자의 간격이며, 이것이 초기에 사람들을 혼동시키는 것입니다.
Juno표 구조화 표가 커지면 부분을 그룹화하십시오: 헤더 행을 위한 <thead>, 데이터를 위한 <tbody>, 합계 줄을 위한 <tfoot>, 그리고 제목을 위한 첫 번째 자식으로서의 <caption>입니다. colspanrowspan은 셀을 열이나 행 위로 늘이지만, 커버된 위치는 그 행에서 제외된다는 것을 기억하십시오. 개수를 맞게 세면 격자가 유지됩니다.
Juno표 구조화 그룹들은 실제 무게를 가집니다: <thead><tfoot>은 표가 인쇄될 때 반복되고 스크롤링 본문을 고정할 수 있으며, <caption>은 화면 낭독기가 읽는 이름입니다. 스팬은 조용한 함정입니다. 모든 행은 여전히 전체 격자 너비를 채워야 하므로 커버된 위치는 셀을 얻지 못합니다. 브라우저는 잘못된 개수를 기꺼이 렌더링하는데, 이것이 정확히 발견하기 어려운 이유입니다.

접근 가능한 표

접근 가능한 표는 화면 낭독기(페이지를 큰 소리로 읽는 소프트웨어)로 페이지를 보는 대신 듣는 사람을 포함하여 모두에게 이해되는 표입니다. 할 수 있는 가장 유용한 것은 이미 도구 상자에 있습니다: 모든 헤더 셀에 <td>가 아닌 <th>를 사용하십시오. 화면 낭독기는 그 청취자에게 어느 셀이 레이블이고 어느 것이 데이터인지 알려줄 수 있으므로, "£15" 같은 값이 속한 열과 함께 발표됩니다. 모든 셀이 평문 <td>인 표는 숫자의 납작한 벽으로 읽히며 그것들을 고정할 것이 없습니다.

<th>는 셀을 헤더로 표시하지만, 열 헤더와 행 헤더 둘 다를 가진 표에서는 어느 것인지 말하지 않습니다. scope 속성이 이를 명시적으로 만듭니다. scope="col"은 헤더가 전체 열을 레이블한다고 말합니다; scope="row"는 전체 행을 레이블한다고 말합니다. 모든 <th>에 이를 추가하면 화면 낭독기가 어떤 데이터 셀이든 올바른 열 헤더와 행 헤더를 한 번에 쌍으로 만들 수 있습니다.

html
<th scope="col">월</th>
<th scope="row">강수량</th>

단순한 격자의 경우 브라우저가 종종 이 연관성을 추측할 수 있지만, scope로 명시하면 추측이 제거되고 추가하기가 저렴합니다.

scope는 행과 열 헤더 한 수준을 가진 표를 커버합니다. 복잡한 표, 즉 여러 열에 걸쳐 있는 헤더나 열 헤더의 2단계를 가진 표는 데이터 셀이 더 이상 그 위에 정확히 하나의 열 헤더와 하나의 행 헤더를 가지지 않으므로 scope를 가진 경우에도 모호합니다. 그들의 경우, **id와 headers**로 명시적으로 셀을 연관 짓습니다. 각 헤더 셀에 id (그 요소의 고유한 이름)를 부여한 다음, 각 데이터 셀의 headers 속성에 관련 id를 나열합니다:

html
<th id="q1">Q1</th>
<th id="north">북부</th>
<td headers="north q1">£12,000</td>

데이터 셀이 이제 정확히 어떤 헤더가 그것을 설명하는지를 읽혀야 할 순서대로 명명하므로, 어떤 알고리즘도 관계를 추론할 필요가 없습니다. 상세하므로 정말 필요한 표들을 위해 보관하십시오. 먼저 scope를 시도하고 헤더 구조가 너무 불규칙해서 scope로 표현할 수 없을 때만 idheaders로 확대하십시오.

접근성은 표만으로 더 넓습니다; 접근성 장이 나머지 그림을 다룹니다.

Juno접근 가능한 표 가장 큰 이득이 추가 비용이 없습니다: 헤더에는 <th>를, 데이터에는 <td>를 사용하십시오. 화면 낭독기는 이 분할에 의존하여 각 값을 속한 헤더와 함께 읽으므로, £15는 자신의 열과 함께 도착합니다. 이를 건너뛰면 전체 표가 느슨한 숫자의 벽으로 도착합니다.
Juno접근 가능한 표 헤더 셀에 scope를 놓으십시오: 열 헤더에는 scope="col", 행 헤더에는 scope="row". 이것은 화면 낭독기가 각 데이터 셀을 양쪽 축의 올바른 헤더에 연결할 수 있게 합니다. 브라우저는 단순한 격자에 대해 추측할 수 있지만, 명시하는 것은 저렴하고 추측을 제거합니다.
Juno접근 가능한 표scope는 일반적인 각 방향에 하나의 헤더씩인 격자를 처리합니다. 헤더가 스팬되거나 스택되고 셀이 한 축에 하나 이상을 가질 때, 헤더의 id와 데이터 셀의 headers로 전환하여 수동으로 연결하십시오. 이는 장황하므로 실제로 필요한 표들을 위해 보관하고 나머지는 scope에 맡기십시오.

표는 레이아웃이 아닌 데이터용입니다

CSS가 레이아웃을 처리할 수 있기 전의 시대가 있었는데, 그때 사람들은 표 밖에서 전체 페이지 레이아웃을 만들었습니다: 왼쪽에 메뉴를 놓고 오른쪽에 콘텐츠를 놓기 위한 <table>이었습니다. 시각적으로 작동하므로 여전히 오래된 페이지와 일부 이메일 템플릿에서 볼 수 있습니다. 복사하지 마십시오. 표는 **표 형식 데이터**용입니다. 행과 열의 격자에 속하는 정보입니다. 페이지의 조각을 배열하는 것은 CSS의 일입니다. 데이터를 보관하는 대신 물건을 배치하기 위해 표를 사용하면 화면 낭독기를 사용하는 누군가에게 페이지를 읽기가 더 어려워지고 나중에 조정하기가 더 어려워집니다.

규칙은 간단합니다: <table>은 "이 콘텐츠는 관련 데이터의 격자"를 의미합니다. 정보가 정말로 행과 열을 가지고 있을 때 사용하십시오: 일정, 비교, 결과 집합. 페이지를 레이아웃하는 데 사용하지 말고, 데이터가 아닌 물건을 줄 세우는 데 사용하지 마십시오. CSS 그리드와 플렉스박스는 레이아웃을 제대로 수행하고, 화면 크기에 맞추며, HTML이 배열을 설명하는 대신 콘텐츠를 설명하도록 유지합니다.

표를 잡아서 열을 얻으려는 것은 고전적인 오용입니다. 콘텐츠가 내비게이션 바나 페이지 전체에 걸쳐 있는 폼이면 표 형식 데이터가 아니고, 올바르게 보이게 만들 수 있더라도 표는 잘못된 도구입니다.

레이아웃에 표를 사용하면 보조 소프트웨어(페이지를 말하는 화면 낭독기 같은 도구)에 데이터가 아닌 데이터 구조를 건넵니다. 화면 낭독기는 표를 그 치수로 발표하고 사용자가 셀 단위로 움직이도록 하며, 레이아웃 스캐폴딩을 마치 모든 지역이 격자의 관련 값인 것처럼 취급합니다. 결과는 정말은 헤더, 사이드바, 기사인 것에 대해 "표, 4개 열, 10행"과 같은 발표입니다.

또한 읽기 순서 문제가 있습니다. 보조 소프트웨어와 검색 엔진은 페이지를 소스 순서, 요소가 HTML에 나타나는 순서로 읽으며, 화면에 앉아 있는 순서가 아닙니다. 레이아웃 표는 소스 순서가 시각 격자와 일치하도록 강제하므로, 청취자를 위해 먼저 와야 할 콘텐츠인 주요 기사가 시각 열이 필요하기 때문에 네비게이션의 열 뒤에 올 수 있습니다. CSS 레이아웃은 이 결합을 끊습니다: 소스에서 중요한 콘텐츠를 먼저 유지하면서도 여전히 화면 어디든 배치할 수 있습니다. 표를 데이터용으로 유지하면 읽기 순서가 제어 상태로 유지됩니다.

한 가지 애매한 영역은 HTML 이메일로, 더 오래된 메일 클라이언트는 여전히 신뢰할 수 있는 CSS 레이아웃이 부족하고 표 기반 구조가 여전히 일반적입니다. 이것은 그 매체의 제약이지, 웹으로 복구할 패턴이 아닙니다.

html
<!-- 잘못됨: 사이드바를 기사 옆에 배치하는 데 사용된 표 -->
<table>
  <tr>
    <td><nav>...</nav></td>
    <td><article>...</article></td>
  </tr>
</table>

<!-- 올바름: 실제 요소, CSS가 열을 처리함 -->
<nav>...</nav>
<article>...</article>

이것은 HTML이란에서 설정된 구조와 표현의 분리와 같습니다: HTML의 구조, CSS의 레이아웃. 의미로 요소를 선택하는 것에 대해서는 의미론적 HTML를 보십시오.

Juno표는 레이아웃이 아닌 데이터용입니다 표는 격자, 행과 열의 관련 값에 속하는 데이터용입니다. 오래된 사이트가 그런 방식으로 사용했더라도 페이지를 배열하기 위한 것이 아닙니다. 페이지의 부분을 배치하는 것은 CSS의 일이며, 이를 표에 접으면 페이지를 큰 소리로 읽고 변경하기가 어려워집니다.
Juno표는 레이아웃이 아닌 데이터용입니다 콘텐츠가 정말 데이터 격자일 때만 <table>을 사용하십시오: 일정, 비교, 결과 목록. 페이지를 레이아웃하거나 비데이터를 줄 세우려면 CSS 그리드나 플렉스박스에 도달하십시오. 이들은 화면에 맞추고 HTML을 콘텐츠로 유지합니다. 레이아웃으로 누른 표는 고전적인 잘못된 도구입니다.
Juno표는 레이아웃이 아닌 데이터용입니다 레이아웃 표는 화면 낭독기를 오도합니다: 데이터 격자를 듣고 의미 없는 행과 열을 읽습니다. 또한 소스 순서를 시각 격자에 고정하는데, 소스 순서가 보조 기술과 검색 엔진이 실제로 읽는 것입니다. 표를 데이터용으로 유지하고, CSS가 물건을 배치하도록 하면, 읽기 순서가 제어 상태로 유지됩니다. HTML 이메일은 유일한 예외이며, 그 클라이언트가 과거에 갇혀 있기 때문일 뿐입니다.