WAI-ARIA를 반영하여 접근성을 향상시킨 UI 컴포넌트 제작

— 아코디언 컴포넌트 편

아코디언 컴포넌트

패널 섹션(Panel Section) 영역을 펼침/감춤 처리하는 컴포넌트를 말합니다.

일반적으로 수직 방향으로 겹쳐진 요소들의 집합을 말하며, 각 헤더 레이블을 클릭하면
패널 섹션은 펼침되거나 접힘되어 토글 됩니다. 웹/앱 페이지에 하나 이상의 섹션 콘텐츠를
표시하고자 할 때, 협소한 공간을 효율적으로 활용하기 위해 사용 되는 UI 컴포넌트 입니다.

아코디언 컴포넌트를
구성하는 기본 구조

연관된 섹션 콘텐츠를 펼치거나, 접는 역할을 수행합니다.

아코디언 헤더(Accordion Header)

아코디언 헤더와 연관된 섹션 콘텐츠입니다.

아코디언 패널(Accordion Panel)

중첩된 아코디언 컴포넌트

경우에 따라서는 중첩된 아코디언 컴포넌트 디자인이 필요한 경우도 있습니다.
 

웹사이트 좌측 메뉴 예시는 중첩된 형태로 섹션 콘텐츠를 펼치거나 접을 수 있습니다.
가급적 중첩된 형태가 아닌 단순한 형태의 아코디언이 권장되지만, 기획에 따라 중첩된
아코디언을 사용해야 할 경우도 있습니다.

아코디언 컴포넌트
접근성 분석

국내 기업 사이트에 사용된
아코디언 컴포넌트

서브 아코디언을 중첩하여 포함하는 아코디언 컴포넌트 입니다.
웹사이트가 WA 인증마크를 획득한 만큼 키보드 접근/조작하는데 문제가 없습니다.
텍스트 콘텐츠로 각 항목을 제공되고 있어 스크린리더 사용자도 듣고 이해하는데 문제 없습니다.

다만, 접근성을 최소한 수준으로 고려한 것으로 접근성을 최상으로 끌어올렸다 볼 수는 없습니다.
이와 같은 주장에 대한 이유를 살펴보면서 접근성을 향상시키는 방법에 대해 이야기 해봅시다.

<div class="box">
  <button class="btn_close" type="button">전체메뉴 닫기</button>
  <ul>
    <li class="">...</li>

    <li class="current">
      <a href="javascript:;"><span>투자정보</span></a>
      <div class="sub_menu" style="display: block;">
        <div>
          <div class="inner">
            <ul style="display: block;">
              <li>
                <a href="javascript:;"><span>재무정보</span></a>
                <ul style="display: none;">...</ul>
              </li>
              <li>
                <a href="javascript:;"><span>공시정보</span></a>
                <ul style="display: block;">
                  <li>
                    <a href="..." target="_blank" title="새 창 열림"><span>공시자료</span></a>
                  </li>
                  <li><a href="..."><span>공시정보관리규정</span></a></li>
                  <li><a href="..."><span>전자공고</span></a></li>
                </ul>
              </li>
              <li>
                <a href="javascript:;"><span>IR자료실</span></a>
                <ul style="display: none;">...</ul>
              </li>
            </ul>
          </div> <!--/ .inner -->
        </div>
      </div> <!--/ .sub_menu -->
    </li>
  </ul>
  <button class="btn_close" type="button">전체메뉴 닫기</button>
</div> <!--/ .box -->

box?

sub_menu?

inner?

목록, 목록 아이템?

링크?

"목록 안에 링크가 있구나. 그런데 링크를 클릭 하니 안에 링크가 또 있네?"

국외 아코디언 컴포넌트

