본문 바로가기
Publish/accessibility

WAI-ARIA (웹접근성)

by 성젼이 2024. 10. 18.

참고 : https://jangkunblog.com/assets/file/2016.12.14-WAI-ARIA.pdf


1. 속성

aria-haspopup (팝업 유/무)

  • 값 : true / false
  • 다른 속성은 지원하지않는 브라우저 많다. 그렇기때문에 위 값 위주로 써줄것을 추천한다.

aria-current (현재 위치)

  • 선택된 메뉴와 같은 경우에 적용
  • 값: page(paging), *step(preocess), location, date, time, *true(tab), false(default)

aria-expanded (확장)

  • 값 : true(확장) / false(축소)
  • 아코디언이나 레이어팝업 열기/닫기 버튼

aria-controls="id" (제어하는 요소)

  • 현재 버튼이 제어하는 요소를 넣어주기
  • 레이어팝업 열기닫기 버튼 등, 아코디언에 사용한다.

aria-pressed (눌러진 상태)

  • 값: true(선택됨) / false(선택해제)
  • 즐겨찾기 버튼, 좋아요 버튼 등에 사용한다.

aria-checked (체크된 상태)

  • 값: true(선택) / false(선택해제)
  • pressed 와는 다른 속성이며 Input에 쓰이는 경우이다.

aria-live

  • 값 : polite(기본적으로 많이 쓰임) / * assertive(계속적으로 업데이트된 경우 알림)/off(안알림) / off (해제)
  • 사용자가 탐색 중인 페이지 위치와 상관없이 새롭게 업데이트된 정보(내용)를 사용자에게 즉시 알릴 필요가 있을 때 사용한다.
  • 페이지 네비게이션, 유효성 문구, alert notice 등에 사용한다.

aria-atomic

  • 값 : true / false
  • 라이브 영역 안에서 변경된 내용만을 읽을지(false), 변경된 내용을 포함한 전체 영역을 다시 읽을지(true) 설정할 때 사용하는 속성이다.

role=""

  • presentation : 태그가 가지고 있는 의미를 지움. (탭의 ul과 같은 경우)
  • none : 위와 같은 경우 때문에 쓰임
  • button : 버튼 태그가 아닌데 버튼 역할을 하는 경우
  • grid... 잘 안쓰임

2. WAI-ARIA 사용시 단점 및 기타

  • 속성을 사용하면서 마크업이 길어지기 때문에 CSS는 WAI-ARIA Selector로 제어 가능 (ie8부터 가능)
.clss[aria-selected] {}
  • 센스리더는 IE에서 WAI-ARIA 잘 지원 안함
  • 엔비디아 같은 경우 사용함
  • 죠스 + IE - 기준으로 WAI-ARIA 개발을 많이 한다.
  • nvde 크롬 (프리웨어)

위의 지원 상태는 2017년 기준임을 명시합니다.


3. UI 사용 (접근성 세미나 발췌)

Form 유효성

  • role="alert"
  • 위 속성이 IE10에서 안되므로 해당 속성 같이 쓸 것 aria-live="polite/*assertive/off"
  • aria-atomic="true/false" 변경된 내용 다 읽기 (true)
  • JS로 Input에서 Focus out시 WAI-ARIA 속성을 줄 것
<p role="alert" aria-live="assertive" aria-atomic="true">유효성 멘트</p>

페이지 네비게이션 (Page navigation)

주의! 📢

aria-live 속성을 고정으로 넣으면 자동 슬라이드 페이지 네비게이션의 경우 계속해서 소리가 나온다.

자동 슬라이드의 페이지의 경우 Focus 진입시만 assertive 값을 Focus가 없을땐 off로 값을 준다.

<ul>
	<li><a href="" aria-live="assertive">1</a></li>
	<li><a href="">2</a></li>
	<li><a href="">3</a></li>
</ul>

