키보드 포커스

hidden
notion image
 

키보드를 사용하는 이유

많은 사람들이 키보드를 기본 탐색 수단으로 사용한다.
  • 개인적인 선호나 효율성으로 인해
  • 일시적인 신체 제한(예: 손목 염좌)이나 만성적인 미세 운동 장애(예: 손목터널증후군)로 인해
  • 저시력 또는 시각 장애 사용자는 화면 확대 소프트웨어나 스크린 리더(Screen Reader)와 함께 키보드를 사용해 탐색할 수 있다.
📌 결론: 다양한 이유로 키보드 탐색이 중요하며, 이를 고려한 접근성을 제공해야 한다.

키보드 접근성과 포커스(Focus)

  • 포커스(Focus): 키보드에서 입력을 받을 수 있는 활성 요소를 의미.
  • HTML과 CSS를 활용해서 키보드 탐색이 원활하도록 만들 수 있다.
  • JavaScript를 사용하면 포커스 관리와 키보드 이벤트 처리를 더 세밀하게 제어할 수 있다.

포커스 대상

Focusable Elements

포커스로 이동할 수 있는 요소를 Focusable Elements(포커스를 받을 수 있는 요소) 라고 한다.
  • 기본적으로 HTML에서는 링크(<a>), 체크박스(<input type="checkbox">), 입력 필드(<input>), 버튼(<button>) 같은 Ineractive한 요소들은 자연스럽게 포커스를 받을 수 있다.
  • 이 요소들에는 기본적인 탭 순서 지원키보드 이벤트 처리도 포함되어 있다.

Unfocusable → Fully Focusable

기본적으로 포커스를 받을 수 없는 요소들도 tabindex를 부여해 포커스 대상에 포함시킬 수 있다.
다만 포커스를 받도록 만들 뿐이므로, 상호작용을 위한 작업들은 별도로 해줘야 한다.
  • 포커스 받을 수 있도록 tabindex 추가
<div tabindex="0">Click Me</div>
  • 포커스 받았을 때 UI 처리
div:focus { outline: 2px solid blue; /* 포커스가 있을 때 강조 표시 */ }
  • 엔터, 스페이스바 등 키보드 입력에 대한 처리
