tabindex로 포커스 제어

<button> 또는 <input>와 같은 표준 HTML 요소에는 키보드 접근성이 내장되어 있으며 가능하면 항상 사용해야 합니다. 그러나 맞춤 양방향 요소를 빌드해야 하는 경우 tabindex를 추가하여 예상되는 사용자 동작을 만들 수 있습니다.

브라우저 지원

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.5.
  • Safari: 3.1

소스

대화형 콘텐츠에만 tabindex를 추가하세요. 주요 이미지와 같이 중요한 콘텐츠라도 스크린 리더 사용자는 포커스를 추가하지 않고도 이를 이해할 수 있습니다.

tabindex란 무엇인가요?

내장 요소에서 제공하는 기본 탭 순서를 수정해야 하는 경우 tabindex HTML 속성을 사용하여 요소의 탭 위치를 명시적으로 설정할 수 있습니다.

tabindex는 모든 요소에 적용할 수 있지만 상호작용 요소에만 적용해야 하며 다양한 정수 값을 취합니다. tabindex를 사용하면 포커스 가능한 페이지 요소에 대해 명시적 순서를 지정하고, 포커스 불가능한 요소를 탭 순서에 삽입하고, 탭 순서에서 요소를 제거할 수 있습니다. 예를 들면 다음과 같습니다.

tabindex="0": 자연 탭 순서에 요소를 삽입합니다. Tab 키를 눌러 요소에 포커스를 둘 수 있고 focus() 메서드를 호출하여 요소에 포커스를 둘 수 있습니다.

tabindex="-1": 일반적인 탭 순서에서 요소를 삭제하더라도 focus() 메서드를 호출하여 계속 요소에 포커스를 맞출 수 있습니다.

tabindex="5": 0보다 큰 tabindex를 지정하면 해당 요소를 자연스러운 탭 순서 앞으로 가져옵니다. tabindex가 0보다 큰 요소가 여러 개 있다면 탭 순서는 0보다 큰 가장 낮은 값에서 시작하여 위로 올라갑니다. 0보다 큰 tabindex를 사용하는 것은 안티패턴으로 간주됩니다.

키보드로 컨트롤에 액세스할 수 있는지 확인

Lighthouse와 같은 도구는 특정 접근성 문제를 자동으로 감지하는 데 유용하지만, 일부 테스트는 여전히 사람이 직접 수행해야 합니다.

Tab 키를 눌러 사이트를 탐색해 보세요. 페이지의 모든 양방향 컨트롤에 도달할 수 있나요? 그렇지 않은 경우 tabindex을 사용하여 이러한 컨트롤의 포커스 가능성을 개선해야 할 수 있습니다.

페이지 수준에서 포커스 관리

tabindex를 사용하면 원활한 사용자 환경을 만들 수 있습니다. 예를 들어 페이지 로드의 여러 지점에서 일부 콘텐츠가 숨겨지는 다양한 콘텐츠 섹션이 있는 강력한 단일 페이지를 빌드하는 경우 즉, 페이지 새로고침 없이 내비게이션 링크가 표시되는 콘텐츠를 변경할 수 있습니다.

이 경우 선택한 콘텐츠 영역을 식별하고 tabindex-1로 지정한 다음 focus 메서드를 호출합니다. 이렇게 하면 콘텐츠가 자연스러운 탭 순서에 표시되지 않습니다. 포커스 관리라고 하는 이 기법은 사용자가 인지한 컨텍스트를 사이트의 시각적 콘텐츠와 일치된 상태로 유지합니다.

구성요소에서 포커스 관리

경우에 따라 맞춤 요소와 같이 컨트롤 수준에서 포커스를 관리해야 할 수도 있습니다.

어떤 키보드 동작을 구현할지 알기 어려울 수 있습니다. Accessible Rich Internet Applications(ARIA) Authoring Practices 가이드에는 구성요소 유형과 구성요소가 지원하는 키보드 작업의 종류가 나와 있습니다.

