消灭没有名字的输入框
한국어 원문으로 표시합니다.
목표
가입 폼을 하나 쓰고, 모든 칸에 접근 가능한 이름이 실제로 계산되는지를 확인합니다. 브라우저는 없지만 이름 계산은 마크업만으로 답이 하나입니다.
왜 중요한가
"label 을 썼는가" 는 눈으로 셀 수 있지만, 그것으로는 for 와 id 가
어긋난 칸을 못 잡습니다. 기계가 보는 것은 글자가 아니라 계산 결과이고,
그 계산에는 정해진 순서가 있습니다 — aria-labelledby → aria-label →
label → title → placeholder.
앞 단계가 값을 내면 뒤는 보지 않습니다. 그래서 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-labelledby 와 aria-describedby 도 함께 찍습니다.
단계
- 문서 뼈대와
form· 제출 버튼 - 칸 세 개 · 이름이
label에서 나오게 - 라디오 묶음 ·
fieldset과legend - 규칙 안내를
aria-describedby로 - 오류 상태 —
aria-invalid와role="alert" type과autocomplete- 필수 표시 — 눈으로도, 프로그램으로도
- 계산기 결과를
08-names.txt로 - 정리 →
09-notes.md
참고
- 폼을 보내는 곳은 실제로 없어도 됩니다. 마크업만 봅니다.
id가 겹치면 연결이 전부 첫 번째 요소로만 갑니다. 채점기가 먼저 막습니다.- 자동 검사는 문제의 일부만 잡습니다. 나머지는 마우스를 치우고 Tab 만으로 폼을 끝까지 채워 보면 대부분 드러납니다.
폼 한 벌을 세운다
/root/work/forms/signup.html 을 만드세요. <!doctype html>, <html lang="ko">, <title>, <meta charset>, <meta name="viewport"> 가 있어야 하고, action 과 method 를 가진 <form> 안에 입력 칸 하나와 제출 <button> 이 있어야 합니다.
mkdir -p /root/work/forms. action 과 method 를 적어 두면 자바스크립트가 죽어도 폼은 보내집니다 — 그게 폼의 기본값입니다. 제출은 button 으로 하세요. input type="submit" 도 되지만 버튼 안에 아이콘이나 다른 요소를 넣을 수 없습니다.
이름이 어디에서 나오는가
입력 칸을 세 개 이상으로 늘리고, 모든 칸의 이름이 label 에서 나오게 하세요. 계산기가 찍는 출처= 가 세 칸 모두 label 이어야 합니다. placeholder 나 title 로 이름을 때우면 실패합니다.
label 의 for 와 입력칸의 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단계 기준을 통과해야 합니다.
핵심은 하나입니다 — 연결은 글자가 아니라 계산이다. 어떤 실수가 '마크업은 멀쩡해 보이는데 이름이 없는' 상태를 만드는지 자기 말로 적어 두면 다음에 손이 기억합니다.