라디오 버튼은 다 읽어주는데 정작 질문이 안 읽힌 이유
문제 발생
연락 수단을 고르는 라디오 그룹을 만들었습니다. 스크린리더로 들어보니 "이메일 라디오 버튼, 1/3"처럼 선택지만 읽히고, 무엇을 고르라는 질문인지는 끝까지 나오지 않았습니다.
<p>선호하는 연락 수단</p>
<input type="radio" id="c1" name="contact" value="email" />
<label for="c1">이메일</label>
<input type="radio" id="c2" name="contact" value="phone" />
<label for="c2">전화</label>원인 분석
<p>는 그냥 문단입니다. 그 아래 컨트롤들과 아무 관계가 없고, 스크린리더가 폼 컨트롤을 하나씩 이동할 때는 화면에서 위에 있다는 이유로 읽히지 않습니다. <label>은 자기 for가 가리키는 한 개의 입력만 설명합니다.
MDN은 <fieldset>을 **"폼 안에서 여러 컨트롤과 label을 묶는 데 사용하는 요소"**로 정의하고, **"fieldset의 캡션은 그 안에 중첩된 첫 <legend> 요소가 제공한다"**고 설명합니다. <fieldset>의 암묵적 ARIA role은 group이고, radiogroup도 허용된 role로 나열되어 있습니다.
라디오 그룹 자체는 이름으로 만들어집니다. MDN의 설명대로 라디오 그룹은 그룹 안의 각 라디오 버튼에 같은 name을 주어 정의되고, 그룹이 만들어지면 하나를 고를 때 같은 그룹의 선택이 자동으로 해제됩니다.
해결 방안
- 질문을
<legend>로 옮깁니다. 첫 번째 자식이어야 캡션으로 인정됩니다.
<fieldset>
<legend>선호하는 연락 수단</legend>
<div>
<input type="radio" id="c1" name="contact" value="email" required />
<label for="c1">이메일</label>
</div>
<div>
<input type="radio" id="c2" name="contact" value="phone" />
<label for="c2">전화</label>
</div>
</fieldset>-
required는 그룹에서 하나면 됩니다. 문서 그대로 — 같은 이름의 라디오 그룹 중 어느 하나에required가 있으면 그 그룹에서 하나는 반드시 선택되어야 하며, 반드시 그 속성이 붙은 버튼일 필요는 없습니다. 전부에 붙이면 의미가 늘지 않고 유지보수만 늘어납니다. -
disabled를 그룹 단위로 씁니다.<fieldset disabled>는 문서 설명대로 자손인 모든 폼 컨트롤을 비활성화하고, 이들은 폼과 함께 전송되지 않으며 마우스 클릭·포커스 이벤트도 받지 않습니다. 개별 입력마다disabled를 돌려 붙일 필요가 없습니다. -
<legend>안의 컨트롤은 예외라는 걸 알아둡니다. 문서가 명시합니다 —<legend>안의 폼 요소는 비활성화되지 않습니다. "섹션 전체 사용" 토글을 legend에 두는 패턴이 이것 덕분에 동작합니다. -
시각 디자인 때문에 legend를 지우지 않습니다. 테두리·여백이 마음에 들지 않으면
border: 0으로 fieldset을 조정하고, legend는 남긴 채 시각적으로만 숨깁니다(VisuallyHidden). 지우는 순간 질문이 다시 사라집니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.