CSS / 표(table) 꾸미기 / 반응형 표 만들기

모바일에서 표의 열이 너무 좁아지는 것을 막으려면 표에 필요한 최소 너비를 주고, 표를 감싼 요소에 overflow-x: auto를 지정합니다. 그러면 좁은 화면에서는 표 영역만 가로로 스크롤되고 본문과 페이지 전체의 너비는 유지됩니다. 표를 억지로 줄이기보다 행·열의 비교 관계를 보존할 때 적합한 방법입니다.

표의 최소 너비와 스크롤 영역을 분리하기

table { width: 100%; }만 쓰면 부모 너비를 채우지만, 내용에 따라 셀이 여러 줄로 나뉘거나 긴 문자열 때문에 표가 더 넓어질 수 있습니다. 숫자·날짜·분류명처럼 줄바꿈을 제한해야 하는 내용과 설명처럼 줄바꿈해도 되는 내용을 구분하는 것이 먼저입니다.

표 전체에 min-width를 주면서 바깥 감싸기 요소에 overflow-x를 설정하지 않으면 페이지 자체가 옆으로 넘칠 수 있습니다. 최소 너비는 표에, 넘침 처리는 표를 담은 상자에 적용합니다. 640px 같은 숫자는 모든 표의 정답이 아니라 아래 예제의 시작값이며 실제 열 수와 내용으로 조절해야 합니다.

전체 예제: 제목 행·줄무늬·가로 스크롤

아래 코드를 responsive-table.html로 저장하고 브라우저에서 엽니다. 내용은 구조를 설명하기 위한 학습 계획 예시이며, 외부 파일이나 라이브러리는 필요하지 않습니다. 넓은 창과 좁은 창을 번갈아 비교하세요.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>모바일에서 표만 가로 스크롤하기</title>
  <style>
    body { margin: 20px; font: 16px/1.6 "Noto Sans KR", sans-serif; color: #203348; }
* { box-sizing: border-box; }
    main { max-width: 900px; min-width: 0; }
    h1 { font-size: 24px; }
    .jb-table-scroll { max-width: 100%; overflow-x: auto; border: 1px solid #8ca0b3; }
    .jb-table-scroll:focus-visible { outline: 3px solid #146bcc; outline-offset: 3px; }
    .jb-table-01 { width: 100%; min-width: 640px; border-collapse: collapse; }
    caption { padding: 10px; text-align: left; font-weight: 700; }
    th, td { padding: 12px; border-bottom: 1px solid #a5b5c4; text-align: left; vertical-align: top; }
    thead th { background: #173f65; color: #fff; }
    tbody th { white-space: nowrap; }
    tbody tr:nth-child(even) { background: #edf3fa; }
    .short { white-space: nowrap; }
  </style>
</head>
<body>
<main>
  <h1>작은 화면의 표</h1>
  <p id="table-help">표가 잘리면 표 안을 가로로 스크롤하세요. 키보드에서는 표 영역에 Tab으로 이동한 뒤 방향키를 사용합니다.</p>
  <div class="jb-table-scroll" tabindex="0" role="region" aria-label="학습 계획 표" aria-describedby="table-help">
    <table class="jb-table-01">
      <caption>학습 계획 예시</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">HTML</th><td>입력 양식 구성</td><td class="short">편집기·브라우저</td><td>라벨이 연결된 입력칸과 제출 버튼을 확인합니다.</td></tr>
        <tr><th scope="row">CSS</th><td>표의 색과 간격</td><td class="short">편집기·브라우저</td><td>제목 행, 줄무늬 배경과 모바일 스크롤을 확인합니다.</td></tr>
        <tr><th scope="row">JavaScript</th><td>버튼 동작 연결</td><td class="short">편집기·브라우저</td><td>버튼을 눌렀을 때 안내 문구가 바뀌는지 확인합니다.</td></tr>
      </tbody>
    </table>
  </div>
  <p>이 문단과 페이지 전체는 표와 함께 옆으로 밀리지 않아야 합니다.</p>
</main>
</body>
</html>

넓은 화면에서는 표가 본문 영역을 채우고, 화면이 좁아지면 표를 감싼 영역에 가로 스크롤이 생깁니다. 표 아래의 문단까지 옆으로 밀리면 감싸기 요소가 아니라 페이지 전체가 넘치고 있는 것이므로 설정 위치를 다시 확인합니다. 스크롤 막대는 운영체제 설정에 따라 조작 중에만 나타날 수도 있어 짧은 안내 문구를 함께 두었습니다.

셀 간격·정렬·줄바꿈을 조절하기

caption은 표가 무엇을 보여 주는지 설명하고, thead의 th는 열 제목을 나타냅니다. 첫 열의 분류명도 행 제목으로 보고 scope="row"를 지정했습니다. CSS로 색을 칠하는 것만으로 제목 셀의 의미가 생기지는 않으므로 th와 scope를 알맞게 사용합니다.

셀 안쪽 간격은 padding으로, 셀 경계는 border로 조절합니다. border-collapse: collapse는 인접한 테두리를 합치고, tbody tr:nth-child(even)은 짝수 데이터 행에 배경색을 줍니다. 설명이 여러 줄인 셀을 위쪽에 맞추면 같은 행의 시작을 따라 읽기 쉽습니다. 수치 비교 표라면 숫자를 오른쪽에 맞추는 등 자료의 성격에 맞게 정렬 기준을 선택할 수 있습니다.

white-space: nowrap은 분류명과 준비물 열에만 제한했습니다. 설명 열까지 모두 한 줄로 만들면 표가 지나치게 넓어져 가로 이동이 늘어날 수 있습니다. min-width를 640px에서 480px로 바꿔 좁은 화면의 줄 수와 이동량을 비교한 뒤 원래 값으로 되돌려 보세요. 글자가 너무 잘게 줄바꿈되거나 읽기 어려워지는지 실제 내용으로 판단합니다.

키보드·부모 레이아웃·접근성 확인하기

예제의 스크롤 영역은 tabindex="0"으로 초점을 받을 수 있습니다. Tab으로 영역에 이동하면 파란 초점 테두리가 나타나고, 좌우 방향키로 숨겨진 열을 볼 수 있어야 합니다. 브라우저마다 스크롤 영역의 기본 키보드 접근 방식이 다를 수 있으므로 실제 대상 환경에서 확인하세요. 초점 표시를 없애거나 스크롤 막대를 강제로 숨기지 않는 편이 좋습니다.

표의 바깥 부모가 Flexbox나 Grid 항목이고 계속 페이지가 넓어진다면 해당 항목의 min-width: 0도 확인합니다. 자식이 줄어들지 못하도록 잡는 최소 크기와 표 자체의 최소 너비는 다른 문제입니다. 모든 div에 overflow: hidden을 주어 넘침을 감추면 다른 메뉴나 초점 표시가 잘릴 수 있으므로 표 영역으로 범위를 제한하세요.

행을 카드처럼 세로로 바꾸는 방법도 있지만, 열 제목과 값의 관계를 유지하도록 별도 설계가 필요합니다. 비교해야 할 열이 많은 자료는 표 구조와 가로 스크롤을 유지하는 것이 더 적합할 수 있습니다. 표의 구조를 무조건 display: block으로 바꾸기 전에 독자가 어떤 항목을 나란히 비교해야 하는지 확인합니다.

스타일과 반응형 처리의 기본은 MDN의 표 스타일 안내, 제목 셀의 의미는 W3C의 두 방향 제목 셀 안내에서 확인할 수 있습니다. 스크롤 동작은 overflow 설명을 참고할 수 있습니다.