ARIA 접근성 가이드

역할 · 복합 위젯

role="combobox"

값을 입력하거나 고를 수 있는 입력 요소와, 그 값을 고르도록 돕는 팝업(목록 상자 등)을 묶은 위젯입니다.

심화HTML 요소 우선

한눈에 보기

분류
복합 위젯
대응 HTML
<select>(multiple·size>1 없음), list 속성이 있는 <input> + <datalist>
이름 정하는 방법
작성자
이름 필수
예
필수 상위 요소
없음
필수 하위 요소
없음

설명

combobox는 입력 요소 하나와, 값을 고르는 데 도움을 주는 팝업으로 이루어집니다. 검색어 자동완성, 주소 검색, 디자인을 바꾼 선택 상자가 대표적입니다. 팝업은 기본적으로 listbox이며, aria-haspopup으로 grid, tree, dialog도 지정할 수 있습니다(기본값 listbox).

WAI-ARIA 1.2 방식

  • 포커스를 받는 입력 요소 자체가 role="combobox"입니다. 편집 가능한 콤보박스는 <input type="text" role="combobox">, 선택만 하는 콤보박스는 <div role="combobox" tabindex="0">입니다.
  • aria-controls(필수)로 팝업의 id를 가리킵니다.
  • aria-expanded(필수)로 팝업이 열렸는지 알립니다.
  • 포커스는 입력란에 그대로 두고, 팝업 안 “현재 옵션”은 aria-activedescendant로 가리킵니다. 그 옵션에 aria-selected="true"를 주어 시각적 포커스와 맞춥니다.
  • aria-autocomplete — list(목록으로 제안), inline(입력란 안에 나머지 글자를 채움), both, none.

이전 방식과의 차이

이전 방식과의 차이
버전구조팝업 연결
ARIA 1.0입력란(textbox)에 role="combobox"aria-owns로 목록 상자를 소유
ARIA 1.1combobox가 컨테이너이고, 그 안에 textbox와 팝업이 들어감컨테이너가 팝업을 소유(aria-owns), 입력란은 aria-controls
ARIA 1.2입력란 자체가 combobox (1.0과 비슷하지만 선택 전용 콤보박스도 정의)aria-controls

1.1의 컨테이너 방식은 보조기술 지원이 일관되지 않아 1.2에서 폐기되었습니다. 오래된 라이브러리 코드에서 role="combobox"가 <div> 래퍼에 붙어 있고 그 안에 <input>이 있다면 1.1 방식이므로 1.2 방식으로 고칩니다. aria-owns 대신 aria-controls를 씁니다.

먼저 select와 datalist를 검토하세요

목록에서 하나를 고르기만 하면 <select>가 가장 안정적이고, 간단한 제안 목록은 <input list> + <datalist>로도 됩니다. ARIA 콤보박스는 구현할 키보드 동작과 상태가 많아, 사용자 정의 디자인·비동기 검색이 꼭 필요할 때만 만듭니다.

테스터 관점

  • 입력란에 포커스했을 때 “콤보 상자, 축소됨”처럼 역할과 펼침 상태가 읽히는지 확인합니다.
  • ↓로 옵션을 이동할 때 포커스가 입력란에 남아 있으면서 옵션 이름이 읽히는지(aria-activedescendant가 바뀌는지) 확인합니다.
  • Esc로 팝업이 닫히고, 선택 후 값이 입력란에 들어가는지 확인합니다.
  • 결과 개수나 “결과 없음”이 라이브 리전 등으로 알려지는지 확인합니다.

함께 쓰는 속성

필수 속성

지원 속성

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

키보드 동작

키보드 동작
키동작
↓팝업이 열려 있으면 다음 옵션으로 시각적 포커스를 옮깁니다. 닫혀 있으면 (선택 사항) 팝업을 열고 첫 옵션으로 이동합니다.
↑(선택 사항) 팝업이 열려 있으면 이전 옵션(처음이면 마지막)으로, 닫혀 있으면 팝업을 열고 마지막 옵션으로 이동합니다.
Alt + ↓(선택 사항) 시각적 포커스를 옮기지 않고 팝업만 엽니다.
Alt + ↑(선택 사항) 팝업을 닫고 포커스를 입력란에 둡니다.
Enter팝업에서 시각적 포커스가 있는 옵션을 값으로 받아들이고 팝업을 닫습니다.
Esc팝업이 열려 있으면 닫습니다. (선택 사항) 닫혀 있으면 입력란을 비웁니다.
← / →(편집 가능) 입력란의 커서를 옮기고, 시각적 포커스를 입력란으로 되돌립니다.
Home / End(편집 가능, 선택 사항) 입력란의 처음/끝으로 커서를 옮깁니다. 선택 전용 콤보박스에서는 팝업을 열고 첫/마지막 옵션으로 이동합니다.
글자 키편집 가능: 입력란에 글자를 넣고 목록을 다시 거릅니다. 선택 전용: 그 글자로 시작하는 옵션으로 이동합니다.
Space(선택 전용) 팝업을 열거나, 열려 있으면 현재 옵션을 선택합니다.
Tab(선택 전용) 현재 옵션을 선택하고 팝업을 닫은 뒤 다음 요소로 이동합니다. 편집 가능한 콤보박스는 팝업을 닫고 이동합니다.

