본문 바로가기
JavaScript

[JavaScript] 스크롤 위치에 따라 메뉴바 변경하기

by teamnova 2023. 8. 10.
728x90

안녕하세요. 이번시간에는 자바스크립트를 활용해 스크롤 위치에 따라 메뉴바를 다르게 보이게 하는 법을 알아보려 합니다. 

 

웹사이트에서는 디자인에 따라 하나의 메뉴바만 있는게 아니라 중간 중간에 메뉴바가 있는 경우도 있는데요.

 

위의 사이트처럼 스크롤을 하다 어느 정도 위치부터는 중간에 위치한 메뉴바가 상단에 고정되는 형태를 만들어보려 합니다.

 

우선 기능을 구성하는 ui들입니다.

<nav id="top-menu">          
    <ul>
        <li><a href="#">메뉴1</a></li>
        <li><a href="#">메뉴2</a></li>
        <li><a href="#">메뉴3</a></li>
        <li><a href="#">메뉴4</a></li>
    </ul>
</nav>
<div id="content"></div>
<nav id="middle-menu">
    <ul>
        <li><a href="#">메뉴5</a></li>
        <li><a href="#">메뉴6</a></li>
        <li><a href="#">메뉴7</a></li>
        <li><a href="#">메뉴8</a></li>
    </ul>
</nav>
<div id="content2"></div>

예제에서는 top-menu (맨 위 메뉴), content (첫번째 content 영역), middle_menu (중간의 메뉴), content2 (두번째 content 영역)으로 구성되어 있습니다.

이 포스팅에서는 메뉴바의 위치에 따른 변화가 중점이므로 메뉴바 ui의 경우 비교적 단순하게 구성하였습니다.

메뉴바 구현을 위한 좀 더 자세한 정보는 아래 링크를 참고해 주세요.

https://stickode.tistory.com/306

 

[HTML / CSS] 드롭다운 메뉴바 만들기

안녕하세요 오늘은 웹페이지에서 흔히 볼 수 있는 드롭다운 메뉴바를 만들어 보겠습니다. 웹페이지 상단에 메뉴바가 생성되고 Categories, Services 메뉴는 드롭다운 기능이 있습니다. 마우스 포인터

stickode.tistory.com

 

 

다음 css 코드입니다.

ul {
        
    /* ul의 디폴트 속성 제거 */
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;       
  }

  li {
    float: left;
  }

  li a {
    display: block;
    color: white;
    text-align: center;
    padding: 14px 16px;
    /* li의 디폴트 속성 제거 */
    text-decoration: none;
  }

  li a:hover {
  	/* 마우스 커서가 올라갈 때 색상 변환 */
    background-color: #111;
  }

    /* 맨 위 메뉴바의 스타일 */
    #top-menu {
      /* 상단 고정 */
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      background-color: #333;   
      /* 디폴트로 불투명하게 설정 */
      opacity: 0.5;            
    }

    #top-menu:hover {

        opacity: 1; /* 또렷하게 보이도록 불투명도를 1로 변경 */   
    }

    /* 중간 메뉴바의 스타일 */
    #middle-menu {        
      left: 0;          
      width: 100%;
      background-color: #666;   
      /* 디폴트로 불투명하게 설정 */
      opacity: 0.5;               
    }

    #middle-menu:hover {
        opacity: 1; /* 또렷하게 보이도록 불투명도를 1로 변경 */
    }

    /* 콘텐츠 영역의 스타일 */
    #content {

      height: 400px;
      background-color: #eee;

    }
    #content2 {
      height: 1000px;
      background-color: #eee;         
    }

우선 첫번째 메뉴바를 position : fixed 속성으로 상단에 고정시켰고, 예시로 들었던 웹사이트처럼 hover 된 경우에만 메뉴바가 뚜렷하게 보이도록 처리하였습니다.

 

다음으로 자바스크립트 코드입니다.

// 맨 위 메뉴와 중간 메뉴 변수 할당
const topMenu = document.getElementById("top-menu");
const middleMenu = document.getElementById("middle-menu");

// 중간 메뉴바의 위치 계산            
let middleMenuTop = middleMenu.offsetTop;
let middleMenuHeight = middleMenu.offsetHeight;

// 스크롤 이벤트 핸들러
window.addEventListener("scroll", function() {

    // 스크롤하는 높이를 체크
    let scrollPosition = window.scrollY;

    // 스크롤하는 위치가 중간 메뉴보다 클 경우 (중간 메뉴보다 더 아래로 스크롤 할 경우)
    if (scrollPosition >= middleMenuTop) {
        // 맨 위 메뉴바의 display 속성을 none으로 변경

        topMenu.style.display = "none";

        // 중간 메뉴바의 position을 맨 위 메뉴바의 속성으로 변경                  
        middleMenu.style.position = "fixed";
        middleMenu.style.top = "0";
        middleMenu.style.left = "0";
        middleMenu.style.width = "100%";
        middleMenu.style.opacity = 1;

        // 중간 메뉴바의 투명도 이벤트 리스너 해제
        middleMenu.removeEventListener("mouseover", setOpacityToOne);
        middleMenu.removeEventListener("mouseout", setOpacityToHalf);
    } else {

        // 맨 위 메뉴바의 display 속성을 block으로 변경                    
        topMenu.style.display = "block";

        // 중간 메뉴바를 다시 원래 속성으로 변경
        middleMenu.style.position = "static";     
        middleMenu.style.opacity = 0.5;     

        // 중간 메뉴바의 투명도 이벤트 리스너 등록
        middleMenu.addEventListener("mouseover", setOpacityToOne);
        middleMenu.addEventListener("mouseout", setOpacityToHalf);
    }
});

// 투명도 1로 설정
function setOpacityToOne() {
    middleMenu.style.opacity = "1";
}

// 투명도 0.5로 설정
function setOpacityToHalf() {
    middleMenu.style.opacity = "0.5";
}

우선 scroll 이벤트 안에서 현재 스크롤되는 지점의 높이를 실시간으로 체크합니다.

그러다 스크롤 되는 지점이 중간 메뉴바를 넘어갈 경우에는 맨 위 메뉴바를 없앤 뒤 중간 메뉴바의 속성들을 맨 위 메뉴바의 속성과 일치하게 바꿔줍니다.

반대로 다시 스크롤이 위로 올라갈 경우에는 중간 메뉴바를 원래 속성으로 변경하고 맨 위 메뉴바를 다시 보이게 처리합니다.

 

처음 스크롤 위치가 중간 메뉴바를 넘어갈 때 중간메뉴바를 상단에 고정시키면서 투명도를 1로 바꾸기 때문에 이때 css에서 hover 속성으로 투명도 여부를 지정하는 코드가 사라집니다.

다시 중간 메뉴바에 hover 여부에 따라 투명도를 조정하는 로직을 반영하기 위해 setOpacityToOne/Half라는 별도의 함수를 만들어서 조건에 따라 hover 속성이 적용되도록 하기 위해 자바스크립트를 활용하여 수동으로 처리한 코드입니다.

 

 

결과 영상입니다.