@lifarl/react-scroll-snap-slider
Version:
A performant React Slider / Carousel Component with CSS Scroll Snapping, Intersection Observer and Accessibility.
138 lines (107 loc) • 4.86 kB
Markdown
A performant React Slider / Carousel Component with CSS Scroll Snapping, Intersection Observer and Accessibility.

[](https://badge.fury.io/js/%40lifarl%2Freact-scroll-snap-slider)

Have a look at the ***[Demo](https://lifarl.github.io/react-scroll-snap-slider/)*** for the different variations.

```
yarn add @lifarl/react-scroll-snap-slider
```
> Note: From v3.0.0, this library ships plain CSS (no styled-components). There are no styling peer dependencies.
## Usage
```tsx
import { Slider } from '@lifarl/react-scroll-snap-slider';
<Slider>
<div>Foo</div>
<div>Bar</div>
<div>Baz</div>
</Slider>
```
See also examples in `App.tsx`
- Import once at app entry: `import '@lifarl/react-scroll-snap-slider/styles.css'`.
- All classes are prefixed with `.scs-` to avoid global leaks.
- Theming uses CSS variables set on any parent (or the component root):
- `--scs-gap` (default `8px`)
- `--scs-arrow-bg` (default `#fff`)
- `--scs-arrow-padding` (default `0.5em`)
- `--scs-arrow-radius` (default `4px`)
- `--scs-arrow-color` (default `#676767`)
- `--scs-arrow-size` (default `22px`)
- `--scs-scroll-behavior` (default `smooth`)
- `--scs-snap-type` (default `x mandatory`) — set to `x proximity` to reduce snap sensitivity on Chrome/Android
- `--scs-snap-stop` (default `normal`) — set to `always` to prevent skipping multiple slides per gesture
- `--scs-touch-action` (default `pan-x`) — adjust to `auto` if you need vertical gestures over the slider
- `--scs-overscroll-behavior` (default `auto`) — set to `contain` to prevent scroll chaining to parent
Slots and class overrides are supported via `classes` on the `Slider` component:
```tsx
<Slider
classes={{
root: 'my-carousel',
slider: 'my-slider',
list: 'my-list',
slide: 'my-slide',
nav: 'my-nav',
navPrev: 'my-nav-prev',
navNext: 'my-nav-next',
arrow: 'my-arrow',
}}
>
{...}
</Slider>
```
Firing tracking events on css based sliders can be done with the intersection observer. Pass `onSlideVisible` to the Carousel and it will fire when a slide enters the viewport without triggering a rerender.
```typescript
onSlideVisible?: (index: number) => void // Callback that is triggered when a slide gets visible by a threshold of 0.5
renderCustomArrow?: ({
direction,
ref,
onClick,
}: CustomArrowProps) => JSX.Element // In case you want to use your own arrow design and logic
slidesPerPageSettings?: SlidesPerPageSettings // optionally for setting fixed amounts of slides for different viewports (min-width: 512px / 753px / 1232px)
slideWidth?: number // optionally for setting a fixed slide width
onScrollStart?: () => void // callback that triggers at the beginning of the scroll event
onScrollEnd?: (index: number) => void // callback that triggers at the end of the scroll event
children: React.ReactNode // put your slides here :)
className?: string // root class override
classes?: Partial<{
root: string
slider: string
list: string
slide: string
nav: string
navPrev: string
navNext: string
arrow: string
}>
```
This lib does not include scroll snap polyfills to support older browsers like ie11. You would need to add them yourself. For more information see [here](https://github.com/PureCarsLabs/css-scroll-snap-polyfill).
Mobile browsers implement different scroll-snap heuristics. If the slider feels “too sensitive” on Android/Chrome (small flicks advance a slide, or gestures skip multiple slides), you can tune behavior via CSS variables:
```css
/* Apply to your slider root */
.my-slider {
/* Reduce sensitivity */
--scs-snap-type: x mandatory; /* default */
/* Avoid skipping multiple slides */
--scs-snap-stop: always;
/* Optional axis + scroll chaining controls */
--scs-touch-action: pan-x; /* default */
--scs-overscroll-behavior: contain; /* keep scroll inside slider */
}
```
Usage:
```tsx
<Slider classes={{ root: 'my-slider' }}>
{...}
</Slider>
```
Notes:
- `x proximity` only snaps when near a snap point, which typically reduces accidental snaps on Android compared to `mandatory`.
- `scroll-snap-stop: always` ensures the browser does not skip over intermediate slides during a fast flick.
- If you need vertical page scrolling to take priority when swiping over the slider, set `--scs-touch-action: auto` on the slider root.