접근성을 고려한 요소 숨기기
요소를 숨기는데 다섯 가지 방법이 존재한다.
-
(react) conditional rendering
-
display: none
-
visibility: hidden
-
opacity: 0
-
hidden attribute
display: none
은 요소가 DOM 트리에 포함되지 않는다. 고로 layout도 차지하지 않는다. 리플로우, 리페인트가 발생할 수 있다.
hidden
속성은 요소가 DOM 트리에 포함된다. 하지만 layout은 차지하지 않는다. 당연히 interact가 불가하다. 리플로우, 리페인트가 발생할 수 있다.
visibility: hidden
은 요소가 DOM 트리에 포함된다. layout도 차지하고 있다. 당연히 interact가 불가하다. 리페인트만 발생한다.
opacity: 0
은 요소가 DOM 트리에 포함된다. layout도 차지하고 있다. 그리고 interact가 가능하다. 리페인트만 발생한다.
conditional rendering
과 display: none
의 차이는 이 문서를 참고하자.
display: none
과 hidden
은 거의 동일하다. 단, 사용해야 하는 때는 다음과 같이 구분할 수 있다. hidden
은 숨기려는 요소가 현재 페이지 컨텐츠의 일부가 아닐 때 사용(semantic한 관점)하고, display: none
은 숨기려는 요소가 현재 페이지 컨텐츠의 일부일 때 사용한다.
예를들면 폼을 작성하는 와중에 유저가 잘못 기입했을 때 보여져야하는 에러 메세지나 혹은 폼을 작성하고나서 보여져야하는 성공 메세지는 hidden
이 적합하다. 에러 메세지든 성공 메세지든 실제 조건이 충족되지 않는다면 보여지지 않기 때문에 페이지 컨텐츠의 일부로 보기 어렵기 때문이다.
반면에 뷰포트 등의 제약으로 특정 문단을 숨겨놨다가 토글 버튼을 눌렀을 때 보여주거나, 혹은 유저가 어떤 요소를 Hover 했을 때 보여줘야 하는 경우에는 display: none
이 적합하다.
주의할 점은, hidden
이 display css를 override하지 못한다는 것이다. display: block
이 존재하는 경우 hidden
을 적용해도 요소가 사라지지 않는다.
display: none
은 기본적으로 스크린 리더가 읽어주지 않지만 간혹가다 읽어주는 경우도 존재한다고 한다.
opacity: 0
의 경우 읽어주는 경우도 존재하 고 읽어주지 않는 경우도 존재하고, visibility: hidden
은 스크린 리더가 읽어주지 않는 듯 하다.
이렇게 스크린 리더에 따라서 케이스 바이 케이스가 존재한다면, aria-hidden
은 항상 같이 따라다니는 편이 좋을 것 같다. 예를들면 tab panel을 설계한다면 display: none
을하고 여기에 aria-hidden=true
를 이용하여 엣지 케이스에도 스크린 리더가 제대로 동작하도록.
참고 문헌
Will the CSS property "opacity" only hide content from screen readers if exactly 0?
What is the difference between the hidden attribute (HTML5) and the display:none rule (CSS)?
Using the hidden attribute vs conditionally rendering a component
CSS display:none and visibility:hidden – What's the Difference?