역할 · 복합 위젯
role="grid"
행과 열로 이루어지고, 방향키로 셀 사이를 이동하며 선택·편집할 수 있는 상호작용 표입니다.
한눈에 보기
- 분류
- 복합 위젯
- 대응 HTML
- 없음 (
<table>에role="grid"를 붙여 만들 수 있음) - 이름 정하는 방법
- 작성자
- 이름 필수
- 예
- 필수 상위 요소
- 없음
설명
grid는 table의 구조(행·열·제목 셀)에 위젯 동작을 더한 역할입니다. 그리드 전체가 탭 순서에서 한 번만 멈추고, 안에서는 방향키로 gridcell 사이를 이동합니다. 필수 하위 요소는 row(직접 또는 rowgroup 안)입니다.
APG는 두 가지 용도를 구분합니다.
- 데이터 그리드 — 스프레드시트, 정렬·선택·편집이 되는 데이터 목록. 제목 셀(
columnheader,rowheader)이 있습니다. - 레이아웃 그리드 — 달력 날짜, 사진 목록, 태그 목록처럼 여러 상호작용 요소를 2차원으로 묶어 탭 정지를 줄이는 용도. 제목 셀이 없을 수 있습니다.
그리드 속성: 일부 행·열만 렌더링하면 aria-rowcount·aria-colcount로 전체 크기를, 여러 셀을 고를 수 있으면 aria-multiselectable, 전체가 편집 불가면 aria-readonly를 씁니다. 포커스 관리는 로빙 tabindex 또는 aria-activedescendant 중 하나를 고릅니다.
읽기만 하는 표를 grid로 만들지 마세요
화면낭독기는 grid에 들어가면 포커스(애플리케이션) 모드로 전환해, 표 읽기 단축키 대신 웹 페이지의 키 처리를 따릅니다. 셀 단위 조작이 없는 표를 grid로 만들면 오히려 읽기 어려워집니다. 정렬 버튼 정도만 있는 표는 일반 <table> + 제목 셀 안의 <button>과 aria-sort로 충분합니다.
테스터 관점
- Tab 한 번으로 그리드에 들어가고 한 번 더 누르면 나가는지, 다시 들어오면 마지막 셀로 돌아오는지 확인합니다.
- 셀 이동 시 열 제목이 함께 읽히는지 확인합니다.
- 셀 안 위젯(버튼, 입력란)이 있다면 Enter/F2로 들어가고 Esc로 셀 탐색으로 돌아오는지 확인합니다.
함께 쓰는 속성
지원 속성
전역 속성(이름·설명 등)은 모든 역할에 쓸 수 있어 생략했습니다.
키보드 동작
| 키 | 동작 |
|---|---|
| → | 오른쪽 셀로 이동합니다. 행 끝이면 움직이지 않습니다(레이아웃 그리드는 다음 행 첫 셀로 넘어갈 수 있음). |
| ← | 왼쪽 셀로 이동합니다. |
| ↓ | 아래 셀로 이동합니다. |
| ↑ | 위 셀로 이동합니다. |
| Page Down | (선택 사항) 정해진 행 수만큼 아래로 이동합니다. |
| Page Up | (선택 사항) 정해진 행 수만큼 위로 이동합니다. |
| Home | 현재 행의 첫 셀로 이동합니다. |
| End | 현재 행의 마지막 셀로 이동합니다. |
| Ctrl + Home | 첫 행의 첫 셀로 이동합니다. |
| Ctrl + End | 마지막 행의 마지막 셀로 이동합니다. |
| Ctrl + Space | (선택 지원 시) 현재 셀이 속한 열을 선택합니다. |
| Shift + Space | (선택 지원 시) 현재 셀이 속한 행을 선택합니다. |
| Ctrl + A | (선택 지원 시) 모든 셀을 선택합니다. |
| Shift + → | (선택 지원 시) 선택 범위를 오른쪽으로 넓힙니다. 다른 방향키도 같습니다. |
| Enter | (셀 안 위젯) 편집 모드로 들어가거나 셀의 위젯을 실행합니다. F2도 지원할 수 있습니다. |
| Esc | (편집 모드) 편집을 취소하고 셀 탐색으로 돌아갑니다. |
사용 예
table 기반 데이터 그리드
<table role="grid" aria-labelledby="g-cap" aria-readonly="true">
<caption id="g-cap">이번 주 근무표</caption>
<tr><th scope="col">이름</th><th scope="col">월</th><th scope="col">화</th></tr>
<tr><th scope="row">김민지</th><td tabindex="0">주간</td><td tabindex="-1">야간</td></tr>
</table>가상 스크롤 그리드
<div role="grid" aria-label="주문 목록" aria-rowcount="5000" aria-colcount="6">
<div role="rowgroup">
<div role="row" aria-rowindex="1">
<div role="columnheader" aria-colindex="1">주문 번호</div> ...
</div>
</div>
<div role="rowgroup">
<div role="row" aria-rowindex="1201"> ... </div>
</div>
</div>셀 이동 (로빙 tabindex)
function focusCell(r, c) {
var cell = rows[r].cells[c];
current.tabIndex = -1;
cell.tabIndex = 0;
cell.focus();
current = cell;
}일반 데이터 표를 grid로 바꾸는 실수
<table role="grid"> <!-- 클릭·편집 없는 단순 표 -->
<tr><th>상품</th><th>가격</th></tr>
<tr><td>사과</td><td>3,000원</td></tr>
</table>직접 해 보기
그리드 안 셀에 포커스를 두고 방향키, Home/End, Ctrl+Home/End로 이동해 보세요. Tab을 누르면 그리드를 벗어나고, 다시 들어오면 마지막으로 있던 셀로 돌아옵니다. Space로 셀을 선택/해제합니다.
| 이름 | 월 | 화 | 수 |
|---|---|---|---|
| 김민지 | 주간 | 야간 | 주간 |
| 이서준 | 야간 | 주간 | 휴무 |
| 박하은 | 주간 | 휴무 | 야간 |
실시간 코드 — 조작하면 속성 값이 바뀌는 모습을 볼 수 있습니다
화면낭독기에서는
| 상황 | 들리는 안내 (예) |
|---|---|
| 그리드로 처음 이동 | 근무표 (선택한 칸: 휴무 신청), 표, 4열 4행, 월, 김민지, 주간, 선택 안 됨 |
| →로 이동 | 화, 야간 |
| Space로 선택 | 선택됨 |
사용 지침
이렇게 쓰세요
- 셀 단위 탐색·선택·편집이 실제로 필요할 때만 씁니다.
- 그리드 전체를 탭 정지 하나로 만들고, 현재 셀 위치를 기억합니다.
- 열 제목·행 제목을 제공하고, 일부만 렌더링하면
aria-rowcount/aria-rowindex를 넣습니다.
이렇게 쓰지 마세요
- 읽기 전용 표에 쓰지 않습니다.
row를 빼고 셀을 그리드에 바로 넣지 않습니다.- 셀 안 입력란이 방향키를 가로채 빠져나올 수 없게 만들지 않습니다. Esc 등 탈출 방법을 둡니다.
관련 역할·패턴
이 역할을 쓰는 패턴