ARIA

Jung taeWoong·2021년 9월 4일
4

웹 접근성

목록 보기
2/2
post-thumbnail

ARIA

  • Accessible Rich Internet Application
  • 접근 가능한 고기능 인터넷 애플리케이션
  • HTML의 접근성 문제를 보완하는 W3C 명세
  • HTML에 '역할(roles), 상태(states), 속성(properties)' 정보를 부여하여 보조기기의 웹 문서 접근을 지원
  • 장애인 사용자들이 웹 문서를 좀더 생동감있게 이해하고 사용하는데 도움을 준다.

접근성 좋은 IT 서비스는 현실 세계를 보다 더 자유롭게 누릴 수 있도록 한다.

Return to HTML

  • 웹 접근성 문제의 80%는 HTML
  • 대부분의 WAI-ARIA 명세는 HTML 요소와 속성을 흉내내는 것
  • ARIA를 사용하기에 앞서 HTML을 의미있게 사용했는지 검토할것

역할(Roles)

<element role="tablist"><element role="tab"><element role="tabpanel"><element role="tooltip"><element role="status"><element role="alert"><element role="alertdialog"> == <dialog>
<element role="dialog"> == <dialog>
<element role="navigation"> == <nav>
<element role="complementary"> == <aside>
<element role="none"> == <div>

role="tablist|tab|tabpanel"

  • 탭 스타일을 의미하는 것이 아님
    • 현재 페이지 내용에 색인을 제공하는 구조(tablist, tab, tabpanel)를 의미
  • 사이트 탐색 도구에 해당하는 요소는 nav > h2 + ul 또는 aside > h2 + ul 구조로 마크업

  • tablist: 하나 하나의 tab들을 Grouping 역할
  • tab: 말그대로 tab 역할
  • tabpanel: tab 아래에 표시하는 콘텐츠

예시

<div class="weekly">
  <div role="tablist">
    <button id="mon-anchor" aria-controls="mon" role="tab" aria-selected="true"></button>
    <button id="tue-anchor" aria-controls="tue" role="tab" ></button>
  </div>
  <div id="mon" tabindex="0" role="tabpanel" aria-labelledby="mon-anchor">
    월요일 컨텐츠
  </div>
  <div id="tue" tabindex="0" role="tabpanel" aria-labelledby="tue-anchor">
    화요일 컨텐츠
  </div>
</div>

role="tooltip"

  • 보통 포커스를 받으면 설명을 표시하는 문맥 팝업
  • 툴팁은 포커스 받지 않아야 한다. ESC 또는 마우스를 빼면 사라져야 한다.
  • 참조하는 컨트롤(a, button)에는 aria-describedby="ID reference list" 속성으로 연결

"ID reference list"
여러개의 아이디 값 목록을 공백으로 분리해서 연결

예시

<!-- O: 인풋 툴팁 -->
<label for="tel">전화번호</label>
<input id="tel" type="tel" aria-describedby="TIP-TEL">
<p id="TIP-TEL" role="tooltip" hidden>하이픈(-) 없이 숫자만 입력.</p>

<!-- O: 버튼 퉅립 -->
<button aria-describedby="TIP-DEL">게시물 삭제</button>
<p id="TIP-DEL" role="tooltip" hidden>게시물 삭제 후 복원할 수 없음</p>

role="status"

  • 실시간 결과 정보. role="alert" 만큼 중요하지 않음
  • 이 요소를 갱신할 때 포커스를 받지 않아야 한다.
  • 이 역할을 선언하면 자동으로 aria-live="polite", aria-atomic="true" 속성이 할당됨

aria-live="polite"
보조기기는 현재 전달하는 음성이나 내용을 중단하지않고 기다렸다가 그 음성 낭독이 끝나면 현재 설명하려고하는 내용을 음성으로 전달
aria-atomic="true"
내용이 갱신되었을 때 부분적으로 갱신되었다하더라도 atomic="true" 영역 전체를 다시 읽어줌

예시

  • toast popup 메시지에 사용하자
  • 의미론에 따라 role="status" 대신 <output>요소 사용 가능
<!-- O: 결과 메시지 -->
<p role="status">회원가입 양식 전송완료.</p>
<p role="status">10개의 검색 결과.</p>
<p role="status">장바구니에 5개의 항목</p>

<output>회원가입 양식 전송완료.</output>
<output>10개의 검색 결과.</output>
<output>장바구니에 5개의 항목.</output>

role="alert"

  • 시간에 민감하고 중요한(오류, 제안) 실시간 콘텐츠
  • 이 요소를 갱신할 때 포커스를 받지 않아야 한다.
  • aira-live="assertive" 속성과 aria-atomic="true" 속성 자동 할당

