본문으로 바로 가기
← 데모 코드 목록보기

폼 접근성 비교

접근성 없는 폼과 접근성 있는 폼을 나란히 비교합니다 — Tab 키와 스크린 리더로 차이를 직접 체험해보세요
관련 포스트 읽기 →
🧪 테스트 가이드
  1. 키보드: Tab으로 이동하며 포커스 표시와 이동 순서를 비교하세요.
  2. 스크린 리더: macOS Cmd+F5(VoiceOver) 또는 NVDA를 켜고 각 필드에서 읽히는 내용을 비교하세요.
  3. 에러 유발: 아무것도 입력하지 않고 제출 버튼을 눌러 에러 처리 방식을 비교하세요.
❌ 접근성 없는 폼
placeholder 라벨 · 에러 시각만 · outline:none
결제 수단
✅ 접근성 있는 폼
label·aria-required·fieldset·aria-invalid·role=alert

표시 항목은 필수입니다.

예: hello@example.com

영문·숫자 포함 8자 이상

결제 수단(필수, 1개 선택)
주요 차이점
항목 ❌ 접근성 없는 폼 ✅ 접근성 있는 폼
라벨placeholder만 사용<label for> 명시 연결
필수 표시없음aria-required + 숨김 텍스트
입력 힌트없음aria-describedby 연결
에러 처리빨간 테두리만aria-invalid + role="alert"
그룹화<div> 묶음<fieldset> + <legend>
포커스 표시outline: none명확한 포커스 링
❌ 스크린 리더가 에러를 모름
시각적 변화만 — aria 없음
이메일

스크린 리더 발표 로그
버튼을 눌러보세요
✅ 스크린 리더가 즉시 안내
role="alert" + aria-invalid

예: hello@example.com

스크린 리더 발표 로그 (시뮬레이션)
버튼을 눌러보세요
라벨 연결 WCAG 1.3.13.3.2
<!-- ❌ placeholder만 사용 -->
<input type="text" placeholder="이름">

<!-- ✅ label + for/id 연결 -->
<label for="name">
  이름 <span aria-hidden="true">*</span>
  <span class="sr-only">(필수)</span>
</label>
<input type="text" id="name" required aria-required="true">
에러 처리 WCAG 3.3.13.3.3
<!-- ❌ 시각적 표시만 -->
<input class="has-error" type="email">
<div style="color:red">이메일 형식 오류</div>

<!-- ✅ aria-invalid + role="alert" -->
<input type="email"
  aria-invalid="true"
  aria-describedby="email-err">
<p id="email-err" role="alert">
  올바른 이메일 형식으로 입력해주세요. 예: hello@example.com
</p>
그룹화 WCAG 1.3.1
<!-- ❌ div 묶음 -->
<div>결제 수단</div>
<input type="radio" name="pay"><label>신용카드</label>
<input type="radio" name="pay"><label>계좌이체</label>

<!-- ✅ fieldset + legend (읽힘: "결제 수단, 신용카드, 라디오 1/2") -->
<fieldset>
  <legend>결제 수단 <span class="sr-only">(필수)</span></legend>
  <label><input type="radio" name="pay" value="card"> 신용카드</label>
  <label><input type="radio" name="pay" value="wire"> 계좌이체</label>
</fieldset>
포커스 스타일 WCAG 2.4.72.4.11
/* ❌ 절대 하지 마세요 */
input:focus { outline: none; }

/* ✅ 명확한 포커스 링 */
input:focus {
  outline: 2px solid #5558e3;
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(85,88,227,.25);
}