README
๐น
scroller-motion
Bringing motion scrolling to React, built upon framer-motion
Installation
To begin you'll want to install scroller-motion as well as the peer dependencies:
npm install scroller-motion framer-motion react
# or
yarn add scroller-motion framer-motion react
Note: Due to the use of hooks the minimum required version of React is 16.8
Usage
Implementing scroller-motion couldn't be easier, simply wrap your page with the <ScrollerMotion>
component. For example in a Next.js app this might look like the following:
/* pages/index.jsx */
import { ScrollerMotion } from 'scroller-motion'
export default () => (
<ScrollerMotion>
<MyComponent />
</ScrollerMotion>
)
Most modern browsers implement an inertia bounce effect to the window while scrolling (upon reaching the start/end). This can cause unwanted visual effects, such as flickering, when using scroller-motion.
To fix this, you can disable overscroll-behavior
in your project with the following CSS:
/* style.css */
html,
body {
overscroll-behavior: none;
}
Props
All props are optional.
disabled
type: boolean
default: false
Completly disables and unmounts the ScrollerMotion
component. Any children will be rendered through a React <Fragment>
in this case (thus falling back to native scrolling).
scale
type: number
default: 1
Extends the scrollable length of the page, giving a "slow scroll" experience. For example if the page content is 1400px in height, <ScrollerMotion scale={1.5} />
would result in a scrollable length of 2100px (height * scale
).
The lowest this value can be is 1
, anything lower will be disregarded and 1
will be used in its place.
spring
type: SpringOptions
default: { mass: 1.25, stiffness: 200, damping: 50 }
The main configuration object for the scroll's spring transform, basically the 2nd parameter to framer-motion's useSpring.
You can disable the spring scroll by passing a falsy value to this prop, for example: <ScollerMotion spring={null} />
.
hook useScrollerMotion
This hook allows you to consume the internal MotionValue
values, returning an object of the following type:
{ scrollX: MotionValue, scrollY: MotionValue, x: MotionValue, y: MotionValue }
scrollX
&scrollY
: The current (spring) scroll position.x
&y
: The current transform (useful for calculating scroll position whenscale
is in-use).
It must be used within a <ScrollerMotion />
, to read the values in the parent component see Motion Listeners.
import { ScrollerMotion, useScrollerMotion } from 'scroller-motion'
import { motion } from 'framer-motion'
const MyComponent = () => {
const { x, y } = useScrollerMotion()
return <motion.div style={{ x, y }}>Hello world</motion.div>
}
export default () => (
<ScrollerMotion>
<MyComponent />
</ScrollerMotion>
)
Motion Listeners
Another approach if you need to read/use the internal MotionValue
values is via the ref
prop on <ScrollerMotion />
. The type of the ref is the same as the object returned from useScrollerMotion
.
For example, if we want to use the y-axis scroll position:
import React, { useEffect, useRef } from 'react'
import { useMotionValue } from 'framer-motion'
import { ScrollerMotion, ScrollerMotionRef } from 'scroller-motion'
export default () => {
const scrollerMotion = useRef<ScrollerMotionRef>()
const scrollY = useMotionValue(0)
useEffect(() => {
const unsubscribe = scrollerMotion.current.scrollY.onChange((v) =>
scrollY.set(v)
)
return () => unsubscribe()
}, [scrollY])
return (
<ScrollerMotion ref={scrollerMotion}>
<MyComponent scrollPosition={scrollY} />
</ScrollerMotion>
)
}
For accessing the native scroll value (without any spring motion) we suggest using framer-motion's useViewportScroll
.
Recipes
- Scroll to hash: Custom hook for handling scrolling to an element via a
#hash
anchor.
About
Scroller-motion was born from the need for motion/smooth scrolling in a couple of React projects. Given the fact that we were already using the beloved framer-motion
for the rest of the animations & transitions, we decided to try it out for page scrolling too - and the results were impressive! Time for an emoji list:
- ๐ Configurable motion via the
spring
prop - ๐ "Slow scroll" via the
scale
prop - ๐ Subscribe to the scroll values with
useScrollerMotion
- โ๏ธ SSR compatible
- ๐ค Fully typed w/ TypeScript
- ๐ฃ Built around React hooks
- โ๏ธ Only 2.2kb gzipped
It's still considered a beta
release, with a public roadmap for the stable v1 available here.
Note: Currently scroller-motion only supports motion scrolling on the main window/body. The stable release should allow for motion scrolling on any DOM element.
Contributing
These are the current scripts available for development:
# Start Storybook
npm run start
# Build dist files
npm run build
# Build static Storybook
npm run build:storybook
# Apply Prettier formatting
npm run prettier:format
# Check Prettier formatting
npm run prettier:check
# Run tests
npm run test
License
Released under the MIT License.
Authored and maintained by Wombak with help from contributors.
wombak.xyz ยท GitHub @wombak ยท Twitter @wombak_xyz