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": 요소를 자연스러운 탭 순서에 삽입합니다. Tab을 눌러 요소에 포커스를 둘 수 있으며, 요소의 focus() 메서드를 호출하여 요소에 포커스를 둘 수 있습니다.

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

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

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

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

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

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

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

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

구성요소에서 포커스 관리

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

어떤 키보드 동작을 구현해야 할지 알기 어려울 수 있습니다. Accessible Rich Internet Applications (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 사용 자제

0보다 큰 tabindex은 요소를 자연스러운 탭 순서의 맨 앞으로 이동시킵니다. tabindex이 0보다 큰 요소가 여러 개 있는 경우 탭 순서는 0보다 큰 가장 낮은 값에서 시작하여 위로 올라갑니다.

tabindex이 0보다 큰 값을 사용하면 스크린 리더가 탭 순서가 아닌 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 작성 관행 1.1을 참고하세요. 이 가이드에서는 일반적인 UI 패턴을 나열하고 구성요소에서 지원해야 하는 키를 식별합니다.