tab key를 사용해 header 영역에 있는 검색 버튼을 클릭했을 때 검색 모달창이 정상적으로 나오지만, 모달창의 마지막 요소를 지나면 html 문서에서 모달창 뒤에 오는 요소로 tab이 이동하는 문제가 생겼다. 어디에 focus 되었는지, 검색창을 닫지도 않았는데 뒤에 오는 내용이 맥락없이 읽힐 수도 있다.
tabindex로 tab 순서를 강제로 지정해줄 수는 있다. 하지만 포커스 순서를 제어하는 것은 피하는 것이 좋다. 키보드 포커스가 순서대로 이동하는 것이 아닌 중구난방으로 이동하게 될 경우 혼란을 줄 수 있다. 마크업으로 문서에 요소를 순서에 맞게 배치하는 것이 훨씬 좋다.
현재 보이는 모달창 내에서 tab key가 이동할 수 있도록 하기 위해 focus trap을 적용하였다. esc를 누르면 모달창을 닫을 수 있고, 닫은 후에는 focus의 위치를 원래의 위치(검색 아이콘)에 두었다. shift + tab 으로 이동하더라도 모달창 내에서만 이동하도록 했다.
function openSearchBox() {
focusedElementModal = document.activeElement;
// 포커스 가능한 요소들
let focusableEls = $(searchBox).find(
'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contentditable]',
);
focusableEls = Array.prototype.slice.call(focusableEls);
searchBox.on('keydown', trapTabKey);
const firstTabStop = focusableEls[0];
const lastTabStop = focusableEls[focusableEls.length - 1];
firstTabStop.focus();
searchBox.addClass('active');
$('body').addClass('notscroll');
searchBox.attr('aria-hidden', 'false');
// 포커스 트랩 이벤트
function trapTabKey(e) {
// check Tab key
if (e.keyCode === 9) {
if (document.activeElement === firstTabStop && e.shiftKey) {
e.preventDefault();
lastTabStop.focus();
} else if (document.activeElement === lastTabStop && !e.shiftKey) {
e.preventDefault();
firstTabStop.focus();
}
}
// ESCAPE
if (e.keyCode === 27) {
closeSearchBox();
}
}
}
// 검색창 숨기기
function closeSearchBox() {
searchBox.removeClass('active');
$('body').removeClass('notscroll');
searchBox.attr('aria-hidden', 'true');
focusedElementModal.focus();
}
모달창 내의 포커스 이동을 통제할 수 있었지만, 검색 아이콘을 클릭하고 tab 키를 눌렀을 때 모달창의 첫 번째 요소로 이동하길 바랐으나 검색 아이콘과 형제 요소인 장바구니 아이콘으로 이동해버려서 이 부분은 추후 수정할 예정이다. 기본 뼈대인 마크업을 정확하게 해야 함을 매번 느끼지만 이번에도 다시금 느꼈다.
https://lee-jing.tistory.com/19
https://tarot-story.tistory.com/23