Skip to content


Switch branches/tags


npm npm npm downloads

Snap page when user stops scrolling, basically implements CSS Scroll Snap, adding a customizable configuration and a consistent cross browser behaviour.

  • Works in all modern browsers
  • requestAnimationFrame for 60fps
  • Customizable settings (including easing functions)
  • No additional dependencies
  • No extra stylesheet


yarn add scroll-snap

You can also grab a pre-built version from unpkg


createScrollSnap(element, settings, [callback])


element: HTMLElement

The HTML DOM Element to attach the scroll listener to.

settings: Settings

A configuraiton object consisting of one or more of the following keys:

snapDestinationX: string | number

Snap destination for x axis, should be a valid css value expressed as px | % | vw | vh

snapDestinationY: string | number

Snap destination for y axis, should be a valid css value expressed as px | % | vw | vh

timeout: number

Time in ms after which scrolling is considered finished
[default: 100]

duration: number

Duration in ms for the smooth snap
[default: 300]

threshold: number

Threshold to reach before scrolling to next/prev element, expressed as a percentage in the range [0, 1]
[default: 0.2]

snapStop: boolean

When true, the scroll container is not allowed to "pass over" the other snap positions
[default: false]

easing: (t: number) => number

Custom easing function
@param t: normalized time typically in the range [0, 1]
[default: easeInOutQuad]

For reference:

callback: () => void [Optional]

Optional callback to execute once the animation ends.


An object including two handlers to manually attach and remove the scroll event listener

  // attaches the scroll event listener 
  bind: () => void 
  // removes the scroll event listener
  unbind: () => void 


import createScrollSnap from 'scroll-snap'

const element = document.getElementById('container')

const { bind, unbind } = createScrollSnap(element, {
  snapDestinationX: '0%',
  snapDestinationY: '90%',
  timeout: 100,
  duration: 300,
  threshold: 0.2,
  snapStop: false,
  easing: easeInOutQuad,
}, () => console.log('element snapped'))

// remove the listener 
// unbind();

// re-instantiate the listener 
// bind();

Usage with React


git clone
cd scroll-snap
yarn install

Start the testing environment from playground/:

yarn start

Build lib for production:

yarn build