LabHub
배우기 러닝패스 코스

HTML — タグ一つが機能を肩代わりする

タブ順序を手で直す

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

키보드만으로 끝까지 쓸 수 있는 화면을 씁니다. 브라우저는 없지만 Tab 을 눌렀을 때 어디로 가는가는 마크업만으로 계산됩니다.

왜 중요한가

키보드 접근성은 기능이 아니라 순서입니다. 무엇이 초점을 받고, 어떤 차례로 돌고, 지금 어디 있는지 보이는가. 그리고 이 셋은 마우스로 확인하면 절대 드러나지 않습니다 — QA 도 마우스로 하기 때문에 그대로 배포됩니다.

특히 양수 tabindex 는 그 요소 하나를 옮기는 것이 아니라 페이지를 두 무리로 쪼갭니다. 양수가 붙은 것들이 먼저 전부 돌고 나머지가 그다음입니다. tabindex="1" 하나면 그 요소가 페이지의 첫 칸이 됩니다.

만들 것

/root/work/kbd/app.html 하나입니다. 초점 표시 규칙은 문서 안의 <style> 에 씁니다.

계산기

cd /root/work/kbd
python3 /opt/lab/checks/html-kbd-lab/focus.py app.html

Tab 순서를 번호로 찍고, 양수 tabindex · aria-hidden 안의 초점 요소 · 흉내 위젯 · 끊긴 aria-* 참조를 지적합니다.

단계

  1. 건너뛰기 링크를 첫 칸에 · maintabindex="-1"
  2. 탭 순서 = 문서 순서 (양수 tabindex 금지)
  3. 흉내 위젯을 네이티브 요소로
  4. 장식은 aria-hidden, 접은 영역은 hidden
  5. 펼침 단추 — aria-expandedaria-controls
  6. 대화 상자 — role="dialog" · 이름 · 닫힌 동안 탭 순서에서 제외
  7. 초점 표시 — :focus-visible
  8. 계산기 결과를 08-focus.txt
  9. 정리 → 09-notes.md

참고

건너뛰기 링크를 첫 칸에

/root/work/kbd/app.html 을 만들고, <body>첫 초점 요소<a href="#main"> 건너뛰기 링크를 두세요. 목적지 <main id="main"> 에는 tabindex="-1" 이 있어야 합니다.

mkdir -p /root/work/kbd. 메뉴 뒤에 두면 건너뛸 것을 이미 다 지난 뒤입니다. 그리고 목적지가 초점을 받을 수 없는 요소면 브라우저가 주소만 바꾸고 초점은 그대로 둡니다 — tabindex="-1" 은 Tab 으로는 가지 않지만 링크로는 초점을 받게 합니다.

탭 순서를 문서 순서와 맞춘다

초점을 받는 요소를 여섯 개 이상(링크 3개 이상 · 버튼 2개 이상) 으로 늘리고, 양수 tabindex 가 하나도 없게 하세요. 이미 초점을 받는 요소에 tabindex="0" 을 붙이는 것도 안 됩니다.

계산기가 번호를 매겨 찍어 줍니다. 양수 tabindex 가 하나라도 있으면 그것들이 먼저 전부 돌고 나머지가 그다음입니다. 순서를 바꾸고 싶으면 마크업 순서를 바꾸세요.

흉내 위젯을 없앤다

button 요소를 세 개 이상 두고 모두에 type 을 주세요. role="button" 을 붙인 div, onclick 이 달린 div/span, 그리고 href="#" 처럼 아무 데도 가지 않는 링크가 없어야 합니다.

role 은 이름표만 바꿉니다 — 초점도 Enter·Space 도 따라오지 않습니다. 그리고 폼 안에서 type 없는 button 은 제출 버튼이 되어 누르면 페이지가 새로고침됩니다. 이동하면 링크, 무언가를 하면 버튼입니다.

감춘 것이 정말 감춰졌는가

읽을 필요가 없는 장식 요소에 aria-hidden="true" 를 붙이고, 접어 둔 패널에는 hidden 을 주세요. aria-hidden 안에 초점을 받는 요소가 있으면 안 되고, 접은 패널 안의 단추는 탭 순서에서 빠져야 합니다.

aria-hidden 은 보조기기 트리에서만 지웁니다 — 초점은 그대로 갑니다. 초점은 가는데 아무것도 읽히지 않는 상태가 가장 나쁩니다. 글자로 그린 아이콘처럼 초점도 안 받고 읽을 필요도 없는 것에만 쓰세요.

펼침 단추의 상태를 알린다

aria-expandedaria-controls 를 가진 button 을 두세요. aria-controls 는 실재하는 id 를 가리켜야 하고, aria-expanded="false" 이면 그 패널에 hidden 이 걸려 있어야 합니다.

화살표 모양만 바꾸면 눈으로 보는 사람에게만 상태가 전달됩니다. aria-expanded 는 '지금 열려 있는가' 를 프로그램에게 말합니다. 상태와 화면이 어긋나면 둘 중 하나는 거짓말이 됩니다.

대화 상자에 이름을 준다

role="dialog" · aria-modal="true" · aria-labelledby 를 가진 확인 창을 만들고 그 안에 단추 두 개(실행·취소)를 두세요. 처음에는 hidden 이어야 하고, 이 창을 여는 단추가 aria-controls 로 연결되어 있어야 합니다.

이름이 없으면 열려도 '대화 상자' 라고만 읽힙니다 — 제목 요소를 aria-labelledby 로 가리키세요. 그리고 닫힌 동안 그 안의 단추가 탭 순서에 남아 있으면, 사용자는 보이지 않는 곳으로 초점을 보냅니다.

초점이 보이게 한다

문서 안 <style>:focus-visible 규칙을 쓰고 보이는 outline 을 주세요. outline: none 으로 초점 링을 없애는 규칙이 있으면 안 되고, 건너뛰기 링크는 평소 화면 밖에 있다가 :focus 일 때 나타나야 합니다.

:focus 는 마우스 클릭에도 걸리지만 :focus-visible 은 키보드로 왔을 때만 걸립니다 — 디자인을 해치지 않으면서 필요한 사람에게만 링을 보여 줄 수 있습니다. outline: none 한 줄이 접근성을 가장 크게 망가뜨리는 한 줄입니다.

탭 순서를 남긴다

focus.py 를 돌려 결과를 /root/work/kbd/08-focus.txt 로 남기세요. 저장된 칸 수가 지금 문서의 탭 순서와 같아야 하고, 지적이 0건이어야 합니다.

python3 /opt/lab/checks/html-kbd-lab/focus.py app.html | tee 08-focus.txt. 번호가 화면에 보이는 차례와 같은지 눈으로 따라가 보세요 — 그게 사람이 해야 하는 확인입니다.

무엇이 순서를 깨뜨리는가

/root/work/kbd/09-notes.md 에 세 줄 이상(120자 이상) 적으세요. 본문에 tabindex, 건너뛰기, 초점 이 들어가야 합니다. 문서 자체도 여전히 지적 0건이어야 합니다.

핵심은 하나입니다 — 순서는 마크업이 정한다. 양수 tabindex 가 왜 그 요소 하나가 아니라 페이지 전체를 망가뜨리는지 자기 말로 적어 두세요.