본문 바로가기

웹 개발/React

React) fullpage.js처럼 CSS scroll-snap 속성으로 스크롤 조작 완료 시 특정 위치/오프셋 설정하기

scroll-snap

 

fullPage scroll snapping. Create full screen pages fast and simple

Mouse wheel snap to sections. Fast and simple to use.

alvarotrigo.com

위 fullpage.js 확장 프로그램 예시처럼 사용자가 스크롤을 조작하면 자연스럽게 특정 위치 (예를 들면 어떤 컴포넌트의 최상위) 에 정확하게 이동한다면 사용자 경험이 향상될 거라 판단해서 기존에 하고 있는 프로젝트에 이 기능을 추가하려고 했습니다.

그러나 fullpage.js 확장 프로그램은 유료라서 다른 방법을 찾다가 발견한 방법은 CSS의 scroll-snap 속성을 이용하는 것입니다. 

scroll-snap에 대한 설명은 링크 를 참조하세요.

 


source code

  • 다음은 scroll-snap을 이용해서 스크롤을 마친 후 자동으로 각 컴포넌트 상단에 위치가 이동하도록 정렬하는 기능을 사용할 페이지의 인덱스 컴포넌트 입니다. 
import React from 'react';
import styled from 'styled-components';

import exampleComponent1 from './component/exampleComponent1';
import exampleComponent2 from './component/exampleComponent2';
import exampleComponent3 from './component/exampleComponent13';


const StyledBox = styled.div`
    .container{ 
        scroll-behavior: smooth;
        height: 100vh;
        scroll-snap-type: y mandatory;
        scroll-padding-top: 10px;
        overflow-y: scroll;
    }
    .container::-webkit-scrollbar { width: 0; background: transparent;}
    .container > div {
        scroll-snap-align: start;
    }
`;
const Example = () => {

    return (
        <StyledBox>
            <div className='container'>
                <div><exampleComponent1/></div>
                <div><exampleComponent2/></div>
                <div><exampleComponent3/></div>
            </div>
        </StyledBox>
    );
}

export default React.memo(Example);
  • 저는 styled-component를 설치해서 전체 페이지에서 사용할 수 있도록 StyledBox를 만들어 전체에 적용가능하도록 최상단에 해당 컴포넌트를 위치시키는데 굳이 설치하고 싶지 않으시다면 그냥 css 파일을 따로 만들어서 하셔도 됩니다. 
$ npm install styled-components --save
  • 전체 페이지 컨테이너에 클래스 이름을 설정해서 해당 div에 scroll behavior, 높이 등을 설정하고, scroll-snap-type을 mandatory로 설정해주어야 합니다. y는 세로로 적용한다는 것을 의미하고, x 값을 주면 수평으로 scroll snap이 적용됩니다. mandatory가 아닌 default 값을 사용자의 스크롤 그 자체에 우선권을 주기 때문에 스냅 포인트가 적용되지 않고 사용자의 조작에만 의존하게 됩니다. 
.container{ 
        scroll-behavior: smooth;
        height: 100vh;
        scroll-snap-type: y mandatory;
        scroll-padding-top: 10px;
        overflow-y: scroll;
}
  • 이때 전체 페이지에 스크롤바가 없어야 더 자연스러운 것 같아 .container::-webkit-scrollbar { width: 0; background: transparent;}로 제거했습니다. 
.container::-webkit-scrollbar { width: 0; background: transparent;}
  • 그리고 컨네이터에 snap 포인트가 될 각 요소들에 scroll-snap-align을 설정해 줍니다. start는 요소 상단으로 스냅 포인트를 지정하는 것입니다. 이외에도 center, end 등이 있습니다. 
.container > div {
        scroll-snap-align: start;
    }