[Refact/웹접근성] input file 요소에 잘못된 커스터마이징으로 스크린리더에서 읽을 수 없던 문제 개선하기
[Refact/웹접근성] input file 요소에 잘못된 커스터마이징으로 스크린리더에서 읽을 수 없던 문제 개선하기
지난 프로젝트에서 파일 업로드를 하기 위해 input type file 부분을 커스터마이징했다.
그러는 과정에서 input 요소에 display: none; 을 적용했고, label 요소의 background 로 원하는 이미지를 적용해주었다.
하지만 이런 방법은 tabindex 가 적용되지 않을 뿐더러 스크린리더가 해당 요소를 잡지 못하는 문제점이 발생했다.
이렇게 된다면 웹접근성을 고려하지 않는 방법이라 수정하는 게 좋다는 피드백을 받았다.
📌 접근 가능한 숨김 텍스트
🚫 내가 사용한 잘못된 방법
input{
disaply: none;
}
못생긴 input file 의 기존 디자인을 숨김에 급급했던 나는 input 요소를 화면에서 아예 사라지게 해버린 것이었다.
display none 은 아예 화면에서 차지하는 영역을 없애버리기 때문에 탭 포커싱이 되지 않을뿐더러 스크린리더가 읽을 수가 없게 된다.
🚫 기존에 사용했던 잘못된 방법
input{
text-indent: -999999px;
}
이 방법은 이전에 퍼블리셔 교육을 들었을때 배운 방식인데, 이 방법도 좋지 못한 방법이다.
위치가 문서의 밖으로 날아가버리기 때문에 SEO 에 좋지 않은 영향을 미친다고 한다.
이런걸 교육에서 배웠다니 지금으로써는 정말 어이가 없을 수밖에 없다. 🤣
🚫 크기 없애기
🚫 투명도 조절 → opacity: 0;
🚫보이지 않게 만들기 → visibility: hidden;
➡️ 이와같은 방법을 사용하면 스크린 리더가 잘 읽지 못하는 경우가 생기기 때문에 웹접근성에 위배될 수 있다.
➡️ 또한 탭 포커싱이 되지 않는다.
✏️ clip, clip-path 이용하기
.a11yHidden {
display: inline-block;
overflow: hidden;
position: absolute !important;
clip: rect(0, 0, 0, 0);
clip-path: inset(50%);
width: 1px;
height: 1px;
margin: -1px;
}
clip-path inset(0) 과 inset(50%) 비교


clip-path 는 구형 브라우저에서 지원되지 않을 수도 있으므로, clip 과 같이 사용한다.
하지만,
이런 방법을 사용하면 input 에 포커싱이 가지 않는 것처럼 보이는 문제가 발생했다.
이 문제를 해결하기 위해 다음과 같은 방법을 시도해보았다.
📌 appearance: none;
이 방법을 사용하면 checkbox 와 같은 스타일은 감출 수 있지만, input file button 에는 적용이 되지 않았다.
📌 file-selector-button 에 스타일 지정하기
input::file-selector-button{
border: none;
background: none;
color: transparent;
text-indent: 10px;
}
이 경우 정상적으로 포커싱이 되었다.
스크린리더를 실행해보면 정상적으로 input 을 인식한다.
📌 스크린리더 확장 프로그램
Screen Reader
A web-powered screen reader
chrome.google.com
on/off 버튼이 따로 없어서 사용하지 않을 때는 확장 프로그램을 꺼놓고 테스트할때만 켜놓는다.
다른 스크린리더 확장 프로그램들은 어떻게 사용하는지 몰라서 불편해도 이 확장 프로그램으로 계속 쓰고있다..
✏️ 스크린리더 테스트하기
참고 : 접근 가능한 숨김 텍스트, [velog] 웹 접근성을 고려하여 텍스트 숨기기(written by Lee chae min)
등을 공부하고, 간단하게 정리한 내용입니다. 잘못된 부분이나 문제되는 점이 있으면 댓글 부탁드립니다.
🔅 멋쟁이사자처럼 프론트엔드 4기 파이널 프로젝트
📝 당근마켓 클론코딩
🧑🏻💻 작업 인원 : 5인
🕑 프로젝트 기간 : 23.03.10 ~ 03.28
🔧 기술 스택
• Toolchains : Vite
• Style : Styled Component
• 상태 관리 : Recoil
• Severless : Firebase