tabindex로 포커스 제어

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

Browser Support

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

Source

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

tabindex란 무엇인가요?

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

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

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

tabindex="-1": 자연 탭 순서에서 요소를 삭제하지만 focus() 메서드를 호출하여 요소에 여전히 포커스를 설정할 수 있습니다.

tabindex="5": 0보다 큰 tabindex는 해당 요소를 자연 탭 순서의 맨 앞으로 가져옵니다. tabindex가 0보다 큰 요소가 여러 개인 경우 탭 순서는 0보다 큰 가장 낮은 값에서 시작하여 위로 이동합니다. 0보다 큰 tabindex를 사용하는 것은 안티패턴으로 간주됩니다.

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

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

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

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

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

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

구성요소에서 포커스 관리

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

구현할 키보드 동작을 파악하기는 쉽지 않습니다. 접근성 리치 인터넷 애플리케이션 (ARIA) 작성 관행 가이드에는 구성요소 유형과 구성요소에서 지원하는 키보드 작업 유형이 나와 있습니다.

탭 순서에 요소 삽입

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보다 작은 최솟값부터 시작하여 위로 올라갑니다.

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

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

'로빙 tabindex' 사용

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

자체 구성요소에서 유사한 함수를 구현하려면 '로빙 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 작성 관행 1.1을 참고하세요. 이 가이드에서는 일반적인 UI 패턴을 나열하고 구성요소에서 지원해야 하는 키를 식별합니다.