tabindex 사용

Dave Gash
Dave Gash
Meggin Kearney
Meggin Kearney

의미론적 HTML 요소의 DOM 위치에서 제공하는 기본 탭 순서는 편리하지만 탭 순서를 수정해야 할 때도 있습니다. HTML에서 요소를 이동하는 것이 이상적이지만 실행 가능하지 않을 수도 있습니다. 이 경우 tabindex HTML 속성을 사용하여 요소의 탭 위치를 명시적으로 설정할 수 있습니다.

Browser Support

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

Source

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

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

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

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

이는 특히 헤더, 이미지, 기사 제목과 같은 입력하지 않는 요소에 해당합니다. 가능한 경우 DOM 시퀀스가 논리적 탭 순서를 제공하도록 소스 코드를 정렬하는 것이 가장 좋습니다. tabindex를 사용하는 경우 버튼, 탭, 드롭다운, 텍스트 입력란과 같은 맞춤 대화형 컨트롤(즉, 사용자가 입력을 제공할 것으로 예상되는 요소)로 제한합니다.

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

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

원활한 사용자 환경을 위해 tabindex가 필요한 경우도 있습니다. 예를 들어 모든 콘텐츠가 동시에 표시되지 않는 여러 콘텐츠 섹션이 있는 강력한 단일 페이지를 빌드하는 경우 즉, 탐색 링크가 페이지 새로고침 없이 표시되는 콘텐츠를 변경할 수 있습니다.

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

구성요소에서 포커스 관리

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

예를 들어 select 요소는 기본 포커스를 받을 수 있지만 포커스가 이동하면 화살표 키를 사용하여 선택 가능한 추가 옵션을 표시할 수 있습니다. 맞춤 select 요소를 빌드하는 경우 키보드 사용자가 계속 컨트롤과 상호작용할 수 있도록 이 동작을 복제하는 것이 중요합니다.

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

라디오 버튼 세트를 닮았지만 외관과 동작에 고유한 방식을 적용한 맞춤 요소를 만들고 있을 수 있습니다.

<radio-group>
    <radio-button>Water</radio-button>
    <radio-button>Coffee</radio-button>
    <radio-button>Tea</radio-button>
    <radio-button>Cola</radio-button>
    <radio-button>Ginger Ale</radio-button>
</radio-group>

필요한 키보드 지원을 확인하려면 ARIA 작성 관행 가이드를 확인하세요. 섹션 2에는 새 요소와 가장 일치하는 기존 구성요소인 라디오 그룹의 특성 표를 비롯한 디자인 패턴 목록이 포함되어 있습니다.

지원해야 하는 일반적인 키보드 동작 중 하나는 위/아래/왼쪽/오른쪽 화살표 키입니다. 이 동작을 새 구성요소에 추가하려면 로빈 탭 인덱스라는 기법을 사용합니다.

이동 탭 인덱스는 현재 활성 상태인 하위 요소를 제외한 모든 하위 요소의 tabindex를 -1로 설정하여 작동합니다.

<radio-group>
  <radio-button tabindex="0">Water</radio-button>
  <radio-button tabindex="-1">Coffee</radio-button>
  <radio-button tabindex="-1">Tea</radio-button>
  <radio-button tabindex="-1">Cola</radio-button>
  <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

구성요소는 키보드 이벤트 리스너를 사용하여 사용자가 누르는 키를 결정합니다. 이 경우 이전에 포커스가 설정된 하위 요소의 tabindex를 -1로 설정하고, 포커스가 설정될 하위 요소의 tabindex를 0으로 설정하고, 포커스 메서드를 호출합니다.

<radio-group>
    <!-- Assuming the user pressed the down arrow, we'll focus the next available child -->
    <radio-button tabindex="-1">Water</radio-button>
    <radio-button tabindex="0">Coffee</radio-button> // call .focus() on this element
    <radio-button tabindex="-1">Tea</radio-button>
    <radio-button tabindex="-1">Cola</radio-button>
    <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

사용자가 마지막 (또는 포커스를 이동하는 방향에 따라 첫 번째) 하위 요소에 도달하면 포커스가 첫 번째 (또는 마지막) 하위 요소로 다시 루프됩니다.

다음 예를 시도해 보세요. DevTools에서 요소를 검사하여 탭 인덱스가 한 라디오 버튼에서 다음 라디오 버튼으로 이동하는 것을 확인합니다.

모달 및 키보드 트랩

포커스를 수동으로 관리하면 복잡한 상황이 발생할 수 있으므로 피하는 것이 좋습니다. 예를 들어 포커스를 관리하고 탭 동작을 캡처하려고 하지만 완료될 때까지 사용자가 탭을 닫지 못하도록 하는 자동 완성 위젯이 있습니다. 이를 키보드 함정이라고 하며 사용자에게 매우 불편을 줄 수 있습니다.

WCAG 2.1.2 섹션에 따르면 키보드 포커스가 특정 페이지 요소에서 잠기거나 갇혀서는 안 됩니다. 사용자는 키보드만 사용하여 모든 페이지 요소 간에 이동할 수 있어야 합니다.

이 규칙의 예외는 모달입니다. 하지만 모달을 만들 때는 tabindex를 사용하지 않는 것이 좋습니다. inert를 사용하면 사용자가 실수로 요소와 상호작용할 수 없도록 할 수 있습니다 (의도적인 키보드 트랩). 기본적으로 비활성 상태인 <dialog> 요소를 사용하여 사용자를 위한 모달을 만들고 모달 외부의 클릭과 탭을 차단합니다. 이렇게 하면 사용자가 필수 선택사항에 집중할 수 있습니다.