aria-live="asertive""
굉장히 긴급한 메시지기에 현재 진행중이던 과업, 음성 낭독을 중단하고 그 즉시 오류 내용을 사용자에게 알림

예시

  • 무언가 실패했을때 혹은 시기적으로 민감한 상태였을때 alert 사용
<!-- O: 오류 메시지 -->
<p role="alert">우편번호 입력 오류.</p>

<!-- O: 제안 메시지 -->
<p role="alert">로그인 후, 이용 가능.</p>

상태(States)

<element aria-current="">
<!-- value: page|step|location|date|time|true|false(default) -->
<element aria-selected="">
<!-- value: true|false|undefined(default) -->
<element aria-haspopup="">
<!-- value: true|menu|dialog|listbox|tree|grid|false(default)-->
<element aria-expanded="">
<!-- value: true|false|undefined(default) -->
<element aria-hidden="">
<!-- value: true|false|undefined(default) -->
<element aria-invalid="">
<!-- value: true|false(default)|grammar|spelling -->

aria-current

value
page | step | location | date | time | true | false(default)

현재 맥락과 일치하는 항목을 의미 (보통 a, button에 사용)

  • page: 현재 '페이지'와 일치하는 시각적으로 강조한 링크
  • step: 현재 '단계'와 일치하는 시각적으로 강조한 링크
  • location: 플로우 차트에서 현재 '위치'와 일치하는 시각적으로 강조한 이미지
  • date: 달력에서 현재 '날짜'와 일치하는 날짜
  • time: 시간표에서 현재 '시간'과 일치하는 시간
  • true: 항목이 세트 내 현재 맥락과 일치함
  • false(default): 항목이 세트내 현재 맥락과 일치하지 않음. 속성 또는 값을 선언하지 않은 경우 초기값

예시

<!-- O: 현재 페이지 링크 -->
<nav>
  <h2>글로벌 네비게이션</h2>
  <ul>
    <li><a href="/home" aria-current="page"></a></li>
    <li><a href="/">연재</a></li>
    <li><a href="/">랭킹</a></li>
  </ul>
</nav>

<!-- O: 현재 단계 링크 -->
<nav>
  <h2>회원 가입</h2>
  <ol>
    <li><a href="/accept-terms" aria-current="step">약관 동의</a></li>
    <li><a href="/id-password">아이디/비밀번호 생성</a></li>
    <li><a href="/email-authentication">이메일 인증</a></li>
  </ol>
</nav>

aria-selected

value
true | false | undefined(default)

단일 또는 다중 선택이 가능한 요소(role="gridcell|option|row|tab")에 선택 상태를 명시하는 의미
role="tab" 요소에 가장 흔히 사용
키보드 포커스를 받을 수 있는 요소(a, button)에 적용

  • undefined(default): 속성 또는 값을 선언하지 않은 경우 초기값. 선택할 수 없음
  • true: 선택 가능한 요소를 선택했음
  • false: 선택 가능한 요소를 선택하지 않았음

예시

<!-- O: role="tab" 요소에 선택 상태를 명시 -->
<div role="tablist">
  <a id="mon-anchor" href="#mon" role="tab" aria-selected="true"></a>
  <a id="tue-anchor" href="#tue" role="tab" aria-selected="false"></a>
</div>
  • 선택된 요소만 스타일링을 다르게 할때도 적용하기 쉬움
[aria-selected="true"] {
...
}

aria-haspopup

value
true | menu | dialog | listbox | tree | grid | false(default)

보통 a, button 요소에 사용
요소에 연결되어 있는 팝업(메뉴, 대화상자 등) 정보를 제공
팝업 유형은 menu, list, tree, grid, dialog 으로 제한
일반적으로 menu와 dialog 유형이 빈번

  • true: menu와 동일한 의미
  • menu: menu(role) 팝업이 연결됨, menu(role)는 링크 목록
  • dialog: dialog(role) 팝업이 연결됨. dialog(role)는 상호작용 요소(버튼 또는 컨트롤)가 포함된 현재 문서의 하위창
  • listbox: listbox(role) 팝업이 연결됨. listbox(role)는 선택 가능한 option(role)을 포함한 콤보박스
  • tree: tree(role) 팝업이 연결됨. tree(role)는 하위 list(role)를 포함하며 접고 펼칠 수 있음
  • grid: grid(role) 팝업이 연결됨. grid(role)는 행과 열로 구성된 선택 가능한 위젯. 상호작용 가능한 셀이기 때문에 table(role)과는 역할이 다름에 유의
  • false(default): 연결된 팝업이 없음을 의미

예시

