역할 · 복합 위젯
role="menubar"
보통 가로로 항상 보이는 메뉴입니다. 데스크톱 프로그램의 “파일 · 편집 · 보기” 메뉴 막대에 해당합니다.
한눈에 보기
- 분류
- 복합 위젯
- 대응 HTML
- 없음
- 이름 정하는 방법
- 작성자
- 이름 필수
- 아니요
- 필수 상위 요소
- 없음
- 필수 하위 요소
menuitemmenuitemcheckboxmenuitemradiogroup
설명
menubar는 menu의 하위 역할로, 화면에 계속 표시되는 메뉴입니다. aria-orientation의 기본값은 가로(horizontal)입니다. 각 항목은 menuitem이며, 하위 메뉴를 여는 항목에는 aria-haspopup="menu"(또는 true)와 aria-expanded를 붙이고, 하위 메뉴는 role="menu"로 만듭니다.
메뉴 막대 전체는 탭 정지 하나이며(로빙 tabindex), 메뉴 막대 항목 사이는 ←/→, 하위 메뉴 안은 ↑/↓로 이동합니다. 하위 메뉴가 열려 있을 때 ←/→를 누르면 옆 메뉴의 하위 메뉴로 바로 넘어가는 동작도 APG에 정의되어 있습니다.
웹사이트 상단 내비게이션에 쓰지 마세요
메뉴 막대는 웹 문서 편집기, 디자인 도구처럼 애플리케이션 명령을 모은 곳에만 맞습니다. 사이트 상단 메뉴를 menubar로 만들면 화면낭독기 사용자가 링크 목록·Tab 이동 같은 익숙한 탐색을 쓰지 못하고, 구현해야 할 키보드 동작도 많아 결함이 생기기 쉽습니다. 사이트 내비게이션은 <nav> + 링크 목록(+ 디스클로저 버튼)으로 만듭니다.
테스터 관점
- 메뉴 막대 항목 사이가 Tab이 아니라 ←/→로 이동하는지, Tab을 누르면 메뉴 막대를 벗어나는지 확인합니다.
- 하위 메뉴가 열리면 부모 항목의
aria-expanded가true로 바뀌는지 확인합니다. - Esc로 하위 메뉴를 닫았을 때 포커스가 메뉴 막대 항목으로 돌아오는지 확인합니다.
함께 쓰는 속성
지원 속성
전역 속성(이름·설명 등)은 모든 역할에 쓸 수 있어 생략했습니다.
키보드 동작
| 키 | 동작 |
|---|---|
| → | (메뉴 막대 항목) 다음 항목으로 이동합니다(마지막에서 처음으로 순환은 선택 사항). (하위 메뉴 안, 하위 메뉴 없는 항목) 하위 메뉴를 닫고 다음 메뉴 막대 항목으로 이동해 그 하위 메뉴를 엽니다. |
| ← | (메뉴 막대 항목) 이전 항목으로 이동합니다. (하위 메뉴 안) 하위 메뉴를 닫고 이전 메뉴 막대 항목으로 이동해 그 하위 메뉴를 엽니다. 중첩 하위 메뉴라면 부모 항목으로 돌아갑니다. |
| ↓ | (메뉴 막대 항목) 하위 메뉴를 열고 첫 항목으로 이동합니다. (하위 메뉴 안) 다음 항목으로 이동합니다. |
| ↑ | (메뉴 막대 항목, 선택 사항) 하위 메뉴를 열고 마지막 항목으로 이동합니다. (하위 메뉴 안) 이전 항목으로 이동합니다. |
| Enter | (하위 메뉴가 있는 항목) 하위 메뉴를 열고 첫 항목으로 이동합니다. (일반 항목) 실행하고 메뉴를 닫습니다. |
| Space | Enter와 같습니다. 체크·라디오 항목은 상태를 바꿉니다. |
| Home | 현재 메뉴(막대 또는 하위 메뉴)의 첫 항목으로 이동합니다. |
| End | 현재 메뉴의 마지막 항목으로 이동합니다. |
| Esc | 하위 메뉴를 닫고 그 메뉴를 연 메뉴 막대 항목으로 포커스를 돌려보냅니다. |
| Tab | 열린 메뉴를 모두 닫고 메뉴 막대 다음의 포커스 요소로 이동합니다. |
| 글자 키 | (선택 사항) 현재 메뉴에서 그 글자로 시작하는 다음 항목으로 이동합니다. |
사용 예
메뉴 막대 구조
<ul role="menubar" aria-label="문서 편집기">
<li role="none">
<span role="menuitem" tabindex="0" aria-haspopup="menu" aria-expanded="false">파일</span>
<ul role="menu" aria-label="파일" hidden>
<li role="menuitem" tabindex="-1">새 문서</li>
<li role="menuitem" tabindex="-1">열기</li>
</ul>
</li>
<li role="none">
<span role="menuitem" tabindex="-1" aria-haspopup="menu" aria-expanded="false">편집</span>
...
</li>
</ul>하위 메뉴 열기
function openSub(top, focusLast) {
var sub = top.nextElementSibling;
top.setAttribute('aria-expanded', 'true');
sub.hidden = false;
var items = sub.querySelectorAll('[role^="menuitem"]');
(focusLast ? items[items.length - 1] : items[0]).focus();
}메뉴 막대 항목마다 tabindex="0"을 주는 실수
<span role="menuitem" tabindex="0">파일</span>
<span role="menuitem" tabindex="0">편집</span>
<!-- 메뉴 막대는 탭 정지 하나입니다. 현재 항목 외에는 tabindex="-1" -->직접 해 보기
메뉴 막대에 포커스를 두고 ← →로 이동, ↓·Enter로 하위 메뉴를 여세요. 하위 메뉴가 열린 상태에서 ← →를 누르면 옆 메뉴가 바로 열립니다. Esc는 하위 메뉴를 닫고 메뉴 막대 항목으로 돌아갑니다.
실시간 코드 — 조작하면 속성 값이 바뀌는 모습을 볼 수 있습니다
화면낭독기에서는
| 상황 | 들리는 안내 (예) |
|---|---|
| 메뉴 막대로 이동 | 문서 편집기, 메뉴 막대, 파일, 하위 메뉴, 축소됨, 1/3 |
| ↓로 하위 메뉴 엶 | 파일, 메뉴, 새 문서, 메뉴 항목, 1/3 |
| 하위 메뉴에서 → | 편집, 메뉴, 실행 취소, 메뉴 항목, 1/3 |
사용 지침
이렇게 쓰세요
- 애플리케이션 명령을 모은 메뉴에만 씁니다.
- 메뉴 막대 전체를 탭 정지 하나로 만들고, 마지막으로 포커스한 항목을 기억합니다.
- 하위 메뉴를 여닫을 때 부모 항목의
aria-expanded를 갱신합니다.
이렇게 쓰지 마세요
- 웹사이트 내비게이션에 쓰지 않습니다.
- 하위 메뉴를 마우스 hover로만 열리게 만들지 않습니다.
- 메뉴 막대 항목을 링크(
<a href>)로 두고 메뉴 역할을 덧씌우지 않습니다.