모바일 퍼스트, 반응형 웹에 적용 가능한 아코디언 컴포넌트 모듈입니다.
개발 시간이 부족하거나 직접 개발이 가능하지 않을 경우, 배포된 오픈 소스 코드를
빈번하게
사용하는데 아쉽게도 접근성을 고려하지 않은 경우가 많습니다. 마우스를 사용할 수 없는
사용자의 경우, 컴포넌트에 접근/조작할 수 없습니다.

하지만, 앞서 다룬 국내 사례와 달리 HTML 마크업 구조는 눈여겨 볼만 합니다.

<div class="bellows">
  <div class="bellows__item bellows--is-open">
    <div class="bellows__header">
      <h3>Tab 1</h3>
    </div>
    <div class="bellows__content-wrapper" style="display: block;">
      <div class="bellows__content">
        <p>Lorem honeyed locusts sit amet, none...</p>
      </div>
    </div>
  </div>
  <div class="bellows__item">
    <div class="bellows__header">
      <h3>Tab 2</h3>
    </div>
    <div class="bellows__content-wrapper" style="display: none;">
      <div class="bellows__content">...</div>
    </div>
  </div>
</div>

component

component item

component header

component content

component state

아코디언 컴포넌트 접근성 향상을 위한 WAI-ARIA 디자인패턴

W3C, WAI-ARIA
아코디언 컴포넌트

W3C에 의해 국제 표준으로 제정된 WAI-ARIA 기술이 반영된
아코디언 컴포넌트 Authoring Practice Example을 분석하면서
접근성 향상을 위한 디자인패턴을 공부해 봅시다!

<!-- 아코디언 컴포넌트 -->
<div class="y9-accordion">

  <!-- 아코디언 아이템 -->
  <div class="y9-accordion__item">
    <!-- 아코디언 헤더 -->
    <div class="y9-accordion__heading">
      <!-- 아코디언 헤더 버튼 -->
      <a href class="y9-accordion__button">아코디언 헤더</a>
    </div>
    <!-- 아코디언 패널 -->
    <div class="y9-accordion__panel">
      아코디언 패널
    </div>
  </div>

  <div class="y9-accordion__item">
    <div class="y9-accordion__heading">
      <a href class="y9-accordion__button">아코디언 헤더</a>
    </div>
    <div class="y9-accordion__panel">
      아코디언 패널
    </div>
  </div>

  <div class="y9-accordion__item">
    <div class="y9-accordion__heading">
      <a href class="y9-accordion__button">아코디언 헤더</a>
    </div>
    <div class="y9-accordion__panel">
      아코디언 패널
    </div>
  </div>

</div>

Accordion Component
HTML Markup

accordion

accordion item

accordion header

accordion button

accordion panel

<!-- 아코디언 컴포넌트 -->
<div class="y9-accordion" role="presentation">

  <!-- 아코디언 아이템 -->
  <div class="y9-accordion__item">
    <!-- 아코디언 헤더 -->
    <div class="y9-accordion__heading" role="heading" aria-level="3">
      <!-- 아코디언 헤더 버튼 -->
      <a href class="y9-accordion__button" role="button">아코디언 헤더</a>
    </div>
    <!-- 아코디언 패널 -->
    <div class="y9-accordion__panel" role="region">
      아코디언 패널
    </div>
  </div>

  <div class="y9-accordion__item">
    <div class="y9-accordion__heading" role="heading" aria-level="3">
      <a href class="y9-accordion__button" role="button">아코디언 헤더</a>
    </div>
    <div class="y9-accordion__panel" role="region">
      아코디언 패널
    </div>
  </div>

  <div class="y9-accordion__item">
    <div class="y9-accordion__heading" role="heading" aria-level="3">
      <a href class="y9-accordion__button" role="button">아코디언 헤더</a>
    </div>
    <div class="y9-accordion__panel" role="region">
      아코디언 패널
    </div>
  </div>

</div>

Accordion Component
WAI-ARIA Roles

HTML 요소의 본래 역할을 '표현' 역할로 변경.

아코디언 헤더(레벨3) 역할 설정.

