[JS / jQuery / CSS] 다양한 방법으로 자동스크롤 구현하기 (원페이지 스크롤)

미니프로젝트를 진행하면서 첫 접속시 보이는 영역 → 멤버 소개 카드가 있는 영역으로 사용자가 끝까지 스크롤을 내리지 않아도 자동으로 스크롤이 내려갈 수 있도록 기능을 구현했다.

 

우선 처음에 기획한 내용은 다음과 같았다.

  • 버튼을 클릭했을 때 멤버 소개 카드가 있는 영역으로 자동 이동
  • 느림-빨라짐-느려짐 속도가 변하며 자연스럽게 출발/도착한다.

window.scrollTo()

프로젝트에서 사용한 방법이다. behaviour: smooth 속성을 지정하여 부드럽게 스크롤 이동이 가능하지만 scrollTo() 만으로는 속도조절을 할 수 없다고 하여 requestAnimationFrame()을 이용해 다음 프레임의 스크롤 위치를 계산하고 scrollTo로 이동시키는 방법을 사용했다. 시간의 흐름에 따른 스크롤 위치를 지정해주는 방식이기에 원했던 속도 변화 또한 구현할 수 있었다.

scrollTo() 정리

 

중간에 자동 스크롤 가능한 상황인지 판단하는 방법에서 헤매 생각보다 시간이 오래걸렸다. 우리팀 발표를 진행하고 튜터님께 이 기능이 원페이지 스크롤이고, css scroll-snap-type으로 좀 더 편하게 구현할 수 있다고 피드백을 받았다.

다른 팀의 발표를 보며 jQuery 메소드로도 구현 가능하다는 것을 알게되어 두가지 방법도 이용해보았다.

 

 

animate({ scrollTop: "위치" }, 시간, "ease 종류");

jQuery 메소드다! 위치는 물론 이동 시간도 지정할 수 있고, jQuery UI를 임포트하면 easing 효과도 선택할 수 있다. 이래서 라이브러리를 사용하는구나 하고 몸소 느낄 수 있었다..

물론 JS에는 조금 더 익숙해진 것 같다 ㅎㅎㅎㅎ

 

적용 방법

// import
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

// 움직임 구현해야할 부분
$('html, body').animate({ scrollTop: `${stopPosition}` }, 1000, 'easeInOutCubic');

 

 

scroll-snap-type

CSS를 사용한 방식이다. 튜터님이 언급하기도 하셨고 원페이지 스크롤을 검색했을 때 가장 많이 사용하는 방법인 것 같다. 하지만 속도 조정이나 easing 효과 지정은 불가하다!

 

적용 방법

1) 스크롤 스냅을 적용할 부모 컨테이너 내부에 자식 요소들을 만들어준다.

2) 부모에 scroll-snap-type 속성을 지정한다.

  • 첫번째 인자: 스냅이 적용될 축 지정
    • x, y, block, inline, both
  • 두번째 인자: 스냅 적용 방식
    • none: 스냅하지 않음
    • proximity: 현재 스크롤 위치가 다음 스냅 위치에 가까워질 때 스냅 적용
    • mandatory: 스크롤 위치가 스냅 기준 위치와 일치할 때 다음 스냅 위치로 이동

3) 자식에 scroll-snap-align 속성을 지정한다.

  • 스냅된 영역에서 자식요소가 위치할 기준을 지정
    • start: 스냅 영역에서 시작점에 정렬
    • end: 스냅 영역의 마지막에 정렬
    • center: 스냅 영역에서 가운데정렬
/* 부모 컨테이너 */
.mainContainer {
  overflow: scroll;  /* auto 혹은 scroll */
  scroll-snap-type: y mandatory;
  height: 100vh;
}

/* 자식1 */
.titleContainer {
  width: 100vw;
  height: 100vh;
  
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

/* 자식2 */
.blueZone {
  width: 100vw;
  height: 100vh;
  
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

 

주의사항

* 부모의 높이를 자식의 합보다 작게 설정

처음엔 부모의 height를 지정하지 않았는데, 아마 부모 컨테이너에서 overflow 발생하지 않음 → 스크롤 동작 X → 스크롤 스냅 X 영향이지 않을까 싶다..

 

scroll-snap-type이 동작하지 않을 때 html, body에 overflow: hidden을 적용하라는 글들이 많던데 나는 이 경우에 해당하지는 않았다.