빵 입니다.
Tabindex 본문
Tabindex는 HTML 속성이지만 카테고리를 웹 접근성으로 선택했다.
제대로 사용한다면 접근성에서 유용하게 쓰이기도 하고, 잘못 사용하면 접근성에 위배되기도 때문이다.
Tabindex 속성을 사용하는 것은 문서의 자연스러운 흐름 방해하고, 웹 접근성에 위배되는 일이며 HTML을 깔끔하게 작업하지 못한 것을 증빙하는 일이라고 생각했었다. 또한, 과거엔 비표준 요소라 여겨졌었기 때문에 사용을 더욱 꺼렸었다.
그러나 요즘 웹상의 소스를 가져와 사용하면 tabindex를 이용해 초점을 맞추는 것을 심심찮게 볼 수 있다.
트렌드에 맞게 잘 사용하고 싶어서 tabindex를 파보았다.
가장 먼저 공식 문서의 Tabindex에 대한 설명을 읽어 보았다.
MDN 한국어 버전과 MDN 영문 버전은 내용의 퀄리티 차이가 많이(?) 나서 둘 다 정독했다.
* 접근 가능하다 = 초점을 받다 = focus 할 수 있다 👉🏻 모두 같은 말입니다. *
Tabindex란?
- HTML 요소의 tabindex 속성은 현재 요소의 탭 순서를 나타낸다.
- 탭이 가능하다는 것은 요소에 포스가 가능하다는 걸 나타낸다.
- Tab 키를 사용해서 순차 키보드 탐색할 때 어느 순서에 위치할지 지정할 수 있다.
📍 기본적으로 마크업이 논리적으로 이루어져 있다면 굳이 tabindex를 사용해야 할 이유는 없다.
📍 오히려 잘못된 tabindex를 사용함으로써 스크린리더 사용자가 웹 페이지의 구조를 이해하는데 어려움으로 작용하게 될 수 있다. - Tabindex 속성이 없는 화면에선 자연스러운 마크업 순서에 따라 초점이 이동한다.
기본 값
대화형 콘텐츠의 기본 값 = 0
대화형 콘텐츠는 사용자와의 상호작용을 위해 특별하게 설계된 요소를 포함한다.
대화형 콘텐츠는 ARIA가 관리하는 접근성에 상태를 전달하는 기본 제공 역할 및 상태를 내장하고 있다.
<a>, <button>, <details>, <embed>, <iframe>, <label>, <select>, <textarea>
특정 조건을 만족하는 경우에 대화형 콘텐츠에 속하는 요소
- controls 속성을 가진 <audio>
- usemap 속성을 가진 <img>
- type="hidden"이 아닌 <input>
- type="toolbar"인 <menu>
- usemap 속성을 가진 <object>
- controls 속성을 가진 <video>
비 대화형 콘텐츠의 기본값 = -1
비 대화형 요소를 사용해 만든 대화형 컴포넌트는 접근성 트리에 나타나지 않는다. (ex. 버튼은 <span>으로 만드는 것)
접근성적 측면에서 본다면, 보조 기술이 해당 컴포넌트 탐색, 조작하는 것을 방지한다는 의미이다.
접근성을 위해서라도 상호작용 가능한 요소들은 대화형 요소를 사용해 적절한 의미와 함께 나타나야 한다.
어떻게 사용해야 하는가?
tabindex="-1" / tabindex="0" / tabindex="1"
값을 정수로 지정할 수 있고, 값에 따라 탐색 순서가 달라진다.
음의 정수(보통 -1)
- 음의 정숫값을 가지고 있는 요소는 Tab 키를 눌러서 접근이 불가능하다.
- 초점을 받는 대화형 콘텐츠 요소에 음의 정숫값을 할당하면 강제로 초점을 받지 않게 막을 수 있다.
- Javascript를 이용해서 해당 요소에 접근하게 만들 수 있다.
- 마우스를 클릭함으로써 시각적으로 focus 할 수 있다.
- 음의 정숫값은 off-screen 콘텐츠가 있을 때 유용하다.
📍 페이지에 관련된 요소만 보조 기술에 노출되어야 한다.(ex. 스크린 리더)
👉🏻 스크린 리더가 불필요한 정보까지 읽어준다면 얼마나 불편할까요... - 초점을 받을 수 없기 때문에 사실상 -1 값 이외의 음수 값은 의미가 없다.
0
- 초점을 받지 않는 div, span의 요소도 0의 값을 가지고 있다면 초점을 받을 수 있다.
- 양의 tabindex 값을 가진 요소들이 모두 초점을 받은 후에 초점을 받는다.
양의 정수
- 값의 크기에 따라 문서 내에서 초점을 가장 먼저 받는다. (0보다 우선순위)
- 자연스러운 마크업 순서를 거스를 수 있으니 주의해서 사용해야 한다.
- 동일한 값을 가진 요소는 마크업 순서에 따라 초점이 이동한다.
- 낮은 tabindex에서 높은 tabindex로 초점이 이동한다.
- 최댓값은 32767
- tabindex="4"인 요소는
tabindex="3"인 요소에 초점이 간 이후에 초점을 받는다.
tabindex="5"와 tabindex="0" 보다 먼저 초점을 받는다. - 한 화면에 아래와 같은 마크업이 있다고 가정한다면,
<div tabindex="2">탭 인덱스 2</div>
<strong tabindex="5">탭 인덱스 5</strong>
<div tabindex="0">탭 인덱스 0</div>
<span tabindex="3">탭 인덱스 3</span>
2 → 3 → 5 → 0 순으로 초점이 이동한다.
주의 사항
0보다 큰 tabindex 값을 가능한 사용하지 않는 것이 좋다.
접근성 보조 기술 사용자의 화면 탐색과 조작에 방해될 수 있다.
대신, 마크업을 논리적으로 짜자!
참고 사항
<div>에 tabindex를 추가하는 경우
- 부모 요소에 tabindex를 추가하면 부모 요소가 초점을 받는다.
- 그러나 자식 요소는 초점을 받지 못하고 방향 키로 스크롤링도 불가능하다.
- 자식 요소에 스크롤이 있을 경우, 자식 요소에 tabindex를 주어야 자식 요소가 초점을 받을 수 있고, 방향 키를 이용해 스크롤링이 가능하다.
<div class=“parent”>
<div class=“child”>긴 콘텐츠</div>
</div>
초점 이동 순서 정리
- 양의 정수 → 0 → 음의 정수(js 처리할 경우)
- 양의 정수에서 동일한 값을 가진 요소는 마크업 순서에 따라 초점이 이동한다.
- 양의 정수는 낮은 tabindex에서 높은 tabindex로 초점이 이동한다.
- 양의 정수가 모두 초점을 받은 후에 0이 초점을 받는다.
- 비 활성화된 요소는 Tab 키로 접근이 불가능하다.
- 값이 순차적일 필요는 없다.
- 아주 큰 수는 각 브라우저가 값을 다듬을 수도 있다.
스크립트를 이용해 접근성 준수하기
음의 값은 잘못 사용하면 보조 기술 사용자의 화면 탐색을 방해하지만, 잘 사용하면 오히려 도움이 될 수 있다.
탐색해야 할 콘텐츠가 아주 많을 경우가 그 예시이다.
아시아 대륙에 속한 국가가 아주 많을 경우엔? 북아메리카 대륙에 속한 국가가 아주 많을 경우엔?
div에 포함된 모든 국가명을 모두 읽어줄 것이다.
그런 폐해를 피하기 위해 Tabindex와 Javascript를 이용해 원하는, 듣고 싶은 대륙의 국가만 접근할 수 있도록 코드를 짜보았다.
부모 요소 <div>에 초점이 가도록 tabindex 값을 0으로 지정했다.
자식 요소는 초점이 가지 않도록 tabindex 값을 -1로 지정했다.
Tab 키를 누르면 부모 요소의 스크린 리더는 aria-label을 읽어준다.(= 초점이 이동한다.)
다시 Tab 키를 누르면, 다음 부모 요소의 aria-label을 읽어준다.
자식 요소에 접근하고 싶다면, 원하는 부모 요소에 초점이 갔을 때 방향 키를 조작하면 된다.
방향 키를 좌, 우로 이동하면 자식 요소 국가명의 초점이 이동한다.
<div class="country" role="region" aria-label="아시아 대륙에 속한 국가" tabindex="0">
<a href="#" target="_blank" tabindex="-1">한국</a>
<a href="#" target="_blank" tabindex="-1">일본</a>
<a href="#" target="_blank" tabindex="-1">중국</a>
</div>
<div class="country" role="region" aria-label="북아메리카 대륙에 속한 국가" tabindex="0">
<a href="#" target="_blank" tabindex="-1">미국</a>
<a href="#" target="_blank" tabindex="-1">캐나다</a>
</div>
let index = -1;
const country = document.getElementsByClassName('country');
for (const value of Object.values(country)) {
value.addEventListener('keydown', (e) => {
const childNodes = e.currentTarget.children.length;
if (index < -1) {
return;
}
if (e.keyCode === 37) {
if (index === 0) {
return false
} else {
-- index;
}
} else if (e.keyCode === 39){
if (index === (childNodes - 1)) {
return false
} else {
++ index;
}
} else if(e.keyCode === 9) {
index = -1;
return;
} else {
return;
}
e.currentTarget.children[index].focus();
});
}
보조 기술 사용자는 부모 요소의 aria-label을 듣고, 하위 항목 탐색이 필요하다면 키보드 방향 키를 이용해 하위 요소들을 탐색할 수 있다.
참고 사이트
Tabindex
https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/tabindex
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/tabIndex
https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets
https://web.dev/control-focus-with-tabindex/
Offscreen
https://developer.chrome.com/docs/lighthouse/accessibility/offscreen-content-hidden/
'스타디 > 웹 접근성' 카테고리의 다른 글
IAT(정보 접근성 기술) 컨퍼런스 2017 (0) | 2017.12.01 |
---|---|
2017 널리 세미나 (0) | 2017.06.28 |