npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-parallax-carousel

v1.1.0

Published

A smooth spring-physics parallax carousel for React — cinematic card transitions with masked parallax images

Readme

react-parallax-carousel

Live Demo

A smooth, spring-physics parallax carousel for React. Cards act as overflow: hidden mask windows over oversized images that shift at a different speed — pure translateX parallax.

  • Overdamped spring physics — cinematic glide
  • Only the immediately adjacent cards peek in from each edge; all others stay hidden
  • Asymmetric peek widths — right peek can be larger than left for a "what's next" hint
  • Masked parallax: large image revealed by the moving card window
  • Chevron arrows on peek cards for clear navigation affordance
  • Click the active slide to follow a link
  • Auto-play with configurable delay
  • Loop / no-loop mode
  • Pointer + touch + keyboard support

Install

npm install react-parallax-carousel

React 17+ is a peer dependency.

Usage

import { ParallaxCarousel } from 'react-parallax-carousel';

const slides = [
  {
    image: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1400',
    tag: 'Landscape',
    title: 'Alpine Silence',
    href: 'https://en.wikipedia.org/wiki/Swiss_Alps',
  },
  {
    image: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=1400',
    tag: 'Nature',
    title: 'Into the Forest',
    href: 'https://en.wikipedia.org/wiki/Forest',
  },
  {
    image: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=1400',
    tag: 'Coastal',
    title: 'Ocean Drift',
    href: 'https://en.wikipedia.org/wiki/Ocean',
  },
];

function App() {
  return (
    <div style={{ background: '#111113', minHeight: '100vh', display: 'flex', alignItems: 'center' }}>
      <ParallaxCarousel
        slides={slides}
        peekLeftVw={10}
        peekRightVw={20}
        title="Discover the World"
        subtitle="Drag to explore"
        loop={true}
        autoPlay={true}
        autoPlayDelay={4000}
        showArrows={true}
        linkTarget="_blank"
        onChange={(index) => console.log('Active slide:', index)}
      />
    </div>
  );
}

Layout Model

The viewport is divided into three regions that always add up to 100 vw:

┌─────────────┬──────────────────────────────────┬──────────────────┐
│ peekLeftVw  │       active card (auto)          │  peekRightVw     │
│   (10 vw)   │    100 - left - right = 70 vw     │   (20 vw)        │
└─────────────┴──────────────────────────────────┴──────────────────┘
  • The previous card is 2 × peekLeftVw wide, so exactly half of it is visible on the left edge.
  • The next card is 2 × peekRightVw wide, so exactly half of it is visible on the right edge.
  • Every other card collapses to zero width and is never visible, no matter how many slides you have.

Slide Object

| Field | Type | Required | Description | |---------|--------|----------|----------------------------------------------------------| | image | string | ✓ | Image URL | | title | string | | Card heading | | tag | string | | Small uppercase label above the heading | | alt | string | | Image alt text (falls back to title) | | id | any | | Stable React key (falls back to array index) | | href | string | | URL opened when the active slide is tapped/clicked |

Props

Layout

| Prop | Type | Default | Description | |----------------|--------|----------|--------------------------------------------------------------------| | slides | array | [] | Array of slide objects (see above) | | peekLeftVw | number | 10 | Visible width of the left peek in vw. Previous card = this | | peekRightVw | number | 18 | Visible width of the right peek in vw. Next card = this | | cardHeight | string | '78vh' | CSS height of each card | | gap | string | '20px' | Gap between cards (use px units) | | borderRadius | string | '24px' | CSS border-radius of cards |

Header

| Prop | Type | Default | Description | |--------------|---------|------------------------|-------------------------| | title | string | 'Discover the World' | Header title text | | subtitle | string | 'Drag to explore' | Header subtitle text | | showHeader | boolean | true | Show or hide the header |

Navigation

| Prop | Type | Default | Description | |----------------|---------|---------------------------|-------------------------------------------------| | initialIndex | number | 0 | Starting slide index | | loop | boolean | true | Wrap around at the first and last slide | | showArrows | boolean | true | Show chevron arrows on the prev/next peek cards | | arrowColor | string | 'rgba(255,255,255,0.9)' | Arrow icon color |

Links

| Prop | Type | Default | Description | |--------------|--------|------------|----------------------------------------------------------------| | linkTarget | string | '_blank' | Browser target for slide href links ('_self' for same tab) |

Auto-play

| Prop | Type | Default | Description | |-----------------|---------|---------|----------------------------------------| | autoPlay | boolean | false | Automatically advance slides | | autoPlayDelay | number | 3000 | Delay between advances in milliseconds |

Physics

| Prop | Type | Default | Description | |-----------------|--------|---------|---------------------------------------------------| | parallaxRange | number | 14 | Image shift range in % (max safe ~18) | | parallaxLerp | number | 0.1 | Image lag smoothing — lower = more luxurious drag | | stiffness | number | 0.022 | Spring stiffness — lower = slower glide | | damping | number | 0.58 | Spring damping — higher = less overshoot | | maxVel | number | 12 | Max release velocity in px/frame | | widthLerp | number | 0.07 | Card width animation speed |

Callbacks

| Prop | Type | Description | |------------|----------|---------------------------------------------------| | onChange | function | (index: number) => void — fires on slide change |

Behaviour Notes

Active slide link: tapping/clicking the active card opens slide.href in linkTarget. Tapping an inactive card navigates to it (does not follow its link).

Peek sizing: peekLeftVw and peekRightVw are the visible widths. The carousel automatically sizes peek cards at those values so exactly half of each card is visible. Making peekRightVw larger than peekLeftVw hints at the upcoming slide:

// 10 vw left peek, 20 vw right peek — right shows twice as much
<ParallaxCarousel slides={slides} peekLeftVw={10} peekRightVw={20} />

One card per side — always: cards beyond the immediate neighbours collapse to zero width with no gap contribution, so no matter how many slides you have, only one card ever peeks in from each edge.

Auto-play: pauses while the user is dragging and resets its timer on every manual navigation.

Loop: when loop={true} (default), navigating past the last slide wraps to the first, and vice versa — including via keyboard and auto-play.

Arrows: the left chevron appears centered on the previous peek card; the right chevron on the next. Both are purely visual — the whole card is the click target.

Slides changing length: animation state is initialised once on mount. If you change the slides array length, use the key prop to remount:

<ParallaxCarousel key={slides.length} slides={slides} />

Styles: a single <style> tag is injected into document.head on first mount and shared across all instances. It's scoped to the .rpc-* class namespace and won't affect your app's global styles.

Keyboard: ArrowRight / ArrowDown advances, ArrowLeft / ArrowUp goes back.

Building from Source

npm install
npm run build   # outputs dist/index.cjs + dist/index.esm.js
npm run dev     # watch mode

License

MIT