ARIA 접근성 가이드

역할 · 복합 위젯

role="listbox"

여러 옵션(option) 중 하나 또는 여러 개를 고르는 목록입니다. 콤보박스의 팝업으로도 쓰입니다.

중급HTML 요소 우선

한눈에 보기

분류
복합 위젯
대응 HTML
<select multiple> 또는 size가 1보다 큰 <select>, <datalist>
이름 정하는 방법
작성자
이름 필수
예
필수 상위 요소
없음
필수 하위 요소
option group

설명

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로 바뀌는지 확인합니다.
  • 현재 옵션(시각적 포커스)이 화면에서도 분명하게 보이는지 확인합니다.

함께 쓰는 속성

지원 속성

전역 속성(이름·설명 등)은 모든 역할에 쓸 수 있어 생략했습니다.

키보드 동작

키보드 동작
키동작
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 방식

HTML
<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>

옵션 묶음

HTML
<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>

현재 옵션 바꾸기

JavaScript
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를 주어 두 방식을 섞지 않습니다.

이 역할을 쓰는 패턴

참고 자료