Detect Scroll Position

문제

Header를 position:fixed로 바꾸고 나서 스크롤(Scroll)의 위치를 바꿨을 때 배경이미지 때문에 로고가 정확하게 보이지 않는 현상을 해결하기 위해 만들었다.

배경이미지 때문에 로고가 선명하게 보이지 않는다.

목적

화면의 스크롤을 내렸을 때 미리 설정 해둔 배경 속성을 적용될 수 있도록 상태 클래스(.scrolling--show) 추가/제거 될 수 있도록 한다.

상태클래스를 추가하면서 배경이 어둡게 변한다.

설계

변수 설정

const SCROLL_SHOW_STATE_CLASSMNAME = 'scrolling--show'
const fixedHeaderNode = document.querySelector('.header--fixed')

방법

  1. window.scrollY를 사용해서 어느 위치에서 인터랙션을 적용할지 계산한다.

  2. window에 'scroll' 이벤트를 바인딩한다.

  3. (1)에서 설정한 scrollY 값 이상일 경우 상태클래스 .scrolling--show가 추가/제거 될 수 있도록 toggle() 메서드를 사용한다.

처음에 작성한 코드

const SCROLL_SHOW_STATE_CLASSMNAME = 'scrolling--show'
const fixedHeaderNode = document.querySelector('.header--fixed')

const scrollShowHide = function (target, Ypos = 0) {
  if (window.scrollY >= Ypos) {
    target.classList.toggle(SCROLL_SHOW_STATE_CLASSMNAME)
  }
}

const handleScrollShowHide = function () {
  scrollShowHide(fixedHeaderNode, 30)
}

window.addEventListener('scroll', handleScrollShowHide)

문제점 발견

문제

toggle() 메서드는 추가/제거를 하는 기능을 하기 때문에 해당 코드에서는 scroll을 할 때마다 toggle이 된다. 그렇기 때문에 위와 같은 현상이 나타났다.

해결

add()/remove() 사용하기

const scrollShowHide = function (target, Ypos = 0) {
  if (window.scrollY > Ypos) {
    target.classList.add(SCROLL_SHOW_STATE_CLASSMNAME)
  } else {
    target.classList.remove(SCROLL_SHOW_STATE_CLASSMNAME)
  }
}

개선

  • show와 hide 두 가지 기능이 있는 함수가 아닌 재사용이 가능한 함수로 만들기 위해 show, hide 각각의 기능을 가진 함수를 독립적으로 만들어서 재사용할 수 있도록 했다.

  • 함수 매개 변수에 className을 전달할 수 있도록 해서 SCROLL_SHOW_STATE_CLASSNAME을 두 번 사용하지 않도록 했다.

  • 조건에 contains()을 추가해서 함수가 한 번만 실행될 수있도록 했다. (성능 고려)

const SCROLL_SHOW_STATE_CLASSMNAME = 'scrolling--show'
const fixedHeaderNode = document.querySelector('.header--fixed')

var scrollShow = function (target, Ypos = 0, className) {
  if (window.scrollY >= Ypos && !target.classList.contains(className)) {
    target.classList.add(className)
  }
}

const scrollHide = function (target, Ypos = 0, className) {
  if (window.scrollY < Ypos && target.classList.contains(className)) {
    target.classList.remove(className)
  }
}

const handleScrollShowHide = function () {
  scrollShow(fixedHeaderNode, 30, SCROLL_SHOW_STATE_CLASSNAME)
  scrollHide(fixedHeaderNode, 30, SCROLL_SHOW_STATE_CLASSNAME)
}

window.addEventListener('scroll', handleScrollShowHide)

Last updated

Was this helpful?