<!-- O: aria-haspopup="menu|true" -->
<button type="button" id="menu-button" aria-haspopup="menu" aria-control="menu-list" aria-expanded="false">메뉴</button>
<ul id="menu-list" role="menu" aria-labelledby="menu-button" hidden>
  <li><a href="/compoleted">완결</a></li>
</ul>

<!-- O: aria-haspopup="dialog" -->
<a href="#login-dialog"  aria-haspopup="dialog">로그인</a>
<section id="login-dialog" role="dialog" aria-labelledby="login-heading" aria-modal="true" hidden>
  <h2 id="login-heading">로그인</h2>
  ...
</section>

aria-expanded

value
true | false | undefined(default)

제어 대상의 확장 또는 축소 상태
보통 a, button 요소에 사용
aria-controls 속성을 이용하여 제어 대상을 명시
툴팁(role="tooltip"), 알럿(role="alert"), 알럿 대화상자(role="alertdialog"), 대화상자(role="dialog")와 같이 동적으로 표시 상태를 결정(토글)하는 요소에 사용

  • true: 요소 또는 제어 대상 확장 상태
  • false: 요소 또는 제어 대상 축소 상태
  • undefined(default): 속성 또는 값을 선언하지 않은 경우 초기값. 제어 대상이 없거나 모두 확장 상태. 확장/축소 제어 불가능

예시

<!-- O: 아코디언 -->
<dt>
  <button type="button" aria-controls="anwer-99" aria-expanded="false">보너스 코인은 언제 소진되나</button>
</dt>
<dd id="answer-99" hidden>
  <p>만료기한이 짧은 보너스 코인이 일반 코인보다 먼저 소진된다.</p>
</dd>

<!-- O: 팝업 -->
<a id="popular-btn" href="#popular" aria-haspopup="menu" aria-expanded="false">인기</a>
<ul id="popular" role="menu" aria-labelledby="popular-btn" hidden>
  <li><a href="#romance">로맨스</a></li>
</ul>

aria-hidden

value
true | false | undefined(default)

접근성 API(보조기기 접근 가능성) 차단 상태를 결정
예를 들면 모달 대화상자를 화면에 표시할 때 모달 대화상자 뒤 본문 콘텐츠에 aria-hidden="true" 속성을 선언하면 보조기기가 무시.

  • true: 접근성 API 차단.(화면 표시 여부와 무관한 API 차단)
  • false: 접근성 API 사용.(화면에 표시한 경우 API 사용)
  • undefined(default): 속성 또는 값을 선언하지 않을 경우 초기값. 화면 표시여부에 따라 접근성 API 차단 상태를 결정. 화면에 표시하면 false, 화면에 숨기면 true
예시
<!-- O: 모달 윈도우를 표시할 때 다른 요소를 차단 -->
<body>
  <div class="container" aria-hidden="true">
    // 보조기기가 무시하는 영역
  </div>
  <div role="alertdialog" aria-modal="true" aria-labelledby="TITLE" aria-describedby="DESCRIPTION">
    <h2 id="TITLE">레진패스 안내</h2>
    <p id="DESCRIPTION">이 작품의 유료 에피소드 열람 시 자동으로 구매합니다. 레진패스를 적용하시겠습니까?</p>
    <button type="button">레진패스 적용</button>
    <button type="button">취소</button>
  </div>
</body>

aria-invalid

value
true | false(default) | grammar | spelling

주로 <input> 요소에 선언
사용자가 입력한 값이 요구하는 형식과 일치하는지 여부를 나타낸다.
aria-errormessage 속성과 함꼐 사용하여 오류 설명을 제공

  • false(default): 오류 없음. aria-invalid 속성을 선언하지 않거나 갑싱 없으면 false로 간주
  • true: 오류 있음
  • grammar: 문법 오류
  • spelling: 철자 오류

예시

<!-- O: 입력 값이 유효하면 aria-invalid 속성을 생략 -->
<!-- O: 입력 값이 오류이면 aria-invalid="true" 속성을 선언 -->

<label for="email">이메일</label>
<input id="email" type="email" required value="..." aria-invalid="true" aria-errormessage="email-error-msg">
<p id="email-error-msg" aria-role="alert">이메일 형식이 유효하지 않음. 앳(@)과 마침표(.)를 포함해 주세요.</p>

속성(properties)

<element aria-controls="ID refernce list"><element aria-live="polite|assertive|off(default)"><element aria-labelledby="ID refernce list"><element aria-label="string">
<element aria-describedby="ID refernce list">
<element aria-errormessage="ID refernce list"><element aria-modal="true|false(default)">

aria-controls

  • 현재 요소가 제어하는 대상을 명시
  • 주로 role="tab", aria-haspopup, aria-expanded 속성과 함꼐 a, button 요소가 무엇을 제어하는지 명시
  • 값은 하나 이상의 ID 참조. 값이 여럿인 경우 공백으로 분리

