스크롤 감지하여 헤더 보이거나 숨기기

sealkim·2023년 4월 3일
0

1. fixed된 헤더의 불편함

많은 웹사이트에서 네비게이션 탐색에 도움을 주기 위해 상단의 헤더를 position:fixed와 같이 고정해 두곤 한다. 그러나 고정된 헤더에 높이가 긴 콘텐츠를 포함하고 있는 경우 사이트의 사용자 경험을 떨어뜨리는 요인이 될수 있다. 특히 모바일과 같은 뷰포트가 작은 기기들에서는 더욱 그러하다.

기존의 단순히 고정된 형태의 헤더 디자인보다는 사용자의 스크롤 방향에 따라 헤더 부분을 보여주거나 감춤으로써, 사용자의 의도에 맞게 디자인을 제공하는 것이 좋다.

  • 사용자의 스크롤이 아래로 향한다면 -> 콘텐츠 탐색으로 간주
  • 스크롤이 위로 향한다면 -> 처음으로 돌아가거나 네비게이션을 찾는것으로 간주


HTML, CSS은 간단하다고(?) 생각하니 넘어가고 js에 대해 설명하겠다.(header는 fixed 되어 있는 상태!)

<방법1>

⬜️ CSS

/*생략*/

.nav-up {
    top: -40px; // 줄여질 헤더 높이
}

⬜️ JS

* jQuery 사용

var didScroll;

var lastScrollTop = 0;
var delta = 5; //동작의 구현이 시작되는 위치
var navbatHeight = $('.header').outerHeight(); //영향을 받을 요소를 선택

$(window).scroll(function(evnet){ //스크롤 시 사용자가 스크롤했다는 것을 알림
  didScroll  = true;
});

setInterval(function(){ //hasScrolled()를 실행하고 didScroll 상태를 재설정
  if (didScroll) {
    hasScrolled();
    didScroll = true;
  }
}, 200);

function hasScrolled(){
  const st = $(this).scrollTop();

  if(Math.abs(lastScrollTop - st) <= delta)
    return;

  if(st > lastScrollTop && st > navbatHeight){
    // Scroll Down
    $('.header').addClass('nav-up');
    //$('header').removeClass('nav-down').addClass('nav-up');
  } else {
    if(st + $(window).height() < $(document).height()) {
      // Scroll Up
      $('.header').removeClass('nav-up');
      //$('header').removeClass('nav-up').addClass('nav-down');
    }
  }
  lastScrollTop = st
}
.nav-up {
    top: -55px;
}

✍️ 코드 분석

$(window).scroll 에 의해 스크롤 이벤트를 감지하여 didScroll 의 변수 값을 true로 설정한다. 매 250ms 마다 didScroll의 변수 값을 체크하여 동작을 구현하고 다시 didScroll의 변수 값을 false로 설정한다. 이는 스크롤될때 마다 전체의 동작을 구현하는 것보다 변수를 설정하는 것이 브라우저의 부하를 덜 수 있는 방법이 된다.

var st = $(this).scrollTop();: 접근하기 쉽게 현재 스크롤 위치를 저장
if (Math.abs(lastScrollTop — st) <= delta): 설정한 delta 값보다 더 스크롤 되었는지 확인

if(st > lastScrollTop && st > navbatHeight){
    $('.header').addClass('nav-up');
  } else {
    if(st + $(window).height() < $(document).height()) {
      $('.header').removeClass('nav-up');
    }

헤더의 높이보다 더 스크롤이 되었는지 확인하고 스크롤의 방향이 위인지 아래인지 확인

lastScrollTop = st: 현재 스크롤 위치 저장

✏️ 추가

  • && = And 연산자
  • Math.abs : 인자값에 대한 절대값을 반환하는 함수

* 참고 글 https://webdir.tistory.com/481


<⭐️ 방법2>

처음엔 위의 방법으로 했으나 setInterval()함수가 목적에 맞지 않다고 생각하여 빼고 다시 작성했다.

⬜️ JS

$(function(){
  let lastScrollTop = 0;
  const delta = 15;

  $(window).scroll(function(event){
    const st = $(this).scrollTop();
    if(Math.abs(lastScrollTop - st) <= delta) return;
    if((st > lastScrollTop) && (lastScrollTop > 0)) {
      $('.header').addClass('nav-up');
    }else {
      $('.header').removeClass('nav-up');
    };
    lastScrollTop = st;
  });
});

✍️ 코드 분석

  • let lastScrollTop = 0;
    : 스크롤 바가 맨 위에 위치할 때의 scrollTop 값을 저장하는 변수(변한는 값이기 때문에 let)
  • const delta = 15;
    : 스크롤 이벤트를 발생시키기 위한 최소 delta값을 설정하는 변수
  • const st = $(this).scrollTop();
    : 현재 스크롤 위치의 scrollTop 값을 변수 st에 저장
  • if(Math.abs(lastScrollTop - st) <= delta) return;
    : 마지막 스크롤 위치와 현재 스크롤 위치의 차이가 delta값 이하이면 함수를 종료(스크롤 위치가 변하는 동안 불필요한 클래스 추가/제거 방지)
  • if((st > lastScrollTop) && (lastScrollTop > 0)){}
    : 현재 스크롤 위치가 이전 스크롤 위치보다 아래에 있고, 이전 스크롤 위치가 0보다 클 경우
  • lastScrollTop = st;
    : 현재 스크롤 위치를 마지막 스크롤 위치로 저장

간단히 설명하면 윈도우 객체에서 스크롤 이벤트가 발생할때 마다, 현재 스크롤 위치를 확인하여 이전 스크롤 위치와 일정 수준 이상 차이가 나면 .header에 nav-up클래스를 추가하거나 제거하는 역할을 하는 코드이다.

profile
📚 Coding Notes

0개의 댓글