탭 (Tab)

  • ul에 넣는 속성 role="none" or role="presentation" (none의 속성의 경우 현재 베리데이션에 오류로 뜸, 두개 다 넣음)
  • li에 넣는 속성 role="presentation"
  • 탭 버튼은 a 에 role="tab", aria-controls="탭내용id"
  • guide 넣어주기 p#tabguide, ul[aria-describedby="tabguide"]
  • Tab Content 부분에 role="tabpanel"
  • 선택된 Tab a 에 aria-current="true"

레이어팝업 (Layer Popup)

  • Dimmed 될 내용에 aria-hidden="true" 적용
  • 레이어에 role="dialog" 속성을 넣어주고 팝업 오픈시 Focus 넘겨줄 것

GNB 열기/닫기 버튼

  • aria-label="menu" (메뉴를 뜻함)
  • aria-controls="주메뉴id" (열릴 메뉴 id)
  • aria-haspopup="true" (팝업 있음을 뜻함)
  • aria-expanded="true/false" (확장됨/안됨)
  • a의 경우 <a href="" role="button">주메뉴 열기/닫기</a>

4. WAI-ARIA UI 실무 적용

Mobile

닫기버튼과 같이 .blind .hidden (접근성 클래스) 속성에 font-size:0; line-height:0; opacity:0; width:0; height:0; 해당 할 경우, 쓰지말 것 (IOS 에서 못읽음)

PC

  • visibility: hidden; display: none; 위 속성 쓰지말 것
  • 과도한 text-indent:-999999999em 도 제외

tab-index

  • 키보드 포커스를 못받게 하는 요소는 tabindex="-1"
  • 키보드 포커스가 선형화 순서로 받는 요소는 tabindex="0"

gnb, lnb, snb (메뉴)

  • 메뉴 시작 ul에 role="tree", li 에 role="treeitem", 그 안의 소메뉴 ul에 role="group"
  • 소메뉴를 가진 li가 닫혀있을 경우 aria-expanded="false" (닫혀 있음을 뜻하며 JS로 변경 상태 변경해야한다)
<ul role="tree">
	<li role="treeitem">
		<a href="#" aria-controls="menu1" aria-expanded="false">메뉴1</a>

		<ul role="group" id="menu1">
			<li role="treeitem">소메뉴 1</li>
			<li role="treeitem">소메뉴 2</li>
		</ul>
	</li>
</ul>

gnb 열기/닫기 버튼

  • aria-label="menu", aria-controls="gnbId값", arai-haspopup="true"(팝업있음), aria-expanded="false/true"(열림/닫힘), role="button"
  • aria-label 사용 시 스크린리더에서 label 속성이 해당 요소의 텍스트보다 우위에 속해 텍스트를 읽지 않을 수 있기 때문에 해당 속성의 텍스트와 설명을 추가합니다.
  • aria-expanded 는 열림과 닫힘에 따라 JS로 처리 해주어야 한다.
<a href="#" aria-label="주메뉴 열기" aria-controls="gnb" arai-haspopup="true" role="button" aria-expanded="false">주메뉴 열기</a>
<button type="button" aria-label="주메뉴 열기" aria-controls="gnb" arai-haspopup="true" aria-expanded="false">주메뉴 열기</button>

<div id="gnb">
	주메뉴 내용
</div>

랜드마크 (role)

  • html5를 쓰기 때문에 아래 랜드마크는 쓰지 말 것 (스크린리더 중복 이유)
role="header"
role="banner"
role="navigation"
role="main"
role="form"

버튼 (Button)

  • 텍스트 버튼이 아닌 이미지 버튼의 경우 button이나, a에 aria-label 속성 넣어줄 것
  • aria-label 사용시 스크린리더에서 label 속성이 해당 요소의 텍스트보다 우위에 속해 텍스트를 읽지 않을 수 있기 때문에 해당 속성의 텍스트와 설명을 추가합니다.
<button type="button" aria-label="폼요소 추가">추가</button>

사이트 이동 경로 (Breadcrumb)

  • breadcrumb의 최상단에 aria-label="사이트 이동 경로" 속성 추가
  • 현재 페이지에 해당하는 요소에 aria-current="location" 속성 추가

FORM

검색

  • 검색 전체 영역에 role="search" 추가
