LabHub
배우기 러닝패스 코스

HTML — One Tag Stands In For a Feature

Getting Rid of Nameless Fields

LabHub 에서 이어서 보기

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

목표

가입 폼을 하나 쓰고, 모든 칸에 접근 가능한 이름이 실제로 계산되는지를 확인합니다. 브라우저는 없지만 이름 계산은 마크업만으로 답이 하나입니다.

왜 중요한가

"label 을 썼는가" 는 눈으로 셀 수 있지만, 그것으로는 forid 가 어긋난 칸을 못 잡습니다. 기계가 보는 것은 글자가 아니라 계산 결과이고, 그 계산에는 정해진 순서가 있습니다 — aria-labelledbyaria-labellabeltitleplaceholder.

앞 단계가 값을 내면 뒤는 보지 않습니다. 그래서 aria-label 하나가 눈에 보이는 label 을 통째로 덮어쓰고, 화면에 적힌 글자와 음성이 갈라집니다. 말로 조작하는 사용자는 보이는 글자를 부르므로 그 순간 조작이 안 됩니다.

만들 것

/root/work/forms/signup.html 하나입니다. CSS 도 자바스크립트도 필요 없습니다 — 이 실습이 보는 것은 연결이 성립하는가 입니다.

계산기

cd /root/work/forms
python3 /opt/lab/checks/html-form-lab/accname.py signup.html

칸마다 이름과 그 이름이 어디에서 나왔는지를 보여 줍니다. 끊긴 aria-labelledbyaria-describedby 도 함께 찍습니다.

단계

  1. 문서 뼈대와 form · 제출 버튼
  2. 칸 세 개 · 이름이 label 에서 나오게
  3. 라디오 묶음 · fieldsetlegend
  4. 규칙 안내를 aria-describedby
  5. 오류 상태 — aria-invalidrole="alert"
  6. typeautocomplete
  7. 필수 표시 — 눈으로도, 프로그램으로도
  8. 계산기 결과를 08-names.txt
  9. 정리 → 09-notes.md

참고

폼 한 벌을 세운다

/root/work/forms/signup.html 을 만드세요. <!doctype html>, <html lang="ko">, <title>, <meta charset>, <meta name="viewport"> 가 있어야 하고, actionmethod 를 가진 <form> 안에 입력 칸 하나와 제출 <button> 이 있어야 합니다.

mkdir -p /root/work/forms. actionmethod 를 적어 두면 자바스크립트가 죽어도 폼은 보내집니다 — 그게 폼의 기본값입니다. 제출은 button 으로 하세요. input type="submit" 도 되지만 버튼 안에 아이콘이나 다른 요소를 넣을 수 없습니다.

이름이 어디에서 나오는가

입력 칸을 세 개 이상으로 늘리고, 모든 칸의 이름이 label 에서 나오게 하세요. 계산기가 찍는 출처= 가 세 칸 모두 label 이어야 합니다. placeholdertitle 로 이름을 때우면 실패합니다.

labelfor 와 입력칸의 id한 글자도 달라선 안 됩니다. 눈으로는 나란히 붙어 있어도 기계에게는 남남입니다. python3 /opt/lab/checks/html-form-lab/accname.py signup.html 로 지금 이름이 어디에서 나오는지 먼저 보세요.

묶음에는 묶음의 이름이 있다

같은 name 을 가진 라디오 버튼을 두 개 이상 만들고, 하나의 <fieldset> 안에 넣은 뒤 <legend> 로 묶음 이름을 주세요. 각 라디오에도 자기 label 이 있어야 합니다.

라디오는 여럿이 모여 질문 하나를 이룹니다. 보기마다 이름이 있어도 '무엇을 고르는 중인지' 는 어디에도 없습니다 — 그 자리를 legend 가 채웁니다. name 이 같아야 서로를 끕니다.

규칙은 이름이 아니라 설명이다

비밀번호 규칙 안내를 별도 요소로 쓰고 aria-describedby 로 연결하세요. 설명 글은 10자 이상이어야 하고, 이름과 같은 문장이면 안 됩니다.

규칙을 label 안에 밀어 넣으면 칸 이름이 '비밀번호 열두 자 이상 숫자와 기호를…' 이 되어 버립니다. 이름은 짧아야 목록에서 고를 수 있습니다. 긴 안내는 설명으로 분리하세요.

오류를 프로그램이 읽게 한다

이메일 칸에 aria-invalid="true" 를 주고, 도움말과 오류 메시지 두 요소aria-describedby 에 공백으로 나열하세요. 오류 메시지 요소에는 role="alert" 를 붙입니다.

빨간 테두리는 색을 구분 못 하는 사람에게 아무것도 아닙니다. aria-describedby 는 여러 id 를 받습니다 — 오류가 떠도 규칙 안내가 사라지지 않게 둘 다 가리키세요. 나중에 나타나는 글자는 role="alert" 가 있어야 읽힙니다.

타자 수도 접근성이다

글자를 치는 칸을 네 개로 늘리고(연락처 칸을 더하세요) 모두에 표준 autocomplete 값을 주세요. 이메일 칸은 type="email"autocomplete="email", 비밀번호는 new-password 입니다.

HTML 표준의 autofill 필드 이름 목록에 없는 값은 브라우저가 그냥 무시합니다 — e-mail 은 아무 일도 하지 않습니다. 가입은 new-password, 로그인은 current-password 입니다. 이 구분이 있어야 비밀번호 관리자가 새 암호를 제안합니다.

필수는 눈으로도 보여야 한다

칸 두 개 이상에 required 를 주고, 그 칸의 label 글자에도 필수 표시를 넣으세요. 선택 칸은 하나 이상 남겨 두어야 하고, 선택 칸의 이름에는 필수 표시가 없어야 합니다.

aria-required 만 쓰면 알려 주기만 할 뿐 브라우저의 제출 막기가 켜지지 않습니다. 반대로 required 만 쓰면 눈으로는 어느 칸이 필수인지 알 수 없습니다. 둘 다 필요합니다. 전부 필수로 만들면 표시가 아무것도 구분해 주지 않습니다.

계산기로 확인한다

accname.py 를 돌려 결과를 /root/work/forms/08-names.txt 로 남기세요. 저장된 줄 수가 지금 문서의 컨트롤 수와 같아야 하고, 출처=placeholder 나 끊긴 참조 경고가 없어야 합니다.

python3 /opt/lab/checks/html-form-lab/accname.py signup.html | tee 08-names.txt. 문서를 고쳤으면 다시 저장해야 합니다 — 채점기가 저장본과 지금 문서를 대조합니다.

무엇이 연결이고 무엇이 글자인가

/root/work/forms/09-notes.md 에 세 줄 이상(120자 이상) 적으세요. 본문에 placeholder, fieldset, 이름 이 들어가야 합니다. 문서 자체도 여전히 2단계 기준을 통과해야 합니다.

핵심은 하나입니다 — 연결은 글자가 아니라 계산이다. 어떤 실수가 '마크업은 멀쩡해 보이는데 이름이 없는' 상태를 만드는지 자기 말로 적어 두면 다음에 손이 기억합니다.