요즘 공부/웹 접근성 스터디

[웹접근성 JS] 3. 하위메뉴 일체형(jQuery -> Vanilla JS) / 초점이동 중심으로..

요즈음 2022. 10. 21. 01:49
320x100

이번 예제는 메뉴를 호버 및 초점 진입시 하위메뉴가 전부 나타나는 UI 디자인이다.
호버했을때 호버한 부분의 하위메뉴의 배경색이 변경되어 시각적으로 구분이 되도록 설정하였다.

특징

1. 배경색

jQuery에서는 마우스 호버에 대한 하위메뉴 배경변경만 설정되어 초접진입시 하위메뉴의 배경색이 변경되지 않는다.
Vanilla JS로 변경할때 초점 진입시에도 지정된 1depth메뉴의 하위메뉴의 배경색을 변경할 수 있도록 보충해 보았다.

(초점 부분 코드 작성할때 정말 애 많이 먹었따...ㅠ 그래서 책 예제에도 언급이 안되어 있었던 건가 싶기도 했다)

2. 하위메뉴에 최대 height값 자동 부여

이번 메뉴에서는 호버시 흰색 바탕이 메뉴의 회색영역의 높이값만큼 모든 하위메뉴가 동일하게 가져야 하는 경우이다.
css로 하나씩 지정하는 방법이 있을 수 있으나, 유지보수를 생각해보면 번거로운 일이 될 것 이다.
따라서 javascript를 이용해 하위메뉴의 높이 값을 뽑아 비교해 가장 큰 값의 높이값을 모든 하위메뉴의 높이값으로 부여하는 로직을 추가해 콘텐츠의 변화가 있어도 따로 작업을 하지 않도록 설정해 두고 있다.
(물론 회색배경색도 값은 높이값을 부여해 준다.)

 

jQuery

 

li.on('mouseover focusin', function(){
  hig = 0;
  gnbdiv.each(function(){
    temp = parseInt($(this).outerHeight());
    if(hig <= temp){
      hig = temp;
    }
  });
  gnbdiv.show().css('height',hig);
  bg.show().css('height',hig);

});
 
Javascript

 

function showMenu(e){
  const eachBg = e.currentTarget.lastElementChild;
  let hig = 0;
  depth2.forEach((div)=> {
    div.style.display = 'block';

    if(div.getAttribute('style')){
      let divHig = div.clientHeight;
      if(hig <= divHig) hig = divHig;
    }
  });

  depth2.forEach((div)=> {
    div.style.background = 'none';
    div.style.height = `${hig}px`;
  });
  eachBg.style.background = '#fff';
  menuBg.style.display = 'block';
  menuBg.style.height = `${hig}px`;
}   
300x250

HTML

구조적으로 간단하게 설명하자면 호버시 나타나는 회색 배경은 header섹션에 포함되어 있지 않고 div태그로 독립적으로 위치해 있다.

 

<header>
....
</header>
<div class='bg_gnb'></div> //<-하위메뉴의 회색 배경

 

이 이유는 UI 상 호버했을 당시 브라우저 화면너비를 충분히 덮어서 나타나야 하는 UI이다.
header를 중앙으로 배치하기 위해 css로 haeder에 너비값을 1160px로 설정하였다.
따라서, header의 자식으로 있게 되면 header의 너비가 최대의 너비인 1160px만큼만 표현이 되어 브라우저 화면 전체 너비만큼 나타나지 않기 때문에 독립적으로 위치시켜 body를 부모요소로 가지도록 설정해 두었다.

jQuery

 

See the Pen 하위메뉴 일체형 - jQuery by yyyhhh (@yyyhhh) on CodePen.

 

Vanilla Javascript

 

See the Pen 하위메뉴 일체형 - vanilla Javascript by yyyhhh (@yyyhhh) on CodePen.


함수 (showMenu / hideMenu)

1. showMenu

하위메뉴가 나타나는 동작하는 함수

특징
1. 하위메뉴와 회색 배경의 높이값을 구해 height값을 부여해 준다.
2. `e.currentTarget`과 `lastElementChild`

 

