녕후킴

녕후킴

블로그 주인의 프로필 그림

input과 label의 배치, 그리고 시각적 순서와 DOM 순서가 일치해야 하는 이유

0 views

input 태그와 label태그를 연결하는 경우, implicit label과 explicit label 두 가지 방식으로 연결이 가능하다.

implicit label을 사용하는 경우는 다음과 같이 label 태그에 for attribute를 사용할 필요가 없다.

<label> Name: <input type="text" name="name" /> </label>

explicit label을 사용하는 경우는 다음과 같이 label 태그에 for attribute를 사용한다.

<label for="name">Name: </label> <input type="text" id="name" name="name" />

하지만 implicit label의 경우 assistive technology가 제대로 인식하지 못하는 경우도 존재하기 때문에 항상 explicit label을 사용하는 것이 좋다고한다.

시각적 순서와 DOM 순서가 일치하도록 작성하기

전 직장에서 이미지 편집기를 결제하여 사용했다. 이 편집기는 기능 뿐만 아니라 화면 역시도 네트워크로 전달받은 스크립트로 그려졌는데, 문제는 이 스크립트가 난독화되어 있었기 때문에 코드를 직접 수정하여 프로젝트 디자인에 맞게 수정하는 것이 불가했다.

당시 팀장님께서 지시하셨던 것은 HTML 구조는 그대로 두고 CSS만으로 바텀 탭에 있는 버튼을 헤더로 옮기라는 것이었다. UI로도 그렇고, HTML 배치도 그렇고 바텀 탭에 존재하는 버튼은 헤더 탭에 존재하는 요소들보다 아래에 존재하게된다.

당시에 그렇게 하면 문제가 될것 같다는 '느낌'만 있었지 구체적으로 어떻게 문제가되는지에 대한 이유가 안떠올랐는데, 이번에 input과 label 태그 배치에 관한 문서에서 답을 찾을 수 있었다. 이유는 다음과 같다.

스크린 리더는 다음과 같이 작성된 HTML 요소를 만나게되면 label에 적힌 내용부터 포커싱한다.

<label>나 라벨!</label> <input type="radio"/>

그렇다면 다음 HTML 요소를 만나게되면 어떤 값 부터 포커싱이 될까?

<div style={{ display: 'flex' }}> <label style={{ order: 2 }}>나 라벨!</label> <input style={{ order: 1 }} type="radio"/> </div>

예상과는 다르게 label 요소부터 포커싱이 된다. 스크린 확대기와 스크린 리더를 동시에 사용하는 저시력자의 경우, 시각적인 순서와 읽어주는 순서가 일치하지 않는 경우 혼란에 빠질 수 있다. 그렇기 때문에 애시당초 다음과 같이 작성해주는 것이 좋다.

<div style={{ display: 'flex' }}> <input /> <label>나 라벨!</label> </div>

참고 문헌

HTML Inputs and Labels: A Love Story | CSS-Tricks - CSS-Tricks