Swipeable views for React using CSS scroll snap
npm install react-scroll-snapper


A library for creating swipeable views using CSS scroll snap.
Originally developed as a replacement for the react-swipeable-views which is not compatible with latest React and no longer maintained.
If you don't need to control the current page from JavaScript, you can use a simple scrollable div with following styles:
``css
.ScrollSnapper {
display: flex;
scroll-snap-type: x mandatory;
overflow-x: scroll;
scroll-behavior: smooth;
}
.ScrollSnapper > * {
box-sizing: border-box; / if not set globally /
width: 100%;
flex-shrink: 0;
scroll-snap-align: center;
scroll-snap-stop: always;
}
`
Then use it in your JSX:
`jsx`
function App() {
return (
Page 1
Page 2
Page 3
)
}
Here are the same styles in Tailwind CSS:
`jsx
function App() {
return (
className={
"flex snap-x snap-mandatory overflow-x-scroll scroll-smooth " +
":w-full :flex-shrink-0 :snap-center :snap-always"
}
>
Page 1
Page 2
Page 3
To implement tabs which scroll to different pages when clicked, you can use anchors which point to the page ids:
`jsx
function App() {
return (
<>
Page 1
Page 2
Page 3
>
)
}
`If you don't need to react to a page change from user, but want to scroll to a page programmatically, you can use the
scrollIntoView method on the page element:`tsx
function App() {
const scrollSnapperRef = useRef(null) return (
<>
Page 1
Page 2
Page 3
>
)
}
`Importing styles
You can import only the styles from this library and use them with the snippets above.
Import the styles in your HTML:
`html
`or in your CSS:
`css
@import "react-scroll-snapper/index.css";
`or in your JavaScript if your bundler supports it:
`js
import "react-scroll-snapper/index.css"
`> [!TIP]
>
> You can also import the styles from
esm.sh or similar CDN.
>
> That way you don't need to install this library in your node_modules and you can use the styles without any build tools.
>
> `html
>
> `Using the React component
You can use the
ScrollSnapper component to easily bind the current page index to your React state:`jsx
import "react-scroll-snapper/index.css"
import { ScrollSnapper } from "react-scroll-snapper"
import { useState } from "react"function App() {
const [pageIndex, setPageIndex] = useState(0)
return (
Page 1
Page 2
Page 3
)
}
`> [!TIP]
> Consider simply copy-pasting the component's source code into your project.
> It's very small and easy to maintain and doesn't have any dependencies.
> You can also add any additional features you need yourself.
example for a more complete example.Tips
$3
Add
scrollbar-width: none to the container:`css
.noScrollbar {
scrollbar-width: none;
}
`For Safari:
`css
.noScrollbar::-webkit-scrollbar {
display: none;
}
`Usage:
`jsx
...
`$3
You can set
max-height on the container and add overflow-y: scroll to the pages.`css
.scrollChildren {
max-height: 384px;
}.scrollChildren > * {
overflow-y: scroll;
}
``jsx
...
`Developing
-
npm start: Start the example app using vite.
- npm run prepare: Build the library using tsc.
- npm test: Check code using tsc.API
ScrollSnapper()
> ScrollSnapper(
props): ElementScroll Snapper React component.
$3
| Parameter | Type |
| --------- | -------------------------------------------------------------------------------------- |
|
props | ScrollSnapperProps & HTMLProps\<HTMLDivElement\> |$3
Element---
ScrollSnapperProps
Props for the ScrollSnapper component.
$3
| Property | Type | Description |
| --------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
index | number | The current page index. Can be changed to programmatically scroll to a different page. |
| onIndexChange | (index: number, target: HTMLDivElement) => void | A callback which runs after the container is scrolled to a page. This will run even if the user scrolled but ended up on the same page. Scrolling triggered by changing the index` prop will also trigger this callback after the animation is finished. |