역할 · 복합 위젯
role="combobox"
값을 입력하거나 고를 수 있는 입력 요소와, 그 값을 고르도록 돕는 팝업(목록 상자 등)을 묶은 위젯입니다.
한눈에 보기
- 분류
- 복합 위젯
- 대응 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.1 | combobox가 컨테이너이고, 그 안에 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로 팝업이 닫히고, 선택 후 값이 입력란에 들어가는지 확인합니다.
- 결과 개수나 “결과 없음”이 라이브 리전 등으로 알려지는지 확인합니다.
함께 쓰는 속성
필수 속성
지원 속성
aria-activedescendantaria-autocompletearia-disabledaria-errormessagearia-haspopuparia-invalidaria-readonlyaria-required전역 속성(이름·설명 등)은 모든 역할에 쓸 수 있어 생략했습니다.
키보드 동작
| 키 | 동작 |
|---|---|
| ↓ | 팝업이 열려 있으면 다음 옵션으로 시각적 포커스를 옮깁니다. 닫혀 있으면 (선택 사항) 팝업을 열고 첫 옵션으로 이동합니다. |
| ↑ | (선택 사항) 팝업이 열려 있으면 이전 옵션(처음이면 마지막)으로, 닫혀 있으면 팝업을 열고 마지막 옵션으로 이동합니다. |
| Alt + ↓ | (선택 사항) 시각적 포커스를 옮기지 않고 팝업만 엽니다. |
| Alt + ↑ | (선택 사항) 팝업을 닫고 포커스를 입력란에 둡니다. |
| Enter | 팝업에서 시각적 포커스가 있는 옵션을 값으로 받아들이고 팝업을 닫습니다. |
| Esc | 팝업이 열려 있으면 닫습니다. (선택 사항) 닫혀 있으면 입력란을 비웁니다. |
| ← / → | (편집 가능) 입력란의 커서를 옮기고, 시각적 포커스를 입력란으로 되돌립니다. |
| Home / End | (편집 가능, 선택 사항) 입력란의 처음/끝으로 커서를 옮깁니다. 선택 전용 콤보박스에서는 팝업을 열고 첫/마지막 옵션으로 이동합니다. |
| 글자 키 | 편집 가능: 입력란에 글자를 넣고 목록을 다시 거릅니다. 선택 전용: 그 글자로 시작하는 옵션으로 이동합니다. |
| Space | (선택 전용) 팝업을 열거나, 열려 있으면 현재 옵션을 선택합니다. |
| Tab | (선택 전용) 현재 옵션을 선택하고 팝업을 닫은 뒤 다음 요소로 이동합니다. 편집 가능한 콤보박스는 팝업을 닫고 이동합니다. |
사용 예
ARIA 1.2 편집 가능 콤보박스
<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 대체)
<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>열기·옵션 이동
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 컨테이너 방식
<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>로 충분한 곳에 직접 만든 콤보박스를 쓰지 않습니다.
관련 역할·패턴
이 역할을 쓰는 패턴