속성 · 위젯 상태
aria-haspopup
요소를 조작하면 메뉴·목록·트리·그리드·대화상자 같은 팝업이 열린다는 것과 그 종류를 알립니다.
한눈에 보기
- 구분
- 속성 (Property)
- 분류
- 위젯 상태
- 값 형식
- 토큰 (false / true / menu / listbox / tree / grid / dialog)
- 기본값
false- 적용 범위
- 특정 역할에만 사용
- HTML 대체
- 없음 (
<select>는 목록 팝업 정보가 자동으로 전달됩니다)
설명
aria-haspopup은 요소를 누르거나 조작했을 때 상호작용할 수 있는 팝업이 나타난다는 것, 그리고 그 팝업의 역할이 무엇인지를 알립니다. 화면낭독기는 “하위 메뉴”, “대화 상자 열기” 등으로 읽어, 사용자가 이 버튼이 바로 동작을 실행하는 버튼이 아니라 선택지를 띄우는 버튼임을 알 수 있게 합니다.
값은 팝업의 역할과 정확히 같아야 합니다. role="menu"를 띄우면 menu(또는 같은 뜻인 true), role="listbox"면 listbox, role="dialog"면 dialog입니다. 흔한 실수는 단순한 링크 목록이나 펼침 영역을 띄우면서 aria-haspopup="true"를 쓰는 것입니다. true는 menu와 같은 뜻이라 사용자는 방향키로 이동하는 메뉴를 기대하게 됩니다. 메뉴 역할이 아닌 일반 펼침 영역이면 aria-expanded만 씁니다.
팝업이 열렸는지는 이 속성이 아니라 aria-expanded로 알립니다. 메뉴 버튼은 보통 aria-haspopup="menu"와 aria-expanded="false"로 시작해, 메뉴가 열리면 aria-expanded="true"로 바꿉니다. combobox는 기본값이 listbox여서, 목록 상자를 띄운다면 따로 쓰지 않아도 됩니다. 툴팁은 상호작용하는 팝업이 아니므로 이 속성을 쓰지 않습니다.
전역 사용은 ARIA 1.2에서 사용 중단
WAI-ARIA 1.1까지 aria-haspopup은 모든 요소에 쓸 수 있는 전역 속성이었지만, WAI-ARIA 1.2에서 전역 사용이 사용 중단(deprecated)되어 아래 “사용할 수 있는 역할”에 나열된 역할(과 그 역할을 상속하는 역할)에만 쓰도록 바뀌었습니다.
테스트할 때는 버튼에서 팝업 종류가 읽히는지, 실제로 열리는 요소의 역할이 값과 같은지, 열린 팝업 안에서 해당 역할에 맞는 키보드 동작(메뉴라면 방향키·Esc)이 되는지, 닫힌 뒤 포커스가 버튼으로 돌아오는지 확인합니다. 브라우저·화면낭독기에 따라 dialog·grid 등 일부 값을 모두 menu처럼 읽기도 합니다.
값
| 값 | 의미 |
|---|---|
false 기본값 | 팝업이 없습니다. |
true | 팝업이 있으며, 그 역할은 menu입니다. (menu와 같은 뜻) |
menu | 메뉴(role="menu")가 열립니다. |
listbox | 목록 상자(role="listbox")가 열립니다. |
tree | 트리(role="tree")가 열립니다. |
grid | 그리드(role="grid")가 열립니다. 예: 날짜 선택 달력. |
dialog | 대화상자(role="dialog")가 열립니다. |
사용 예
메뉴 버튼
<button type="button" id="export-btn" aria-haspopup="menu" aria-expanded="false" aria-controls="export-menu">내보내기</button>
<ul id="export-menu" role="menu" aria-labelledby="export-btn" hidden>
<li role="menuitem" tabindex="-1">PDF로 저장</li>
<li role="menuitem" tabindex="-1">엑셀로 저장</li>
</ul>날짜 선택 대화상자를 여는 버튼
<button type="button" aria-haspopup="dialog" aria-label="날짜 선택">📅</button>일반 펼침 메뉴에 true 사용 (비권장)
<button type="button" aria-haspopup="true" aria-expanded="false" aria-controls="nav-list">카테고리</button>
<ul id="nav-list" hidden>
<li><a href="/a">가전</a></li>
<li><a href="/b">가구</a></li>
</ul>링크 목록은 menu가 아닙니다. aria-haspopup을 빼고 aria-expanded만 쓰는 디스클로저로 만듭니다.
직접 해 보기
“내보내기” 버튼을 누르거나 포커스 후 아래 방향키를 눌러 메뉴를 여세요. 메뉴 안에서는 위·아래 방향키, Home·End로 이동하고 Enter로 실행, Esc로 닫습니다.
실시간 코드 — 조작하면 속성 값이 바뀌는 모습을 볼 수 있습니다
화면낭독기에서는
| 상황 | 들리는 안내 (예) |
|---|---|
aria-haspopup="menu" 버튼에 포커스 | 내보내기, 메뉴 버튼, 하위 메뉴, 축소됨 |
| 아래 방향키로 메뉴 열기 | 내보내기, 메뉴, PDF로 저장, 메뉴 항목, 1/3 |
aria-haspopup="dialog" 버튼에 포커스 | 날짜 선택, 버튼, 대화 상자 열기 |
aria-haspopup="listbox" 버튼에 포커스 | 정렬 기준, 버튼, 목록 열기, 축소됨 |
사용 지침
이렇게 쓰세요
- 값을 실제로 열리는 팝업의 역할과 같게 맞춥니다.
- 팝업의 열림 상태는
aria-expanded로 함께 알립니다. - 팝업 역할에 맞는 키보드 동작과 닫힌 뒤 포커스 복귀를 구현합니다.
이렇게 쓰지 마세요
- 링크 목록이나 단순 펼침 영역에
true/menu를 쓰지 않습니다. - 툴팁처럼 상호작용하지 않는 팝업에 쓰지 않습니다.
role="listbox"를 띄우는 콤보 상자에 중복으로 쓰지 않아도 됩니다(기본값이listbox).- 1.2에서 지원하지 않는 역할(일반 텍스트 등)에 쓰지 않습니다.
사용할 수 있는 역할
관련 속성·패턴
이 속성을 쓰는 패턴