<div class="search" role="search"></div>
  • 자동입력이 있는 경우 검색어 입력 인풋박스에 속성 추가
<input type="text" name="" id="" role="combobox" aria-autocomplete="list" aria-haspopup="true">
  • 상태 관련된 문구 추가 (-live, -relevant 속성은 role을 제대로 지원 안해주는 기기를 위해 보조 지원함)
<div id="status" class="blind" role="status" aria-live="polite" aria-relevant="additions">
	<div>10개의 추천 검색어가 있습니다.</div>
</div>
  • 자동입력 리스트에 role 추가 및 li에 ID값도 같이 추가한다. (해당 아이디 값은 키보드로 해당 값이 탐색될 경우 Input에 aria-activedescendant 속성의 값으로 ID값을 넣어준다.)
<ul role="listbox">
	<li id="opt1" role="option"><a href="">글로벌 테이션</a></li>
	<li id="opt2" role="option"><a href="">글로벌 테이션</a></li>
</ul>

필수 입력 요소

  • 속성 : aria-required="true" (필수 요소)
<input type="text" aria-required="true" title="입력">

유효성 문구

  • 유효성 문구에 div로 작업 후 해당 div에 아래 속성을 추가한다.
  • role="alert", arie-live="assertive"(업데이트시 즉시 알림), aria-atomic="true"(업데이트 내용만 읽음)
<div role="alert" aria-live="assertive" aria-atomic="true">유효성 멘트</div>

폼 요소 추가 설명 문구

비밀번호와 같은 추가 설명이 있는 문구에는 ID추가와 해당 Form요소에는 aria-describedby="설명아이디값" 속성 추가한다.

<input type="password" aria-describedby="desc">
<p id="desc">비밀번호는 숫자 네자리로 입력하시오.</p>

전화번호나, 이메일 Input

  • 폼은 나눠져있으나 label이 하나인 경우 label보단 title 속성을 기입해준다.
  • 현재 label 태그가 있는 경우는 그대로 두고 새로 만들어지는 것에 대하여는 label이 아닌 title모두 공통 대체한다 (코드의 공통화를 위해)
<input type="text" name="" id="" title="지역번호 입력">
<input type="text" name="" id="" title="국번 3자리 입력">
<input type="text" name="" id="" title="끝 4자리 입력">

radio 또는 checkbox 가 그룹일 경우

상단에 해당 그룹을 묶는 속성을 추가한다 role="radiogroup", role="group"

<!-- radio 묶음에는 radiogroup -->
<ul role="radiogroup">
	<li><input type="radio" name="" id=""></li>
	<li><input type="radio" name="" id=""></li>
	<li><input type="radio" name="" id=""></li>
</ul>

<!-- checkbox 묶음에는 group -->
<ul role="group">
	<li><input type="checkbox" name="" id=""></li>
	<li><input type="checkbox" name="" id=""></li>
	<li><input type="checkbox" name="" id=""></li>
</ul>

LAYERPOPUP

  1. 레이어팝업을 오픈하는 버튼에 속성 추가 aria-haspopup="true", aria-expanded="false"
<button type="button" aria-haspopup="true" aria-expanded="false" aria-controls="popup">주메뉴 열기</button>
<a href="#popup" aria-haspopup="true" aria-expanded="false" aria-controls="popup">주메뉴 열기</a>
  1. 레이어팝업에 속성 추가 role="dialog"
<div id="popup" role="dialog" aria-labelledby="testPopTit">
	<h2 id="testPopTit">팝업 헤딩</h2><!-- // 헤딩 단계는 h2부터 시작 -->

	레이어팝업 내용 ...
</div>

TAB

탭 - 내용 - 탭 - 내용 (순서 선형화 일 경우)

<ul class="tab" role="tablist">
	<li role="presentation">
		<a href="#tabcont1" id="tab1" role="tab" aria-controls="tabcont1" aria-selected="true">탭명1</a>
		<div id="tabcont1" role="tabpanel">
			탭내용1
		</div>
	</li>
	<li role="presentation">
		<a href="#tabcont2" id="tab2" role="tab" aria-controls="tabcont2">탭명2</a>
		<div id="tabcont2" role="tabpanel">
			탭내용2
		</div>
	</li>