function showMenu(){
  const eachBg = e.currentTarget.lastElementChild;
  let hig = 0; //가장 큰 높이값을 담을 변수(비교하면서 변경되기때문에 let으로 선언)
  depth2.forEach((div)=> { //forEach를 이용해 Nodelist에 접근 각 하위메뉴에 css를 적용하도록 한다.
    div.style.display = 'block'; //일단 화면에 보여야 높이값을 얻을 수 있다.

    // 하위메뉴 높이값 구하는 조건문
    if(div.getAttribute('style')){ //하위메뉴가 style을 가지고 있다면 실행
      let divHig = div.clientHeight; //각 하위메뉴의 높이값을 구해 변수에 할당
      if(hig <= divHig) hig = divHig;//위에 선언한 hig와 비교하여 하위메뉴 중 높이 값이 큰 값이 결국에는 hig변수에 할당된다.
    }
  });

  //각 하위메뉴의 높이값 지정
  depth2.forEach((div)=> {
    div.style.background = 'none'; //기본적인 값으로 안보이도록 설정
    div.style.height = `${hig}px`;
  });
  //현재 이벤트가 선택된 요소의 자식(하위메뉴)의 배경색 지정
  eachBg.style.background = '#fff';
  //회색 배경에 높이값 및 block 지정
  menuBg.style.display = 'block';
  menuBg.style.height = `${hig}px`;
} 
  • div.style.display = 'block'; 먼저 실행시킨 이유
    • 요소가 display : none인 경우에 아무리 height값을 얻어내려고 해도 화면에 보이지 않기 때문에 값을 얻어 낼 수 없는 상태이다.
    • 그래서 각 하위메뉴의 height값을 얻기 위해서 display : block을 실행한 것

2. hideMenu

지금까지 보였던 것들을 다 없애버도록 동작한다.

function hideMenu(){
  depth2.forEach((div)=> div.style.display = 'none');
  menuBg.style.display = 'none';
}

이벤트

2. 마우스 이벤트

depth1Li.forEach((li)=> li.addEventListener('mouseenter', showMenu));
depth1Li.forEach((li)=> li.addEventListener('mouseleave', hideMenu));

3. 초점 이벤트

depth1Li.forEach((li)=> li.addEventListener('focusin',showMenu));
logo.addEventListener('focusin',hideMenu);
lang.addEventListener('focusin',hideMenu);

초점이 메뉴에 벗어날때 하위메뉴들이 보이지 않도록 하기 위해 메뉴의 앞, 뒤 요소에 초점이 진입할때 hideMenu함수를 실행시켜 하위메뉴가 보이지 않도록 한다.






마치며...

이번 예제는 이 글을 쓰면서 오류를 발견해 부랴부랴 오류(초점진입시 마우스 호버효과가 사라졌다)를 수정하고 전반적인 글을 수정하는 과정이 있었다.
초점이 메뉴에 진입 후 동시에 마우스 호버할 경우 css로 지정된 호버 효과(하위메뉴 색상변경) 동작이 작동하지 않은 오류가 발생했다.

See the Pen 하위메뉴 일체형 - vanilla Javascript by yyyhhh (@yyyhhh) on CodePen.


오류 수정과정에서 불필요한 변수가 어떤 것이 있는지를 확인하게 되고 간결하게 원하는 동작을 실행 시킬 수 있는 코드가 된 것 같다.

나를 제일 애먹게 한건, 초점 진입시에 동작이었다.
초점시 e.target을 이용해 요소를 잡아내려니(초점 이동할때마다 다 다른 요소값이 찍혔다.) 여러가지 고려할 상황이 많아져 초점 이벤트에 어떻게 동작을 시킬 코드 작성에 애를 먹었다.
그러다 e.currentTarget을 이용해 고정된 기준(상위 li)로 하여 동작하도록 하니 초점에 관련된 동작을 작성할 수 있었다.

 

 

 

 

 

  • 스터디에 사용한 책 ↓
 

[웹접근성 스크립트]jQurey → Vanilla JS로 변경 스터디 : 메뉴편

아직까지도 퍼블리싱에 관련되 JS들은 jQurey를 이용해 DOM요소들을 조작하는 경우가 많다. 이제는 jQurey는 레거시로 여겨지면서 Vanilla JS로 코드를 수정하는 작업이 필요함을 느꼈다. 또한, 나도 jQu

storyofdays.tistory.com

 

  • 다른 유형의 메뉴 ↓
 

[웹접근성 JS] 2. 하위 메뉴가 가로형 GNB : 제이쿼리 -> 바닐라 자바스크립트 변경해보자!

이번에는 하위메뉴가 가로로 나타는 메뉴를 jQuery로 마우스 호버 , 초점진입 코드를 Vanilla Javascript로 변경하는 작업을 하였다. jQuery로는 fadeIn()와 fadeOut() 메서드를 이용해 display:none 인 요소를..

storyofdays.tistory.com

 

반응형