예시

<!-- O: role="tab" 요소에 aria-controls 속성 사용 -->
<button type="button" id="mon-anchor" aria-controls="mon" role="tab" aria-selected="true"></button>

<!-- O: aria-haspopup 속성과 함께 aria-controls 속성 사용 -->
<button type="button" aria-haspopup="dailog" aria-controls="login-dialog">로그인</button>

<!-- O: aria-expanded 속성과 함께 aria-controls 속성 사용 -->
<button type="button" aria-controls="answer-99" aria-expanded="false">보너스 코인은 언제 소진되나요?</button>

aria-live

value
polite | assertive | off(default)

실시간으로 내용을 갱신하는 영역
갱신 영역에 polite, assertive값을 사용하면 갱신 순간 보조 기기가 사용자에게 내용을 전달

  • polite: 중요도가 낮은 내용에 사용, 현재 진행중인 음성 또는 타이핑을 방해하지 않고 뒤늦게 전달
  • assertive: 중요도가 높은 내용에 사용하여 현재 진행중인 보조기기 작업을 중단하고 갱신 내용을 즉시 사용자에게 전달

aria-labelledby

  • 간결한 설명 참조
  • ID(s) 값을 이용하여 내용을 참조(연결)
  • 보통 hx, a, button 요소를 참조하면 적절
  • aria-label 속성과 함계 선언하는 경우, aria-labelledby 속성이 우선순위가 높음
  • W3C는 aria-label 보다는 aria-labelledby 쓰는것을 권장
    • aria-label은 화면에 설명 텍스트를 노출하는 방식이 아니기 때문
  • <label> 를 이용해 <input>에 설명을 제공하는것과 같은 역할이라 보면됨

예시

  • 이 내용에 포커스를 받았을 때 텍스트가 전달됨
<!-- O: 헤딩 설명 참조 모범사례 👏 --> 
<section aria-labelledby="LZ-PATH" hidden>
  <h2 id="LZ-PATH">레진패스란?</h2>
  <p>이 작품의 유료 에피소드 열람시 자동으로 구매함</p>
</section>

<!-- O: 링크 설명 참조 -->
<a id="LZ-PATH" href="#LZ-PATH-TEXT">레진패스란?</a>
<div id="LZ-PATH-TEXT" aria-labelledby="LZ-PATH" hidden>
  <p>이 작품의 유료 에피소드 열람시 자동으로 구매함</p>
</div>

aria-label

  • '간결한' 설명(string)을 직접 제공
  • 가능한 aria-labelledby 속성을 권장.
  • 설명할 다른 참조(연결)요소가 없는 경우 사용

예시

<!-- O: 참조할 설명이 없는 경우 -->
<form>
  <input type="search" aria-label="웹툰 검색">
  <button> 검색 </button>
</form>

aria-describedby

  • 자세한 설명 참조
  • ID(s)값을 이용하여 '상세한' 내용을 참조(연결)
  • 주로 툴팁, 링크(a), 폼 컨트롤, 알럿, 알럿 대화상자 요소에 사용하면 적절

예시

<!-- O: 버튼 요소에 상세한 설명 제공 -->
<button aria-describedby="TIP-DEL">게시물 삭제</button>
<p id="TIP-DEL" role="tooltip" hidden>게시물 삭제 후 복원할 수 없음</p>

<!-- O: 알럿 대화상자 요소에 상세한 설명 제공 -->
<div role="alertdialog" aria-modal="true" aria-labelledby="TITLE" aria-describedby="DESCRIPTION">
  <h2 id="TITLE">레진패스 안내</h2>
  <p id="DESCRIPTION">이 작품의 유료 에피소드 열람시 자동으로 구매합니다 레진패스를 적용하시겠습니까?</p>
  <button type="button">레진패스 적용</button>
  <button type="button">취소</button>
</div>

aria-errormessage

  • 오류 메시지 참조, 주로 <input> 요소에 선언
  • aria-invalid="true" 속성을 활성하면 보조기기는 aria-errormessage 속성이 참조하는 내용을 오류 메시지로 전달
  • 오류 메시지는 '오류 원인과 해결 방법'을 포함

aria-modal

value
true | false(default) |

요소가 모달인지 여부를 보조기기에 전달
보통 role="alertdialog" 또는 role="dialog"와 함께 사용

  • false(default): 속성 또는 값을 선언하지 않은 경우 초기값. 모달 콘텐츠 아님
  • true: 모달 콘텐츠

사용할 수 없는 요소에 aria-hidden="true" 속성을 선언해서 보조기기가 무시하도록 설정. 포인팅 기능도 차단하도록 처리

profile
Front-End 😲

0개의 댓글