</ul>

탭 탭 탭 - 내용 내용 내용

  • tab menu를 감싸는 요소에 role="tablist" 추가
  • tab menu당 role="tab" aria-controls="각탭내용아이디값"
  • tab menu li 에는 role="presentation" 추가 (li 의미 무효화)
  • 선택된 tab menu 에 aria-selected="true" 추가 (js로 동적 변경)
  • tab content에 각 id 부여 및 role="tabpanel" 요소 추가
<ul role="tablist">
	<li role="presentation"><a href="#tabcont1" role="tab" aria-controls="tabcont1" aria-selected="true">탭명1</a></li>
	<li role="presentation"><a href="#tabcont2" role="tab" aria-controls="tabcont2">탭명2</a></li>
	<li role="presentation"><a href="#tabcont3" role="tab" aria-controls="tabcont3">탭명3</a></li>
</ul>

<div id="tabcont1" role="tabpanel">탭내용1</div>
<div id="tabcont2" role="tabpanel">탭내용2</div>
<div id="tabcont3" role="tabpanel">탭내용3</div>

탭 탭 탭 - 내용 (ajax)

  • tab menu를 감싸는 요소에 role="tablist" 추가
  • tab menu당 role="tab" aria-controls="각탭내용아이디값"
  • tab menu li 에는 role="presentation" 추가 (li 의미 무효화)
  • 선택된 tab menu 에 aria-selected="true" 추가 (js로 동적 변경)
  • tab content에 각 id 부여 및 role="tabpanel" 요소 추가
<ul role="tablist">
	<li role="presentation"><a href="#tabcont" role="tab" aria-controls="tabcont" aria-selected="true">탭명1</a></li>
	<li role="presentation"><a href="#tabcont" role="tab" aria-controls="tabcont">탭명2</a></li>
	<li role="presentation"><a href="#tabcont" role="tab" aria-controls="tabcont">탭명3</a></li>
</ul>

<div id="tabcont" role="tabpanel">
	ajax 탭내용
</div>

탭 탭 탭 - 내용 (lnk 이동)

  • tab menu를 감싸는 요소에 role="tablist" 추가
  • tab menu당 role="tab" aria-controls="각탭내용아이디값"
  • tab menu li 에는 role="presentation" 추가 (li 의미 무효화)
  • 선택된 tab menu 에 aria-selected="true" 추가 (js로 동적 변경)
  • tab content에 각 id 부여 및 role="tabpanel" 요소 추가
<ul role="tablist">
	<li role="presentation"><a href="#" role="tab" aria-controls="tabcont" aria-selected="true">탭명1</a></li>
	<li role="presentation"><a href="#" role="tab">탭명2</a></li>
	<li role="presentation"><a href="#" role="tab">탭명3</a></li>
</ul>

<div id="tabcont" role="tabpanel">
	ajax 탭내용
</div>

페이지 네비게이션 (Page Navigation)

<div role="navigation" aria-label="페이지 선택">
	<ol>
		<li> <a href="#" aria-live="assertive" aria-current="page"> <span class="blind">현재페이지</span> <span>1</span> </a> </li>
		<li> <a href="#" aria-live="assertive"> <span>2</span> </a> </li>
		<li> <a href="#" aria-live="assertive"> <span>3</span> </a> </li>
		<li> <a href="#" aria-live="assertive"> <span>4</span> </a> </li>
		<li> <a href="#" aria-live="assertive"> <span>5</span> </a> </li>
	</ol>
</div>

아코디언

  • 아코디언 제목 영역이 a 태그일 경우는, role="button" 추가.
  • aria-expanded는 내용 영역에 따른 동적 변경이 가능하게 해야함. (확장/비확장)
  • 추가로 내용 영역에 aria-labelledby="제목 아이디값" 제목에 id 속성을 줘서 더 자세히 연결할 수도 있다.
<h3><button type="button" aria-controls="accoCont" aria-expanded="false">아코디언 제목</button></h3>

<div id="accoCont">
	아코디언 내용
</div>