메뉴는 네비게이션에 사용되며 웹 페이지 작동의 중요한 부분인 기능을 제공합니다.
- 구조 : 메뉴의 구조를 반영하고 적절한 레이블을 지정하는 방식으로 메뉴를 마크업합니다.
- 스타일링 : 일반적으로 인식되는 디자인 패턴을 사용하여 메뉴와 메뉴 항목의 상태를 구분합니다.
- 플라이아웃 메뉴 : 플라이아웃(드롭다운) 하위 메뉴를 마우스와 키보드로 적절하게 사용할 수 있는지 확인합니다.
- 애플리케이션 메뉴 : 데스크톱 애플리케이션 메뉴와 유사하도록 특정 마크업 및 키보드 동작을 추가합니다.
이것이 왜 중요한가요?
네비게이션 메뉴는 웹사이트의 기본 구조를 반영합니다. 애플리케이션 메뉴는 애플리케이션의 필수 기능에 대한 액세스를 제공합니다. 따라서 메뉴는 웹 페이지와 애플리케이션의 중요한 부분이며 디자인 및 개발 과정에서 특별한 주의가 필요합니다.
- 스크린 리더 및 키보드 사용자는 키보드 상호 운용성 및 다양한 방식으로 메뉴를 조작할 수 있는 마크업의 이점을 누릴 수 있습니다.
- 소근육 장애가 있는 사용자와 터치스크린 사용자는 클릭하거나 탭할 수 있는 더 큰 타겟이 필요합니다. 플라이아웃 메뉴에서는 마우스가 클릭 가능한 영역을 벗어난 직후에 하위 메뉴가 사라지지 않아야 합니다.
- 주의력이 제한적이거나 단기 기억력이 약한 사용자는 현재 페이지와 같이 쉽게 식별할 수 있는 상태를 명확하고 뚜렷하게 표시한 메뉴가 유용합니다.
메뉴 구조
시맨틱 마크업은 메뉴 구조를 사용자에게 전달합니다. 의미론적으로 코딩된 메뉴는 작은 화면 디스플레이, 화면 확대 및 기타 보조 기술과 같은 다양한 상황에 쉽게 적응할 수 있습니다.
메뉴 표현
일반적으로 목록을 사용하여 메뉴 구조를 전달합니다. 이러한 구조적 정보를 통해 보조 기술은 메뉴의 항목 수를 알리고 해당 탐색 기능을 제공할 수 있습니다.
접근 방식 1 : 정렬되지 않은 목록
메뉴 항목이 특정 순서가 아닌 경우 정렬되지 않은 목록(<ul>)을 사용합니다. 웹사이트 탐색과 같은 대부분의 메뉴 유형이 이 범주에 속합니다.
<ul>
<li><a href="…">Home</a></li>
<li><a href="…">Shop</a></li>
<li><a href="…">Space Bears</a></li>
<li><a href="…">Mars Cars</a></li>
<li><a href="…">Contact</a></li>
…
</ul>
접근 방식 2 : 정렬 목록
메뉴 항목의 순서가 중요한 경우 정렬된 목록(<ol>)을 사용합니다. 다음 예제에서 메뉴 항목은 시공 매뉴얼의 단계를 나타냅니다.
<ol>
<li><a href="…">Unpacking the Space Craft</a></li>
<li><a href="…">Check Contents of Package</a></li>
<li><a href="…">Build Chassis</a></li>
<li><a href="…">Build Engine</a></li>
<li><a href="…">Mount Engine to Chassis</a></li>
…
</ol>
메뉴 식별
사용자가 메뉴에 직접 액세스할 수 있도록 <nav> 요소를 사용하여 메뉴를 식별합니다. 메뉴를 마크업하는 다른 기법은 페이지 영역 튜토리얼에 설명되어 있습니다.
<nav>
<ul>
…
</ul>
</nav>
메뉴 레이블
메뉴를 쉽게 찾고 이해할 수 있도록 메뉴에 레이블을 붙입니다. 레이블은 사용자가 웹 페이지의 여러 메뉴를 구분할 수 있도록 짧지만 설명이 포함되어야 합니다. 제목, aria-label 또는 aria-labelledby를사용하여 레이블을 제공합니다. 이러한 기법은 영역 레이블 지정 튜토리얼에 설명되어 있습니다.
<nav aria-labelledby="mainmenulabel">
<h2 id="mainmenulabel" class="visuallyhidden">Main Menu</h2>
</nav>
현재 항목 표시
마크업을 사용하여 웹사이트의 현재 페이지와 같은 메뉴의 현재 항목을 표시하여 메뉴의 방향을 개선할 수 있습니다.
접근 방식 1 : 보이지 않는 텍스트 사용
스크린 리더 사용자에게 소리내어 읽히고 다른 보조 기술에서 현재 항목을 표시하는 데 사용되는 보이지 않는 레이블을 제공하여 사용자 지정 레이블 텍스트를 허용합니다.
사용자가 현재 항목과 상호 작용할 수 없도록 앵커(<a>)를 제거합니다. 이렇게 하면 오해를 피하고 현재 메뉴 항목이 활성화되어 있음을 강조할 수 있습니다.
다음 예제에서는 메뉴 항목에 보이지 않는 텍스트 "현재 페이지:"가 있고 <a> 요소는 현재 클래스가 있는 <span>으로 대체됩니다.
<li>
<span class="current">
<span class="visuallyhidden">Current Page: </span>
Space Bears
</span>
</li>
접근 방식 2 : WAI-ARIA 사용
메뉴의 현재 페이지를 표시하려면 aria-current="page" 속성을 사용합니다. 이 기법은 HTML에서 앵커(<a>)를 제거할 수 없을 때 특히 유용합니다.
다음 예제에서는 탐색의 링크가 페이지의 주요 콘텐츠를 가리킵니다.
<li>
<a href="#main" aria-current="page">
Space Bears
</a>
</li>
메뉴 스타일링
명확하고 일관된 스타일링을 사용하면 사용자가 메뉴를 더 빨리 찾고 인식할 수 있습니다. 이러한 스타일링에는 웹사이트 전체 페이지에서 동작, 모양 및 상대적 위치의 일관성이 포함됩니다.
일반적인 고려 사항
메뉴에는 장식용 또는 기능을 전달하는 아이콘과 같은 이미지가 사용되는 경우가 많습니다. 이러한 이미지에는 이미지 튜토리얼에 설명된 대로 대체 텍스트가 필요합니다. 대비 요구 사항은 메뉴 및 해당 항목에도 적용됩니다.
위치
웹사이트의 대상 고객이 예상하는 위치에 메뉴를 표시합니다. 예를 들어 웹사이트의 기본 탐색 메뉴는 일반적으로 페이지 왼쪽에 세로로 배치되거나 상단에 가로로 배치됩니다. 애플리케이션 메뉴는 일반적으로 상단에 가로로 배치됩니다.
식별
메뉴와 해당 항목을 쉽게 식별할 수 있어야 합니다. 이전 섹션에서 설명한 구조적 마크업 외에도 메뉴 및 항목의 존재를 시각적으로 전달하기 위해서는 색 구성표가 필요합니다.
모든 사람이 메뉴 레이블을 볼 수 있도록 하는 것이 좋습니다. 예를 들어 이 자습서에서 '메뉴 자습서', '모든 자습서', '이 페이지에서'는 모든 사용자가 사용할 수 있는 표시되는 제목으로 제공되는 메뉴 레이블입니다.
가독성
모든 텍스트에 맞게 메뉴 및 메뉴 항목의 크기를 적절하게 조정합니다. 메뉴 크기는 다양한 텍스트 크기에 맞게 조정하여 단어가 긴 언어와 더 큰 텍스트가 필요한 사용자를 수용해야 합니다. 대문자 텍스트, 줄 바꿈, 하이픈은 종종 산만하고 읽기 어렵기 때문에 가급적 사용하지 마세요.
크기
모바일 디바이스의 작은 터치스크린과 손재주가 약한 사람들을 위해 패딩과 같은 충분한 공백을 제공하세요. 동시에 사용자가 텍스트 크기를 늘리거나 페이지를 확대할 때 메뉴와 페이지의 다른 콘텐츠가 겹치지 않도록 하세요.
메뉴 항목
색상 및 기타 스타일링 옵션을 사용하여 메뉴 항목과 해당 상태를 전달하세요. 일부 사용자는 이러한 변경 사항을 인식하지 못할 수 있으므로 색상에만 의존하지 마세요. 예를 들어 메뉴 항목이 선택되었을 때 색상을 변경하는 것 외에도 메뉴 항목의 모양을 변경하거나 아이콘을 추가할 수 있습니다.
기본 상태
메뉴 항목을 활성화할 수 있는 페이지의 영역으로 시각적으로 표시하려면 고유한 스타일을 사용합니다. 그러나 대문자나 작은 대문자로 된 단어와 같이 과장된 텍스트 장식은 텍스트를 읽기 어렵게 만들 수 있으므로 피하세요.
호버 및 포커스 상태
메뉴 탐색 시 사용자에게 시각적 안내를 제공하는 호버링 또는 포커스된 메뉴 항목을 변경합니다. 이 예에서 호버링 및 포커스 상태는 반전된 색 구성표(흰색에 파란색이 아닌 흰색에 파란색)와 밑줄을 사용합니다.
nav a:hover,
nav a:focus {
color: #036;
background-color: #fff;
text-decoration: underline;
}
활성 상태
클릭, 탭 또는 키보드 선택을 통해 활성화된 메뉴 항목을 표시합니다. 예를 들어 사용자가 잘못된 메뉴 항목을 클릭한 경우와 같이 의도하지 않은 활성화를 식별할 수 있습니다. 이 예에서 활성화된 항목은 진한 파란색 배경과 밑줄이 있습니다.
nav a:active {
color: #fff;
background-color: #024;
text-decoration: underline;
}
현재 상태
또한 이전 섹션에서 설명한 구조적 마크업과 더불어 현재 메뉴 항목을 시각적으로 표시합니다.
이 예에서는 현재 메뉴 항목에 뚜렷한 색상과 모양을 부여하기 위해 다른 색상 조합(회색에 검은색)과 하단 테두리를 추가했습니다.
nav [aria-current=page] {
background-color: #bbb;
color: #000;
border-bottom: .25em solid #444;
}
방문한 상태
안내 단계와 같은 일부 메뉴 유형의 경우 사용자가 이미 방문한 적이 있는 메뉴 항목을 표시하는 것이 유용할 수 있습니다. 그러나 대부분의 메뉴는 방문한 상태에 따라 변경되지 않을 것으로 예상됩니다.
드롭다운 메뉴
플라이아웃(또는 드롭다운) 메뉴를 사용하여 웹 사이트의 페이지 계층 구조에 대한 개요를 제공합니다. 사용자가 정보를 찾을 수 있는 위치를 알고 있다면 여러 페이지를 로드할 필요가 없습니다. 애플리케이션 메뉴도 이와 유사하게 구현되지만 WAI-ARIA 마크업이 추가됩니다.
손 떨림과 같이 손재주가 약한 사람들은 종종 드롭다운 메뉴를 조작하는 데 어려움을 겪습니다. 일부에게는 불가능할 수도 있습니다. 상위 메뉴 항목의 페이지에서 하위 메뉴 항목을 반복하는 등 하위 메뉴 항목에 도달할 수 있는 다른 방법을 제공해야 합니다.
하위 메뉴 표시
마크업을 사용하여 시각적으로 하위 메뉴가 있는 탐색 메뉴 항목을 표시합니다. 다음 예에서는 하위 메뉴가 아이콘으로 시각적으로 표시됩니다. WAI-ARIA 마크업 aria-expanded="false"는 하위 메뉴 탐색이 현재 숨겨져 있거나 "collapsed"을 선언합니다.
<nav aria-label="Main">
<ul>
<li><a href="…">Home</a></li>
<li><a href="…">Shop</a></li>
<li class="has-submenu">
<a href="…" aria-expanded="false">
Space Bears
</a>
<ul>
<li><a href="…">Space Bear 6</a></li>
<li><a href="…">Space Bear 6 Plus</a></li>
</ul>
</li>
<li><a href="…">Mars Cars</a></li>
<li><a href="…">Contact</a></li>
</ul>
</nav>
드롭다운 기능
드롭다운 기능은 마우스와 키보드 사용자를 약간 별도로 고려한 CSS와 스크립트를 사용하여 만들어졌습니다.
마우스 사용자
다음 예제는 상위 메뉴 항목을 마우스 오버했을 때 하위 메뉴를 표시하고 숨기는 데 아래의 CSS 코드를 사용합니다.
nav > ul li ul { display: none; }
nav > ul li:hover ul { display: block; }
또한 스크립팅을 사용하여 마우스가 해당 영역을 벗어날 때 하위 메뉴 항목이 즉시 닫히는 것을 약간 지연시킵니다. 이 지연을 통해 마우스로 탐색하는 것이 정확하지 않을 때 메뉴를 더 쉽게 사용할 수 있습니다.
다음 예에서는 타이머를 사용하여 1초의 지연을 추가합니다.
var menuItems = document.querySelectorAll('li.has-submenu');
Array.prototype.forEach.call(menuItems, function(el, i){
el.addEventListener("mouseover", function(event){
this.className = "has-submenu open";
clearTimeout(timer);
});
el.addEventListener("mouseout", function(event){
timer = setTimeout(function(event){
document.querySelector(".has-submenu.open").className = "has-submenu";
}, 1000);
});
});
키보드 사용자
탭 키를 사용하여 메뉴를 탐색할 때 하위 메뉴가 열리면 키보드 사용자가 다음 최상위 항목으로 이동하기 위해 모든 하위 메뉴 항목을 거쳐야 하므로 하위 메뉴가 열리지 않아야 합니다. 대신 다음 접근 방식 중 하나를 고려하십시오.
접근방식 1) 부모 요소를 토글로 사용
상위 메뉴 항목이 하위 메뉴를 요약만 하고 웹 페이지 링크와 같은 기능을 수행할 필요가 없는 상황에서 이 접근 방식을 사용합니다. 이 경우 사용자가 최상위 항목을 활성화하면 스크립트에 의해 하위 메뉴가 열리고 초점이 하위 메뉴에서 벗어나면 하위 메뉴가 닫힙니다.
참고
href 속성 값은 무시되지만 JavaScript가 로드되지 않은 경우 기존 문서에 링크할 수 있습니다.
다음 코드는 has-submenu 클래스가 있는 모든 최상위 항목을 반복하고 상태에 따라 하위 메뉴를 열거나 닫는 클릭 이벤트를 추가합니다. 또한 하위 메뉴가 열려 있으면 aria-expanded 속성이 true로 설정되고 그렇지 않으면 false로 설정됩니다.
참고
이름과 상관없이 클릭 이벤트는 링크가 활성화되는 즉시 입력 방법에 관계없이 활성화됩니다.
var menuItems = document.querySelectorAll('li.has-submenu');
Array.prototype.forEach.call(menuItems, function(el, i){
el.querySelector('a').addEventListener("click", function(event){
if (this.parentNode.className == "has-submenu") {
this.parentNode.className = "has-submenu open";
this.setAttribute('aria-expanded', "true");
} else {
this.parentNode.className = "has-submenu";
this.setAttribute('aria-expanded', "false");
}
event.preventDefault();
return false;
});
});
접근방식 2) 버튼 요소를 토글로 사용
상위 메뉴 항목이 웹 페이지 링크와 같은 기능을 수행해야 하는 경우 상위 항목에 별도의 버튼을 추가하여 하위 메뉴를 열고 닫을 수 있습니다. 이 버튼은 하위 메뉴의 존재를 시각적으로 표시하는 역할도 할 수 있습니다.
다음 코드는 하위 메뉴가 있는 모든 최상위 메뉴 항목에 버튼을 추가합니다. 버튼이 활성화되면 하위 메뉴가 표시되거나 숨겨집니다. 버튼의 보이지 않는 레이블은 하위 메뉴의 상태를 반영하여 "하위 메뉴 표시" 또는 "하위 메뉴 숨기기"로 설정됩니다.
참고
가능하면 버튼의 레이블에 상위 메뉴 항목의 이름을 포함하세요(예: 예: "Space Bears 하위 메뉴 표시".
var menuItems = document.querySelectorAll('li.has-submenu');
Array.prototype.forEach.call(menuItems, function(el, i){
var activatingA = el.querySelector('a');
var btn = '<button><span><span class="visuallyhidden">show submenu for “' + activatingA.text + '”</span></span></button>';
activatingA.insertAdjacentHTML('afterend', btn);
el.querySelector('button').addEventListener("click", function(event){
if (this.parentNode.className == "has-submenu") {
this.parentNode.className = "has-submenu open";
this.parentNode.querySelector('a').setAttribute('aria-expanded', "true");
this.parentNode.querySelector('button').setAttribute('aria-expanded', "true");
} else {
this.parentNode.className = "has-submenu";
this.parentNode.querySelector('a').setAttribute('aria-expanded', "false");
this.parentNode.querySelector('button').setAttribute('aria-expanded', "false");
}
event.preventDefault();
});
});
애플리케이션 메뉴
웹 애플리케이션 메뉴는 탐색 메뉴와 동일한 기본 구조를 사용합니다. 가로 메뉴 모음으로 구성되며 레이어 메뉴 기능을 사용하는 경우가 많습니다. 그러나 추가 마크업 및 키보드 동작을 추가해야 합니다.
추가 마크업
aria-expanded 및 aria-haspopup 속성 외에도 애플리케이션 메뉴에 필요한 시맨틱을 제공하기 위해 다음과 같은 WAI-ARIA 역할이 사용됩니다.
- menubar : (일반적으로 가로) 메뉴 표시줄을 나타냅니다.
- menu : 메뉴 표시줄의 링크 또는 명령 집합을 나타내며, 플라이아웃 메뉴에 사용됩니다.
- menuitem : 개별 메뉴 항목을 나타냅니다.
- separator : 메뉴에서 두 메뉴 항목 그룹 사이의 구분 기호를 나타냅니다.
<ul role="menubar" id="appmenu">
…
<li role="menuitem" aria-haspopup="true">
Edit
<ul role="menu">
<li role="menuitem">Undo</li>
<li role="menuitem">Redo</li>
<li role="separator"></li>
<li role="menuitem">Cut</li>
<li role="menuitem">Copy</li>
<li role="menuitem">Paste</li>
</ul>
</li>
…
</ul>
애플리케이션 메뉴에는 일반적으로 링크가 없으며 기능을 제공하기 위해 스크립팅에 의존합니다.
기능
WAI-ARIA 역할을 추가한다고 해서 메뉴의 기능이나 키보드 동작이 자동으로 활성화되는 것은 아닙니다. 이러한 기능은 스크립팅을 사용하여 추가해야 합니다. WAI-ARIA 속성 및 키보드 동작에 대한 자세한 설명은 WAI-ARIA 저작 사례 문서(초안)에서 확인할 수 있습니다.
키보드 동작
웹 애플리케이션 메뉴는 데스크톱 애플리케이션 메뉴처럼 작동해야 합니다. 예를 들어 왼쪽 및 오른쪽 키는 최상위 항목을 반복하는 데 사용되며 위쪽 및 아래쪽 화살표는 하위 메뉴를 탐색하는 데 사용됩니다. 탭 키를 누르면 다음 메뉴 항목이 아닌 메뉴 뒤의 다음 항목에 초점이 맞춰집니다.
키보드로 메뉴 항목에 초점을 설정할 수 있도록 항목에 -1 값의 tabindex 속성이 지정됩니다. 첫 번째 주 메뉴 항목(이 예에서는 "파일")에는 탭 순서에 추가되는 tabindex 값 0이 할당되어 사용자가 키보드를 사용하여 메뉴에 액세스할 수 있습니다.
Array.prototype.forEach.call(appsMenuItems, function(el, i){
if (0 == i) {
el.setAttribute('tabindex', '0');
el.addEventListener("focus", function() {
currentIndex = 0;
});
} else {
el.setAttribute('tabindex', '-1');
}
});
Array.prototype.forEach.call(subMenuItems, function(el, i){
el.setAttribute('tabindex', '-1');
});
최상위 메뉴 항목
다음 표에는 최상위 메뉴 항목의 일반적인 동작이 요약되어 있습니다.
최상위 메뉴 항목에 대한 키 매핑
하위 메뉴 항목
다음 표에는 하위 메뉴 항목의 일반적인 동작이 요약되어 있습니다.
하위 메뉴 항목의 키 매핑
묶음 글 목록
[A11Y] - 웹접근성 튜토리얼 - 2. 페이지 구조
[A11Y] - 웹접근성 튜토리얼 - 3. 메뉴(네비게이션)
이 글은 W3C의 웹접근성 튜토리얼을 번역한 글입니다.
'A11Y' 카테고리의 다른 글
[번역] 웹접근성 튜토리얼 - 6. 폼 (0) | 2023.07.06 |
---|---|
[번역] 웹접근성 튜토리얼 - 5. 테이블(표) (0) | 2023.07.06 |
[번역] 웹접근성 튜토리얼 - 4. 이미지 (0) | 2023.07.06 |
[번역] 웹접근성 튜토리얼 - 2. 페이지 구조 (0) | 2023.07.06 |
[번역] 웹접근성 튜토리얼 - 1. 개요 (0) | 2023.07.06 |