사용 예

ARIA 1.2 편집 가능 콤보박스

권장권장: 입력란 자체가 combobox
<label for="city">도시</label>
<input type="text" id="city" role="combobox"
       aria-autocomplete="list" aria-expanded="false" aria-controls="city-list">
<ul id="city-list" role="listbox" aria-label="도시" hidden>
  <li role="option" id="city-1">서울</li>
  <li role="option" id="city-2">세종</li>
</ul>

선택 전용 콤보박스 (select 대체)

HTML
<span id="sort-label">정렬</span>
<div role="combobox" tabindex="0" aria-labelledby="sort-label"
     aria-haspopup="listbox" aria-expanded="false" aria-controls="sort-list">최신순</div>
<ul id="sort-list" role="listbox" aria-labelledby="sort-label" hidden>
  <li role="option" id="sort-1" aria-selected="true">최신순</li>
  <li role="option" id="sort-2" aria-selected="false">인기순</li>
</ul>

열기·옵션 이동

JavaScript
function open() {
  list.hidden = false;
  input.setAttribute('aria-expanded', 'true');
}
function move(opt) {
  options.forEach(function (o) { o.setAttribute('aria-selected', String(o === opt)); });
  input.setAttribute('aria-activedescendant', opt.id);   // 포커스는 input에 그대로
  opt.scrollIntoView({ block: 'nearest' });
}

ARIA 1.1 컨테이너 방식

비권장비권장: 1.2에서 폐기된 구조
<div role="combobox" aria-expanded="false" aria-owns="list">
  <input type="text" aria-controls="list">
</div>
<ul id="list" role="listbox">...</ul>

직접 해 보기

ARIA 1.2 방식의 편집 가능 콤보박스입니다(목록 자동완성, 수동 선택). 글자를 입력하면 목록이 걸러지고, ↓/↑로 옵션을 고른 뒤 Enter로 확정합니다. Alt+↓는 목록만 열고, Esc는 닫거나(닫혀 있으면) 입력을 지웁니다. 포커스가 입력란에 머무는 동안 aria-activedescendant가 바뀌는 모습을 실시간 코드에서 볼 수 있습니다.

화면낭독기에서는

화면낭독기 안내 예시 (표현은 화면낭독기·브라우저·버전에 따라 조금씩 다릅니다)
상황들리는 안내 (예)
콤보박스에 포커스과일, 콤보 상자, 축소됨, 편집 가능, 비어 있음
“바” 입력 후 결과 알림결과 2개
↓로 옵션 이동바나나, 1/2
Enter로 선택과일, 콤보 상자, 축소됨, 바나나

사용 지침

이렇게 쓰세요

  • 포커스를 받는 입력 요소에 role="combobox"를 붙입니다(1.2 방식).
  • aria-controls로 팝업을 연결하고, 열고 닫을 때마다 aria-expanded를 갱신합니다.
  • 팝업 안 이동은 포커스를 옮기지 말고 aria-activedescendant로 표현합니다.
  • 팝업을 여는 화살표 버튼은 tabindex="-1"로 탭 순서에서 빼고 이름을 붙입니다.

이렇게 쓰지 마세요

  • 1.1 방식처럼 래퍼 <div>에 role="combobox"를 붙이지 않습니다.
  • 팝업이 닫혔는데 aria-activedescendant가 숨은 옵션을 가리키게 두지 않습니다.
  • 옵션 이동 시 실제 DOM 포커스를 옵션으로 옮겨 입력을 끊지 않습니다.
  • <select>로 충분한 곳에 직접 만든 콤보박스를 쓰지 않습니다.

이 역할을 쓰는 패턴

참고 자료