팝업을 만들 때 WAI-ARIA를 활용해서 만들어보고, tabindex를 통해서 팝업 내부 영역에서만 이동하도록 하는 방법

박찬정·2024년 7월 14일
0

웹 접근성을 높이기 위해 WAI-ARIA(웹 접근성 이니셔티브 - 접근성 리치 인터넷 애플리케이션) 속성을 활용해 팝업을 만드는 방법과 tabindex 속성을 이용해 팝업 내부 영역에서만 포커스가 이동하도록 하는 방법에 대해 설명해드리겠습니다.

1. WAI-ARIA를 활용한 팝업 만들기

WAI-ARIA 속성은 웹 애플리케이션의 접근성을 높이기 위해 사용됩니다. 팝업을 만들 때 주로 사용되는 WAI-ARIA 속성은 다음과 같습니다:

role="dialog": 해당 요소가 대화 상자(popup)임을 스크린 리더에게 알려줍니다.
aria-labelledby: 팝업의 제목을 참조하는 속성으로, 팝업의 제목 요소의 id를 지정합니다.
aria-describedby: 팝업의 설명을 참조하는 속성으로, 팝업 내용 요소의 id를 지정합니다.
aria-hidden: 팝업이 보이지 않거나 접근할 수 없을 때 true로 설정하여 스크린 리더에게 이를 알립니다.

2. tabindex를 활용한 포커스 제어

팝업 내부에서만 포커스가 이동하도록 하기 위해서는 tabindex 속성을 활용합니다. 이를 위해 포커스 트랩(focus trap)을 설정할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Accessible Popup Example</title>
<style>
  .popup {
    display: none;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border: 1px solid #ccc;
    padding: 20px;
    background-color: #fff;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  }
  .popup.active {
    display: block;
  }
</style>
</head>
<body>
<button id="openPopupBtn">Open Popup</button>

<div id="popup" class="popup" role="dialog" aria-labelledby="popupTitle" aria-describedby="popupDescription" aria-hidden="true">
  <h2 id="popupTitle">Popup Title</h2>
  <p id="popupDescription">This is a description of the popup content.</p>
  <button id="closePopupBtn">Close Popup</button>
</div>

<script>
  const openPopupBtn = document.getElementById('openPopupBtn');
  const closePopupBtn = document.getElementById('closePopupBtn');
  const popup = document.getElementById('popup');

  openPopupBtn.addEventListener('click', () => {
    popup.classList.add('active');
    popup.setAttribute('aria-hidden', 'false');
    closePopupBtn.focus();
  });

  closePopupBtn.addEventListener('click', () => {
    popup.classList.remove('active');
    popup.setAttribute('aria-hidden', 'true');
    openPopupBtn.focus();
  });

  // Focus trap implementation
  popup.addEventListener('keydown', (event) => {
    if (event.key === 'Tab') {
      const focusableElements = popup.querySelectorAll('button');
      const firstElement = focusableElements[0];
      const lastElement = focusableElements[focusableElements.length - 1];

      if (event.shiftKey) {
        if (document.activeElement === firstElement) {
          lastElement.focus();
          event.preventDefault();
        }
      } else {
        if (document.activeElement === lastElement) {
          firstElement.focus();
          event.preventDefault();
        }
      }
    }

    if (event.key === 'Escape') {
      closePopupBtn.click();
    }
  });
</script>
</body>
</html>

설명

HTML 구조:

팝업을 열기 위한 버튼과 팝업 자체로 구성됩니다. 팝업은 role="dialog", aria-labelledby, aria-describedby 등의 WAI-ARIA 속성을 가집니다.
팝업의 기본 상태는 display: none으로 숨겨져 있습니다.

JavaScript 동작:

팝업 열기 버튼을 클릭하면 팝업이 나타나고, aria-hidden 속성이 false로 설정됩니다. 동시에 팝업 내부의 닫기 버튼으로 포커스를 이동합니다.
팝업 닫기 버튼을 클릭하면 팝업이 사라지고, aria-hidden 속성이 true로 설정되며, 다시 팝업 열기 버튼으로 포커스가 돌아갑니다.

포커스 트랩:

팝업 내부에서 Tab 키를 눌렀을 때 포커스가 팝업 내부의 첫 번째와 마지막 포커스 가능한 요소 사이에서만 이동하도록 합니다.
Shift + Tab 조합으로 역방향으로 이동할 때와 일반 Tab 키로 순방향으로 이동할 때의 포커스 이동을 제어합니다.
Escape 키를 눌렀을 때 팝업이 닫히도록 합니다.
이렇게 하면 사용자가 키보드를 통해 팝업을 쉽게 열고 닫을 수 있으며, 팝업이 열린 동안 포커스가 팝업 내부에서만 이동하도록 보장하여 접근성을 높일 수 있습니다.

profile
프론트엔드 배우고 있습니다

0개의 댓글