아코디언 헤더 버튼 역할 설정.

아코디언 패널 영역 역할 설정.

W3C, WAI-ARIA
아코디언 컴포넌트 역할 정리

아코디언 헤더 (Accordion Header)는 연결된
패널 (Accordion Panel)의 레이블 (Label) 역할
을 수행합니다.

아코디언 헤더 버튼은 연결된 패널을 토글(펼침/접힘) 합니다.

HTML에서 제공하는 기본 제목(h3), 버튼(button) 요소를 사용하지 않을 경우,
제목 역할에 role="heading"aria-level="3"을, 버튼 역할에
role="button"
속성을 추가해야 합니다.

아코디언 헤더는 내부에 버튼 요소 하나만 포함해야 합니다.

Accordion Component
HTML Native Element

기본 제공되는 HTML 제목 요소를 사용한다면,

WAI-ARIA Role 속성을 사용하지 않을 수 있습니다. (권장)

<!-- 아코디언 컴포넌트 -->
<div class="y9-accordion" role="presentation">

  <!-- 아코디언 아이템 -->
  <div class="y9-accordion__item">
    <!-- 아코디언 헤더 -->
    <h3 class="y9-accordion__heading">
      <!-- 아코디언 헤더 버튼 -->
      <button type="button" class="y9-accordion__button">아코디언 헤더</button>
    </h3>
    <!-- 아코디언 패널 -->
    <div class="y9-accordion__panel" role="region">
      아코디언 패널
    </div>
  </div>

  <div class="y9-accordion__item">
    <h3 class="y9-accordion__heading">
      <button type="button" class="y9-accordion__button">아코디언 헤더</button>
    </h3>
    <div class="y9-accordion__panel" role="region">
      아코디언 패널
    </div>
  </div>

  <div class="y9-accordion__item">
    <h3 class="y9-accordion__heading">
      <button type="button" class="y9-accordion__button">아코디언 헤더</button>
    </h3>
    <div class="y9-accordion__panel" role="region">
      아코디언 패널
    </div>
  </div>

</div>

기본 제공되는 HTML 버튼 요소를 사용하면,

WAI-ARIA Role 속성을 사용하지 않습니다. (권장)

<!-- 아코디언 아이템 -->
<div class="y9-accordion__item">
  <!-- 아코디언 헤더 -->
  <h3 class="y9-accordion__heading">
    <!-- 아코디언 헤더 버튼 -->
    <button
      type="button"
      class="y9-accordion__button"
      aria-controls="y9-accordion__panel-1"
      id="y9-accourdon__button-1">아코디언 헤더</button>
  </h3>
  <!-- 아코디언 패널 -->
  <div
    class="y9-accordion__panel"
    role="region"
    id="y9-acordion__panel-1"
    aria-labelledby="y9-accourdon__button-1">
    아코디언 패널
  </div>
</div>

Accordion Component
WAI-ARIA Properties

ARIA 관계 속성 중 하나인 aria-controls 속성을 사용하여 연결된 패널 id 속성 값을 설정합니다.

<!-- 아코디언 아이템 -->
<div class="y9-accordion__item">
  <!-- 아코디언 헤더 -->
  <h3 class="y9-accordion__heading">
    <!-- 아코디언 헤더 버튼 -->
    <button
      type="button"
      class="y9-accordion__button"
      aria-controls="y9-accordion__panel-1"
      id="y9-accourdon__button-1">아코디언 헤더</button>
  </h3>
  <!-- 아코디언 패널 -->
  <div
    class="y9-accordion__panel"
    role="region"
    id="y9-acordion__panel-1"
    aria-labelledby="y9-accourdon__button-1">
    아코디언 패널
  </div>
</div>

Accordion Component
WAI-ARIA Properties

ARIA 관계 속성 중 하나인 aria-labelledby 속성을 사용하여 연결된 헤더 버튼의 id 속성 값을 설정합니다.