const element = document.querySelector('div[role="button"]'); element.addEventListener("keydown", function(event) { if (event.key === "Enter" || event.key === " ") { // 클릭 시의 동작을 처리 (예: 함수 호출, 내용 변경 등) alert("Button clicked!"); } });
  • ARIA 속성들을 추가하여 AT 에게 어떤 요소인지 설명
<div tabindex="0" role="button" aria-pressed="false">Click Me</div>
 

포커스 순서(Focus Order)

  • 기본적인 포커스 순서:
    • 대부분의 언어들은 왼쪽에서 오른쪽, 위에서 아래로 읽음.
    • 오른쪽에서 왼쪽으로 읽는 언어(예: 아랍어, 히브리어)
    • 따라서 페이지의 주 언어 설정에 따라 포커스 순서는 달라질 수 있다.
📌

Tab 키와 Shift + Tab

  • Tab 키 → 다음 포커스 가능한 요소로 이동
  • Shift + Tab 키 → 이전 포커스 요소로 이동
 

Tabindex 속성

tabindex 속성을 사용하면 포커스 순서를 조정할 수 있다.
  • tabindex="0" → 기본적인 포커스 순서에 따라 이동하도록 추가
  • tabindex="-1" → 의도적으로 포커스에서 제거하지만, JavaScript를 사용하여 다시 포커스 받도록 되돌릴 수 있음.
    • 예) input 값이 채워지지 않으면 접근되면 안되는 요소에 상태에 따라 "-1"로 설정
  • tabindex="1" 이상권장되지 않음! (사용자를 혼란스럽게 할 수 있음)

좋지 않은 예시

<div> <h1>Focus order</h1> <p tabindex="0">Focus goes here 4th</p> <p tabindex="2">Focus goes here 2nd</p> <p tabindex="1">Focus goes here 1st</p> <p tabindex="-1">Focus never goes here</p> <p tabindex="3">Focus goes here 3rd</p> <p tabindex="0">Focus goes here 5th</p> </div> <br> <div> <span>Note: this is an example of the power of the tabindex atttribute and what NOT to do with your focus order!</span> </div>
이렇게 하면 논리적인 순서를 망칠 수 있음!
📌 결론: tabindex="0"을 사용해서 자연스러운 포커스 흐름을 유지하고, tabindex="1" 이상의 값을 사용하지 않는 것이 좋음.
 

Skip Links (건너뛰기 링크)

요즘 대부분의 웹 페이지는 페이지의 메인 헤더에 긴 메뉴 링크 목록을 가지고 있다.
웹사이트의 네비게이션이 너무 길면 키보드 사용자들이 메인 콘텐츠에 도달하기 어려울 수 있다.
  • 페이지 이동 시 마다 nav 탭을 건너 뛰기 위해 여러번의 tab을 해야 하기 때문.
  • "건너뛰기 링크(Skip Links)" 를 사용하면 불필요한 네비게이션을 건너뛰고 바로 주요 콘텐츠로 이동할 수 있도록 도울 수 있다.

활용방안

스킵 링크는 일반적인 사용자에겐 필요하지 않다.
  • 기본적으로 시각적으로 숨긴 상태로 추가하고,
  • 사용자가 웹사이트에 처음 도달했을 때 가장 먼저 포커스를 받을 수 있는 요소로 지정하고,
  • 탭을 눌렀을 때 스킵 링크로 포커스가 이동하도록 만든다.
  • 스킵링크와 상호작용 하면 main content 로 바로 건너뛴다.

예제 코드

<header> <a href="#main-content" class="skip-link">Skip to main content</a> <nav> <ul> <li><a href="#">Menu item 1</a></li> <li><a href="#">Menu item 2</a></li> <li><a href="#">Menu item 3</a></li> <li><a href="#">Menu item 4</a></li> <li><a href="#">Menu item 5</a></li> </ul> </nav> </header> <main id="main-content"> <h1>Hello world!</h1> <div>Cupcake ipsum dolor sit amet soufflé gingerbread. Tart cake biscuit cotton candy cake donut cake marshmallow jelly beans. Oat cake shortbread pudding soufflé cookie dragée icing. Danish <a href="#">gummi bears</a> donut cake lollipop jelly-o. Candy toffee croissant fruitcake soufflé sesame snaps bonbon bear claw. Jelly toffee bear claw sweet dragée marshmallow bonbon cookie jelly. Cupcake gingerbread brownie tiramisu. Pastry danish fruitcake sugar plum candy jelly beans jelly-o.</div> </main>
.skip-link { position: absolute !important; height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px); color: red; } .skip-link:focus { position: unset !important; /* position 속성 값을 초기화하여 화면에 보이도록 만듦 */ }
notion image
숨겨져 있다가 사용자가 tab을 하면 skip link가 나타나고, 상호작용하면 메인 콘텐츠로 건너뛴다.
 
📌 결론: 키보드 탐색을 돕기 위해 "Skip to main content" 같은 건너뛰기 링크를 제공하는 것이 중요하다.
 

포커스 스타일 (Focus Indicator)

키보드 탐색을 지원하려면 포커스가 어디에 있는지 표시하는 것이 중요하다.
  • 브라우저는 기본적으로 포커스된 요소에 스타일을 제공하지만, 웹사이트의 디자인이 이를 덮어쓸 수도 있다.
  • 특히 “outlinke: 0” 또는 outline: none; 같은 스타일은 포커스 위치를 알 수 없게 만든다.

나쁜 예시 (포커스 스타일 삭제)

a:focus { outline: none; /* 이렇게 하면 안 됨! */ }
이렇게 하면 키보드 사용자가 어디에 포커스가 있는지 알 수 없게 됨.

좋은 예시 (포커스 스타일 유지)

a:focus { outline: auto 5px Highlight; /* 비웹킷 브라우저 */ outline: auto 5px -webkit-focus-ring-color; /* 웹킷 브라우저 */ }

커스텀 스타일

사용자 경험을 향상시키기 위해 커스텀 스타일을 만들 수도 있다.
/* Removing the browser default focus styling for demo purposes - don't do this! */ a:focus { outline: none; } /* Adds the browser default styling back */ a.style1:focus { outline: auto 5px Highlight; /* for non-webkit browsers */ outline: auto 5px -webkit-focus-ring-color; /* for webkit browsers */ } /* Adds a thick green rounded outline */ a.style2:focus { outline: 0.5rem solid #25aa00; border-radius: 5px; } /* Adds a medium-sized dotted purple outline */ a.style3:focus { outline: medium dashed #bf40bf; } /* Adds a blue wavy underline */ a.style4:focus { text-decoration: wavy underline 2px #0000ff; } /* Adds a green background */ a.style5:focus { background-color: #25aa00; }
notion image
 
📌 결론: 포커스 스타일을 명확하게 유지해야 하고, 최소한 명확한 대비(contrast) 를 유지해야 WCAG 접근성 가이드라인을 만족할 수 있다.
 

결론

  • 키보드 접근성은 모든 사용자를 위해 필수적이며, 장애가 없는 사용자에게도 유용할 수 있음.
  • tabindex="0"을 활용해서 자연스러운 탐색 흐름을 유지하고, tabindex="1" 이상의 값은 피해야 함.
  • "Skip to main content" 같은 건너뛰기 링크를 사용하면 사용자가 빠르게 원하는 콘텐츠로 이동할 수 있음.
  • 포커스 스타일을 명확하게 유지해서 사용자가 어디에 위치하고 있는지 쉽게 알 수 있도록 해야 함.