문제 상황
문제 상황은 다음과 같다.
검색 input안의 아이콘을 연속클릭하면 검색창이 왔다 갔다한다.
문제 원인
HTML, CSS, JS 의 코드는 다음과 같다.
HTML
<div class="search">
<input type="text" />
<span class="material-icons">search</span>
</div>
header .sub-menu .search input {
...
/* transition 의 default 값은 all 이지만 아래처럼 width 속성만 지정할 경우 transition 이 width 에만 적용돱니다. */
transition: width 0.4s;
}
header .sub-menu .search input:focus {
width: 190px;
border-color: #669900;
}
/**
* 검색창 제어
*/
// 검색창 요소(.search) 찾기.
const searchEl = document.querySelector('.search');
const searchInputEl = searchEl.querySelector('input');
// 검색창 요소를 클릭하면 실행.
searchEl.addEventListener('click', function () {
console.log('click');
searchInputEl.focus();
});
// 검색창 요소 내부 실제 input 요소에 포커스되면 실행.
searchInputEl.addEventListener('focus', function () {
console.log('focus');
searchEl.classList.add('focused');
searchInputEl.setAttribute('placeholder', '통합검색');
});
// 검색창 요소 내부 실제 input 요소에서 포커스가 해제(블러)되면 실행.
searchInputEl.addEventListener('blur', function () {
console.log('blur');
searchEl.classList.remove('focused');
searchInputEl.setAttribute('placeholder', '');
searchInputEl.value = '';
});
동작을 제대로 이해하기 위해서는 이벤트 버블링, 이벤트 위임에 대해 알아야한다. 나는 캡틴판교님의 글을 보고 공부했다.
동작 흐름
1. Search 아이콘을 선택하면 blur 이벤트리스너 가 동작한다.
2. 또한 class="search"를 가지는 부모요소에 click 이벤트리스너가 등록되어있다. 따라서 자식 요소인 search 아이콘을 클릭했을 때 이벤트 버블링이 발생하고 부모의 click 이벤트가 발생한다. 이렇게 부모에 click 이벤트를 두어 자식에는 따로 click 이벤트를 등록하지않는 방법을 이벤트 위임이라고 한다.
3. click 이벤트가 발생과 동시에 focus 이벤트가 발생하게 되므로 동영상과 같은 검색창이 열렸다 닫히는 UI 현상이 발생한다.
해결 방법
css 만 바꿔주면 해결이 가능하다.
header .sub-menu .search .material-icons {
...
transition: 0.2s;
}
header .sub-menu .search.focused .material-icons {
opacity: 0;
visibility: hidden;
}
transition 의 속도를 더 짧게 바꿔주고, visibility 를 사용하여 아이콘이 보이지 않도록 하면된다.
만약 스크린 리더 사용자를 위해 접근성 트리까지 고려해야했다면 a11y-hide css 를 사용했을 것 이다. 왜냐하면 visibility 는 접근성 트리에 존재하지 않기 때문이다.
하지만 이 경우에는 간단한 아이콘이기 때문에 접근성까지 고려할 필요는 없다고 생각된다.
혹시나 궁금할 분들은 위한 a11y-hide 를 사용한 코드 (결과는 동일합니다.)
header .sub-menu .search .material-icons {
...
transition: 0.2s;
}
header .sub-menu .search.focused .material-icons {
position: absolute !important;
clip: rect(1px, 1px, 1px, 1px);
-webkit-clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
padding: 0 !important;
border: 0 !important;
height: 1px !important;
width: 1px !important;
overflow: hidden;
}
추가적으로 더 간편한 방법을 알게되어 기록한다.
focus 되었을 때 pointer-events: none 으로 속성 값을 주면, 아이콘을 클릭할 수 없다.
header .sub-menu .search .material-icons {
...
transition: 0.2s;
}
header .sub-menu .search.focused .material-icons {
...
pointer-events: none;
}
동영상이라 볼 수 없지만 마우스로 계속 클릭중이다.
'개발 > 개발 버그' 카테고리의 다른 글
토스트 메세지 구현중에.. (0) | 2023.05.20 |
---|---|
AWS 과금 해결과정 (RDS 과금) (0) | 2023.05.15 |
hover에서 벗어날 때 transition 바로 종료 (0) | 2023.05.09 |