역할 · 복합 위젯
role="listbox"
여러 옵션(option) 중 하나 또는 여러 개를 고르는 목록입니다. 콤보박스의 팝업으로도 쓰입니다.
한눈에 보기
- 분류
- 복합 위젯
- 대응 HTML
<select multiple>또는size가 1보다 큰<select>,<datalist>- 이름 정하는 방법
- 작성자
- 이름 필수
- 예
- 필수 상위 요소
- 없음
설명
listbox는 option들을 담는 선택 목록입니다. 필수 하위 요소는 option이며, 옵션을 묶을 때는 이름 붙인 group(그 안에 option)을 씁니다. aria-orientation의 기본값은 세로(vertical)입니다.
- 단일 선택 — 선택된 옵션에
aria-selected="true". 포커스를 옮기면 선택도 따라가게(selection follows focus) 만들 수 있습니다. - 다중 선택 —
aria-multiselectable="true". 포커스와 선택을 분리하고, Space·Shift·Ctrl 조합으로 선택합니다. - 포커스 관리 — 목록 상자에 포커스를 두고
aria-activedescendant로 현재 옵션을 가리키거나, 옵션에 직접 포커스를 옮기는 로빙 tabindex를 씁니다. 콤보박스 팝업으로 쓸 때는 콤보박스 입력란이aria-activedescendant를 가집니다.
옵션은 Children Presentational이라 옵션 안에 버튼·링크를 넣을 수 없습니다. 항목마다 조작 요소가 필요하다면 grid나 일반 목록 + 버튼 구조를 씁니다.
긴 목록
APG는 옵션이 많으면 글자 키로 이동하는 type-ahead를 강하게 권장합니다. 목록이 스크롤된다면 현재 옵션이 보이도록 scrollIntoView 등으로 위치를 맞춥니다. 일부만 렌더링한다면 옵션에 aria-setsize·aria-posinset를 넣습니다.
테스터 관점
- 목록 상자 이름과 현재 옵션, “n개 중 m번째”가 읽히는지 확인합니다.
aria-activedescendant방식이면 옵션을 이동할 때 그 값이 실제 존재하는 옵션id로 바뀌는지 확인합니다.- 현재 옵션(시각적 포커스)이 화면에서도 분명하게 보이는지 확인합니다.
함께 쓰는 속성
지원 속성
aria-activedescendantaria-disabledaria-errormessagearia-expandedaria-invalidaria-multiselectablearia-orientationaria-readonlyaria-required전역 속성(이름·설명 등)은 모든 역할에 쓸 수 있어 생략했습니다.
키보드 동작
| 키 | 동작 |
|---|---|
| Tab | 목록 상자로 들어오면 선택된 옵션(없으면 첫 옵션, 다중 선택은 첫 선택 옵션)에 포커스가 갑니다. |
| ↓ | 다음 옵션으로 이동합니다. 단일 선택은 선택도 함께 옮길 수 있습니다. |
| ↑ | 이전 옵션으로 이동합니다. |
| Home | (선택 사항) 첫 옵션으로 이동합니다. |
| End | (선택 사항) 마지막 옵션으로 이동합니다. |
| 글자 키 | (권장) 입력한 글자로 시작하는 다음 옵션으로 이동합니다. 빠르게 여러 글자를 치면 그 문자열로 시작하는 옵션으로 이동합니다. |
| Space | (다중 선택) 현재 옵션의 선택을 바꿉니다. |
| Shift + ↓ | (다중 선택, 선택 사항) 다음 옵션으로 이동하며 선택을 바꿉니다. Shift+↑는 반대 방향입니다. |
| Shift + Space | (다중 선택, 선택 사항) 마지막으로 선택한 옵션부터 현재 옵션까지 연속으로 선택합니다. |
| Ctrl + Shift + Home | (다중 선택, 선택 사항) 현재 옵션부터 첫 옵션까지 선택합니다. End와 조합하면 마지막 옵션까지 선택합니다. |
| Ctrl + A | (다중 선택, 선택 사항) 모든 옵션을 선택합니다. |
사용 예
네이티브 목록 상자
<label for="lang">사용 언어 (여러 개 선택)</label>
<select id="lang" multiple size="4">
<option>한국어</option><option>영어</option><option>일본어</option>
</select>aria-activedescendant 방식
<p id="ship-label">배송 방법</p>
<ul role="listbox" tabindex="0" aria-labelledby="ship-label" aria-activedescendant="o2">
<li role="option" id="o1" aria-selected="false">일반 배송</li>
<li role="option" id="o2" aria-selected="true">빠른 배송</li>
</ul>옵션 묶음
<div role="listbox" aria-label="지역">
<ul role="group" aria-labelledby="g1"><li role="presentation" id="g1">수도권</li>
<li role="option" aria-selected="false">서울</li>
<li role="option" aria-selected="false">인천</li>
</ul>
</div>현재 옵션 바꾸기
function activate(opt) {
lb.setAttribute('aria-activedescendant', opt.id);
options.forEach(function (o) { o.setAttribute('aria-selected', String(o === opt)); });
opt.scrollIntoView({ block: 'nearest' });
}직접 해 보기
목록 상자에 포커스를 두고 ↑ ↓ Home End나 글자 키(옵션 이름의 영문 첫 글자 E, S, P 등)를 눌러 보세요. 한글은 입력기(IME) 조합 때문에 글자 키 이동에 쓰기 어려워, 데모 옵션에 영문 이름을 함께 넣었습니다. 실제 포커스는 목록 상자에 머물고 aria-activedescendant만 바뀝니다. 선택이 포커스를 따라갑니다.
배송 방법
- Standard 일반 배송
- Express 빠른 배송
- Same-day 당일 배송
- Early 새벽 배송
- Pickup 매장 수령
- Locker 무인 보관함
실시간 코드 — 조작하면 속성 값이 바뀌는 모습을 볼 수 있습니다
화면낭독기에서는
| 상황 | 들리는 안내 (예) |
|---|---|
| 목록 상자로 이동 | 배송 방법, 목록, Standard 일반 배송, 1/6 |
| ↓로 이동 | Express 빠른 배송, 2/6 |
| 다중 선택 목록 | 사용 언어, 다중 선택 목록, 한국어, 선택 안 됨, 1/3 |
사용 지침
이렇게 쓰세요
- 가능하면
<select>를 씁니다. - 목록 상자에 이름을 붙이고, 옵션만(또는 옵션을 담은
group만) 직접 자식으로 둡니다. - 현재 옵션이 화면에서 잘 보이도록 시각적 포커스 표시를 둡니다.
이렇게 쓰지 마세요
- 옵션 사이에 제목·구분선 등 다른 요소를 그냥 끼우지 않습니다.
group과 그룹 이름을 씁니다. - 옵션 안에 상호작용 요소를 넣지 않습니다.
aria-activedescendant를 쓰면서 옵션에도tabindex를 주어 두 방식을 섞지 않습니다.
관련 역할·패턴
이 역할을 쓰는 패턴