탭 순서에 요소 삽입

tabindex="0"를 사용하여 자연 탭 순서에 요소를 삽입합니다. 예를 들면 다음과 같습니다.

<div tabindex="0">Focus me with the TAB key</div>

요소에 포커스를 맞추려면 Tab 키를 누르거나 요소의 focus() 메서드를 호출합니다.

탭 순서에서 요소 삭제

tabindex="-1"를 사용하여 요소를 삭제합니다. 예를 들면 다음과 같습니다.

<button tabindex="-1">Can't reach me with the TAB key!</button>

이렇게 하면 자연스러운 탭 순서에서 요소가 삭제되지만 focus() 메서드를 호출하여 요소에 계속 포커스를 둘 수 있습니다.

요소에 tabindex="-1"을 적용해도 하위 요소에는 영향을 미치지 않습니다. 하위 요소가 자연스럽게 탭 순서에 있거나 tabindex 값으로 인해 탭 순서에 있는 경우 탭 순서로 유지됩니다. 탭 순서에서 요소와 모든 하위 요소를 삭제하려면 WICG의 inert 폴리필을 사용하는 것이 좋습니다. 폴리필은 제안된 inert 속성의 동작을 에뮬레이션하여 보조 기술에서 요소를 선택하거나 읽지 못하도록 합니다.

tabindex > 0 사용 자제

tabindex가 0보다 크면 요소가 일반적인 탭 순서 앞으로 이동합니다. tabindex가 0보다 큰 요소가 여러 개 있는 경우 탭 순서는 0보다 크고 가장 낮은 값부터 시작해서 계속 높은 값으로 이동합니다.

0보다 큰 tabindex를 사용하면 스크린 리더가 탭 순서가 아닌 DOM 순서로 페이지를 탐색하므로 안티패턴으로 간주됩니다. 요소가 탭 순서에서 더 일찍 표시되어야 하는 경우 DOM의 앞쪽으로 이동해야 합니다.

Lighthouse를 사용하면 tabindex가 0보다 큰 요소를 식별할 수 있습니다. 접근성 감사(Lighthouse > 옵션 > 접근성)를 실행하고 '[tabindex] 값이 0보다 큰 요소가 없음' 감사의 결과를 확인합니다.

'로빙 tabindex' 사용

복잡한 구성요소를 빌드하는 경우 포커스 외에도 키보드 지원을 추가해야 할 수 있습니다. 가능하면 내장된 select 요소를 사용하세요. 포커스를 받을 수 있으며 화살표 키를 사용하여 선택 가능한 추가 옵션을 노출할 수 있습니다.

자체 구성요소에서 유사한 함수를 구현하려면 '이동 tabindex'라고 하는 기법을 사용하면 됩니다. 이동 tabindex는 현재 활성 상태인 하위 요소를 제외한 모든 하위 요소에 대해 tabindex를 -1로 설정하여 작동합니다. 그런 다음 구성요소는 키보드 이벤트 리스너를 사용하여 사용자가 눌렀던 키를 확인합니다.

이 경우 구성요소는 이전에 포커스가 맞춰진 하위 요소의 tabindex를 -1로 설정하고 포커스를 둘 하위 요소의 tabindex을 0으로 설정하며 이 하위 요소에서 focus() 메서드를 호출합니다.

<div role="toolbar">
  <button tabindex="-1">Undo</button>
  <button tabindex="0">Redo</button>
  <button tabindex="-1">Cut</button>
</div>

<div role="toolbar">
  <button tabindex="-1">Undo</button>
  <button tabindex="-1">Redo</button>
  <button tabindex="0">Cut</button>
</div>

키보드 액세스 레시피

맞춤 구성요소에 어떤 수준의 키보드 지원이 필요한지 확실하지 않은 경우 ARIA Authoring Practices 1.1을 참고하세요. 이 가이드에서는 일반적인 UI 패턴을 나열하고 구성요소에서 지원해야 하는 키를 식별합니다.