접근성 모범 사례
GitLab v19.1잘못된 ARIA보다 ARIA를 사용하지 않는 것이 낫다는 원칙에 따라, aria-*, role, tabindex를 사용하기 전에 다음 권장 사항을 먼저 검토하세요. WebAIM의 상위 100만 홈페이지 접근성 분석에서 "ARIA는 더 높은 탐지 가능한 오류와 상관 관계가 있다"는 사실이 발견되었습니다.
빠른 요약#
잘못된 ARIA보다 ARIA를 사용하지 않는 것이 낫다는 원칙에 따라,
aria-*, role, tabindex를 사용하기 전에 다음 권장 사항을 먼저 검토하세요.
접근성 시맨틱이 내장된 시맨틱 HTML을 사용하고, 이상적으로는
스크린 리더와 브라우저의 관련 조합으로 테스트하세요.
WebAIM의 상위 100만 홈페이지 접근성 분석에서
"ARIA는 더 높은 탐지 가능한 오류와 상관 관계가 있다"는 사실이 발견되었습니다.
ARIA를 잘못 사용하면 오류가 크게 증가할 가능성이 높으므로,
확신이 없다면 aria-*, role, tabindex를 사용하지 말고 시맨틱 HTML을 고수하세요.
macOS에서 키보드 탐색 활성화#
기본적으로 macOS는 탭 키를 텍스트 상자와 목록만으로 제한합니다. 전체 키보드 탐색을 활성화하려면:
-
시스템 환경설정을 엽니다.
-
키보드를 선택합니다.
-
단축키 탭을 엽니다.
-
키보드 탐색으로 컨트롤 간 포커스 이동 설정을 활성화합니다.
브라우저별 키보드 탐색 활성화에 대한 자세한 내용은 a11yproject에서 확인할 수 있습니다.
빠른 체크리스트#
장식이 아닌 아이콘에는 aria-label이 있습니다.
-
클릭 가능한 아이콘은 버튼입니다. 즉,
<gl-icon />대신<gl-button icon="close" />를 사용합니다. -
아이콘 전용 버튼에는
aria-label이 있습니다. -
인터랙티브 요소는 Tab 키로 접근할 수 있고 가시적인 포커스 상태가 있습니다.
-
툴팁이 있는 요소는 Tab 키로 포커스 가능합니다.
-
role,tabindex또는aria-*속성이 불필요한 것은 없습니까? -
div또는span요소를p,button,time과 같은 더 시맨틱한 HTML 요소로 교체할 수 있습니까?
좋은 문서 구조 제공#
제목은 스크린 리더 사용자가 콘텐츠를 탐색하는 데 사용하는 주요 메커니즘입니다. 따라서 페이지의 제목 구조는 좋은 목차처럼 이해하기 쉬워야 합니다. 다음 사항을 확인해야 합니다:
-
페이지에
h1요소가 하나만 있어야 합니다. -
제목 레벨을 건너뛰어서는 안 됩니다.
-
제목 레벨이 올바르게 중첩되어야 합니다.
스크린 리더를 위한 접근 가능한 이름 제공#
접근 가능한 이름이 있는 마크업을 제공하려면 다음 사항을 확인하세요:
-
입력에 연결된
label이 있어야 합니다. -
버튼과 링크에 가시적인 텍스트가 있거나, 아이콘 버튼처럼 가시적인 텍스트가 없을 때는
aria-label이 있어야 합니다. -
이미지에
alt속성이 있어야 합니다. -
fieldset의 첫 번째 자식으로legend가 있어야 합니다. -
figure의 첫 번째 자식으로figcaption이 있어야 합니다. -
table의 첫 번째 자식으로caption이 있어야 합니다.
alt 속성은 약 150자를 넘지 않아야 합니다. 공식 지침은 없지만, 일부 스크린 리더는 alt 속성 내의 긴 문자열을 읽지 않습니다.
접근 가능한 이름은 여러 방법으로 제공할 수 있으며 접근 가능한 이름 계산에 따라 결정됩니다. 다음은 우선순위를 가지는 다양한 기법의 간략한 순서입니다:
-
aria-labelledby -
aria-label -
alt,legend,figcaption또는caption -
title
접근 가능한 이름 제공 예시#
다음 하위 섹션에는 접근 가능한 이름이 있는 HTML 요소를 렌더링하는 마크업 예시가 포함되어 있습니다.
GlFormGroup을 사용할 때 주의하세요:
-
labelprop만 전달하면label값을 포함하는legend가 있는fieldset이 렌더링됩니다. -
label과label-forprop을 모두 전달하면 동일한label-forID를 가진 폼 입력을 가리키는label이 렌더링됩니다.
접근 가능한 이름이 있는 폼 입력#
체크박스 및 라디오 입력 그룹은 legend가 있는 fieldset에 함께 그룹화해야 합니다.
legend는 체크박스 및 라디오 입력 그룹에 레이블을 제공합니다.
label, 자식 텍스트, 또는 자식 요소가 시각적으로 필요하지 않다면,
클래스 이름 gl-sr-only를 사용하여 스크린 리더를 제외한 모든 것에서 요소를 숨기세요.
파일 입력 예시:
<!-- File input with a label -->
<label for="attach-file">{{ __('Attach a file') }}</label>
<input id="attach-file" type="file" />
<!-- File input with a hidden label -->
<label for="attach-file" class="gl-sr-only">{{ __('Attach a file') }}</label>
<input id="attach-file" type="file" />
접근 가능한 이름이 있는 이미지#
이미지 예시:
<img :src="https://docs.gitlab.com/imagePath" :alt="__('A description of the image')" />
<!-- SVGs implicitly have a graphics role so if it is semantically an image we should apply `role="img"` -->
<svg role="img" :alt="__('A description of the image')" />
<!-- A decorative image, hidden from screen readers -->
<img :src="https://docs.gitlab.com/imagePath" :alt="" />
설명적인 접근 가능한 이름이 있는 버튼과 링크#
버튼과 링크는 독립적으로 이해할 수 있을 만큼 설명적인 접근 가능한 이름을 가져야 합니다.
<!-- bad -->
<gl-button @click="handleClick">{{ __('Submit') }}</gl-button>
<gl-link :href="url">{{ __('page') }}</gl-link>
<!-- good -->
<gl-button @click="handleClick">{{ __('Submit review') }}</gl-button>
<gl-link :href="url">{{ __("GitLab's accessibility page") }}</gl-link>
Role#
일반적으로 role 사용을 피하세요.
대신 암묵적으로 role을 가진 시맨틱 HTML 요소를 사용하세요.
| 잘못된 방법 | 올바른 방법 |
|---|---|
<div role="button"> |
<button> |
<div role="img"> |
<img> |
<div role="link"> |
<a> |
<div role="header"> |
<h1> to <h6> |
<div role="textbox"> |
<input> or <textarea> |
<div role="article"> |
<article> |
<div role="list"> |
<ol> or <ul> |
<div role="listitem"> |
<li> |
<div role="table"> |
<table> |
<div role="rowgroup"> |
<thead>, <tbody>, or <tfoot> |
<div role="row"> |
<tr> |
<div role="columnheader"> |
<th> |
<div role="cell"> |
<td> |
키보드 전용 사용 지원#
키보드 사용자는 포커스 아웃라인에 의존하여 페이지에서 자신의 위치를 파악합니다. 따라서 요소가 인터랙티브한 경우 다음을 확인해야 합니다:
-
키보드 포커스를 받을 수 있어야 합니다.
-
가시적인 포커스 상태가 있어야 합니다.
이러한 동작을 기본으로 제공하는 a(GlLink) 및 button(GlButton)과 같은 시맨틱 HTML을 사용하세요.
다음 사항을 염두에 두세요:
-
Tab 및 Shift-Tab은 정적 콘텐츠가 아닌 인터랙티브 요소 간에만 이동해야 합니다.
-
:hover스타일을 추가할 때는 대부분의 경우:focus스타일도 추가해야 마우스 및 키보드 사용자 모두에게 스타일이 적용됩니다. -
인터랙티브 요소의
outline을 제거하면box-shadow와 같은 다른 방법으로 시각적 포커스 상태를 유지해야 합니다.
자세한 내용은 Pajamas 키보드 전용 페이지를 참조하세요.
tabindex#
다음 이유로 tabindex를 사용하지 않는 것을 권장합니다:
-
button(GlButton)과 같은 시맨틱 HTML을 사용하면 암묵적으로tabindex="0"이 제공됩니다. -
탭 순서는 시각적 읽기 순서와 일치해야 하며 양의
tabindex는 이를 방해합니다.
tabindex="0"으로 요소를 인터랙티브하게 만드는 것을 피하세요#
div 및 span 태그 대신 인터랙티브 요소를 사용하세요.
예를 들어:
마크업이 시맨틱적으로 완성되면 CSS를 사용하여 원하는 시각적 상태로 업데이트하세요.
<!-- bad -->
<div role="button" tabindex="0" @click="expand">Expand</div>
<!-- good -->
<gl-button class="gl-p-0!" category="tertiary" @click="expand">Expand</gl-button>
인터랙티브 요소에 tabindex="0"을 사용하지 마세요#
인터랙티브 요소는 이미 탭으로 접근 가능하므로 tabindex를 추가하는 것은 중복입니다.
<!-- bad -->
<gl-link href="help" tabindex="0">Help</gl-link>
<gl-button tabindex="0">Submit</gl-button>
<!-- good -->
<gl-link href="help">Help</gl-link>
<gl-button>Submit</gl-button>
스크린 리더가 읽을 요소에 tabindex="0"을 사용하지 마세요#
스크린 리더는 탭으로 접근할 수 없는 텍스트도 읽을 수 있습니다.
tabindex="0" 사용은 불필요하며 문제를 일으킬 수 있습니다.
스크린 리더 사용자는 그 요소와 상호작용할 수 있다고 기대하게 되기 때문입니다.
<!-- bad -->
<p tabindex="0" :aria-label="message">{{ message }}</p>
<!-- good -->
<p>{{ message }}</p>
양의 tabindex를 사용하지 마세요#
tabindex="1"
이상의 값은 항상 피하세요.
아이콘#
아이콘은 세 가지 유형으로 나눌 수 있습니다:
-
장식적인 아이콘
-
의미를 전달하는 아이콘
-
클릭 가능한 아이콘
장식적인 아이콘#
UI에서 아이콘을 제거했을 때 사용자가 정보를 잃지 않으면 장식적인 아이콘입니다.
GitLab 내 대부분의 아이콘은 장식적이므로, GlIcon은 렌더링된 아이콘을 스크린 리더로부터 자동으로 숨깁니다.
따라서 GlIcon에 aria-hidden="true"를 추가할 필요가 없으며, 이는 중복입니다.
<!-- unnecessary: gl-icon hides icons from screen readers by default -->
<gl-icon name="rocket" aria-hidden="true" />
<!-- good -->
<gl-icon name="rocket" />
정보를 전달하는 아이콘#
UI에서 아이콘을 제거했을 때 사용자가 정보를 잃으면 정보를 전달하는 아이콘입니다.
예를 들어, 이슈가 기밀임을 나타내는 기밀 아이콘이 있고 그 옆에 "Confidential"이라는 텍스트가 없는 경우가 있습니다.
정보를 전달하는 아이콘에는 스크린 리더 사용자에게도 정보가 전달될 수 있도록 접근 가능한 이름이 있어야 합니다.
<!-- bad -->
<gl-icon name="eye-slash" />
<!-- good -->
<gl-icon name="eye-slash" :aria-label="__('Confidential issue')" />
클릭 가능한 아이콘#
클릭 가능한 아이콘은 시맨틱적으로 버튼이므로, 접근 가능한 이름과 함께 버튼으로 렌더링해야 합니다.
<!-- bad -->
<gl-icon name="close" :aria-label="__('Close')" @click="handleClick" />
<!-- good -->
<gl-button icon="close" category="tertiary" :aria-label="__('Close')" @click="handleClick" />
요소 숨기기#
다음 표를 사용하여 적절한 경우 사용자로부터 요소를 숨기세요.
| 시각 장애가 없는 사용자에게 숨기기 | 스크린 리더에게 숨기기 | 시각 장애가 없는 사용자와 스크린 리더 모두에게 숨기기 |
|---|---|---|
| .gl-sr-only | aria-hidden="true" | display: none, visibility: hidden, or hidden attribute |
스크린 리더에서 장식적인 이미지 숨기기#
스크린 리더 사용자의 노이즈를 줄이려면 alt=""를 사용하여 장식적인 이미지를 숨기세요.
이미지가 인라인 SVG와 같이 img 요소가 아닌 경우, role="img"와 alt=""를 모두 추가하여 숨길 수 있습니다.
gl-icon 컴포넌트는 스크린 리더에서 아이콘을 자동으로 숨기므로 gl-icon을 사용할 때
aria-hidden="true"는 불필요합니다.
<!-- good - decorative images hidden from screen readers -->
<img src="https://docs.gitlab.com/development/fe_guide/accessibility/best_practices/decorative.jpg" alt="">
<svg role="img" alt="" />
<gl-icon name="work-item-epic" />
ARIA를 사용해야 하는 경우#
시맨틱 HTML을 사용할 때는 이미 접근성이 내장되어 있으므로 ARIA가 필요하지 않습니다.
그러나 시맨틱 HTML에 해당하는 것이 없는 UI 패턴이 있습니다. 일반적인 예로는 대화 상자(모달)와 탭이 있습니다. GitLab 특화 예로는 담당자와 라벨 드롭다운이 있습니다. 이러한 위젯을 구현하려면 스크린 리더가 이해할 수 있도록 ARIA가 필요합니다. WCAG 준수를 보장하기 위해 적절한 조사와 테스트를 수행해야 합니다.