aria-labelledby는 레이블 지정 가능한 요소뿐 아니라 어떤 요소에서든 사용할 수 있습니다.

label 요소는 자신이 레이블을 지정하는 대상을 참조하지만 aria-labelledby의 경우에는 관계가 뒤바뀝니다. 즉, 레이블을 지정하는 대상이 레이블을 지정하는 주체를 참조합니다.

aria-labelledby를 사용하여 숨겨져 있거나 접근성 트리에 없는 요소를 참조할 수 있습니다. 예를 들어, 레이블을 지정하려는 요소 옆에 숨겨진 span을 추가하고 aria-labelledby로 참조할 수 있습니다.

aria-labelledby가 한 요소에 대한 다른 모든 이름 소스를 재정의한다는 점입니다. 예를 들어, 어떤 요소에 aria-labelledby와 aria-label이 모두 있거나 aria-labelledby와 네이티브 HTML label이 있는 경우에는 aria-labelledby 레이블이 항상 우선합니다.

 

W3C, WAI-ARIA
아코디언 컴포넌트 속성 정리

아코디언 헤더의 버튼은 aria-controls 속성에 연결된 패널 id 속성 값을 연결해야 합니다.

아코디언 패널 역할을 수행하는 요소에 role="region"을 설정하고,
연결된 헤더 버튼 요소 id 값을 aria-labelledby 속성에 설정합니다.

<!-- 아코디언 아이템 -->
<div class="y9-accordion__item">
  <!-- 아코디언 헤더 -->
  <h3 class="y9-accordion__heading">
    <!-- 아코디언 헤더 버튼 -->
    <button
      type="button"
      class="y9-accordion__button"
      aria-controls="y9-accordion__panel-1"
      id="y9-accourdon__button-1"
      aria-expanded="false">아코디언 헤더</button>
  </h3>
  <!-- 아코디언 패널 -->
  <div
    style="display: none;"
    class="y9-accordion__panel"
    role="region"
    id="y9-acordion__panel-1"
    aria-labelledby="y9-accourdon__button-1">
    아코디언 패널
  </div>
</div>

Accordion Component
WAI-ARIA States

aria-expanded 속성을 사용하여 연결된 패널의 펼침/접힘 상태 정보를 제공합니다.

<!-- 아코디언 아이템 -->
<div class="y9-accordion__item">
  <!-- 아코디언 헤더 -->
  <h3 class="y9-accordion__heading">
    <!-- 아코디언 헤더 버튼 -->
    <button
      type="button"
      class="y9-accordion__button"
      aria-controls="y9-accordion__panel-1"
      id="y9-accourdon__button-1"
      aria-expanded="true"
      aria-disabled="true">아코디언 헤더</button>
  </h3>
  <!-- 아코디언 패널 -->
  <div
    style="display: block;"
    class="y9-accordion__panel"
    role="region"
    id="y9-acordion__panel-1"
    aria-labelledby="y9-accourdon__button-1">
    아코디언 패널
  </div>
</div>

Accordion Component
WAI-ARIA States

aria-disabled 속성을 사용하는 경우는 연결된 패널이 닫히면 안되는 상태라는 정보를 제공합니다.

W3C, WAI-ARIA
아코디언 컴포넌트 상태 정리

아코디언 헤더와 연결된 패널이 토글되면 헤더의 버튼은
aria-expanded 상태 값이 변경되어야 합니다. (펼침 true, 접힘 false)

만약 아코디언 헤더와 연결된 패널이 펼쳐진 상태를 유지해야 하는 경우,
헤더의 버튼 요소에 aria-disabled="true"를 설정합니다.

AOA, Make UI Component using WAI-ARIA

By yamoo9

AOA, Make UI Component using WAI-ARIA

WAI-ARIA를 반영한 탭(Tab) UI 컴포넌트 제작 학습용 슬라이드.

  • 1,902