React Scroll Parallax

website·Indexed 33 days ago

https://react-scroll-parallax.v3.damnthat.tv/

React hooks and components for creating scroll-driven parallax effects via WAAPI (v4 beta). Features include the <ParallaxProvider />, <Parallax />, and <ParallaxBanner /> components, as well as the useParallax() hook for implementing custom effects, easing animations, and horizontal scrolling.

Tokens
6.1K
Snippets
35
Records
39
Agent score
49%

What's inside React Scroll Parallax

  1. Implement CSS scroll effects with start and end values

    CSS effects are defined using an array containing a start value, an end value, and an optional third value for easing.

    • Start: The effect begins when the top of the element enters the bottom of the view.
    • End: The effect ends when the bottom of the element exits the top of the view.

    Supported effects include translateX, translateY, rotate, rotateX, rotateY, rotateZ, scale, scaleX, scaleY, scaleZ, and opacity.

    useParallax({
      // Translate Y from -100% to 100% with ease-in
      translateY: [-100, 100, 'ease-in'],
      // Scale from 0 to 1 with a custom cubic-bezier
      scale: [0, 1, 'cubic-bezier(0.2, -0.67, 1, -0.62)'],
    });
  2. Create a parallax banner using ParallaxBanner

    The <ParallaxBanner> component creates a container for layered parallax elements. It hides overflow and allows for multiple layers of images or custom markup.

    Critical Requirement: You must provide a height or aspectRatio via the style prop (or CSS class), otherwise the banner will have no height and be hidden.

    Layers can be defined in two ways:

    1. As children using the <ParallaxBannerLayer> component.
    2. As an array of objects passed to the layers prop.

    Layer Order: The first layer defined (or first in the array) is at the bottom; the last layer is on top.

    import { ParallaxBanner, ParallaxBannerLayer } from 'react-scroll-parallax';
    
    // Option 1: Using ParallaxBannerLayer children
    <ParallaxBanner style={{ aspectRatio: '2 / 1' }}>
      <ParallaxBannerLayer image="https://foo.com/foo.jpg" speed={-20} />
      <ParallaxBannerLayer speed={-10}>
        <h1>My Headline</h1>
      </ParallaxBannerLayer>
    </ParallaxBanner>
    
    // Option 2: Using the layers prop
    <ParallaxBanner
      style={{ aspectRatio: '2 / 1' }}
      layers={[
        { image: 'https://foo.com/foo.jpg', speed: -20 },
        { children: 'My Headline', speed: -10 },
      ]}
    />
  3. Implement parallax effects using the useParallax hook

    The useParallax hook allows you to apply parallax effects directly to an element by attaching the returned ref to it. Effect styles are applied directly to the referenced element. You can pass configuration props such as speed to control the rate of scroll.
    import { useParallax } from 'react-scroll-parallax';
    
    const Component = () => {
      // speed: 10 speeds up the rate of scroll
      const { ref } = useParallax({ speed: 10 });
      return <div ref={ref}>I am parallaxing</div>;
    };
  4. Install react-scroll-parallax v4 beta

    Install the v4 beta version of react-scroll-parallax, which utilizes the Web Animations API (WAAPI) and ScrollTimeline for high-performance animations on the compositor thread. Note that Firefox does not currently support the Web Animations ViewTimeline API by default and requires a polyfill.
    npm install react-scroll-parallax@beta
  5. Implement parallax effects using the Parallax component

    The <Parallax /> component wraps children and applies effect styles to a managed div wrapper rather than the children themselves. It supports CSS transform props like translateY and translateX. When providing arrays for these props, values without units are assumed to be percentages.
    import { Parallax } from 'react-scroll-parallax';
    
    const Component = () => (
      <>
        {/* translateY from -20% to 20% */}
        <Parallax translateY={[-20, 20]}>
          <div>Content 1</div>
        </Parallax>
    
        {/* translateX from -100px to 200px */}
        <Parallax translateX={['-100px', '200px']}>
          <div>Content 2</div>
        </Parallax>
      </>
    );
  6. Apply parallax effects to a DOM element using useParallax

    The useParallax hook is the primary way to apply parallax effects to a DOM element. You must assign the returned ref to the target element and provide a configuration object (such as speed) to define the effect.
    import { useParallax } from 'react-scroll-parallax';
    
    function Component() {
      // speed: 10 defines the parallax effect
      const { ref } = useParallax<HTMLDivElement>({ speed: 10 });
      return <div ref={ref}>Parallax Element</div>;
    }
  7. Create basic parallax effects with hooks or components

    You can implement parallax effects using either the useParallax hook for fine-grained control over a DOM element or the <Parallax> component for a declarative wrapper.
    // Using the hook
    function HookComponent() {
      const parallax = useParallax({
        speed: -10,
      });
      return <div ref={parallax.ref}>Content</div>;
    }
    
    // Using the component
    function Component() {
      return (
        <Parallax speed={-10}>
          <div>Content</div>
        </Parallax>
      );
    }
  8. Setup the ParallaxProvider

    The ParallaxProvider must wrap the root level of your application to provide the necessary context for the Parallax Controller. It should be placed in a component that does not unmount during route changes (e.g., an AppContainer).
    import { ParallaxProvider } from 'react-scroll-parallax';
    
    const AppContainer = () => (
      <ParallaxProvider>
        <Router>
          <App />
        </Router>
      </ParallaxProvider>
    );
  9. Configure react-scroll-parallax with Next.js 13 App Router

    Because ParallaxProvider and parallax effects rely on client-side APIs, they must be implemented in Client Components using the 'use client' directive. Wrap the application root in a ParallaxProvider via a separate providers file to maintain a clean layout structure.
    // app/providers.tsx
    'use client';
    import { ParallaxProvider } from 'react-scroll-parallax';
    
    export function Providers({ children }: { children: React.ReactNode }) {
      return <ParallaxProvider>{children}</ParallaxProvider>;
    }
    
    // app/layout.tsx
    import { Providers } from './providers';
    
    export default function RootLayout({ children }: { children: React.ReactNode }) {
      return (
        <html lang="en">
          <body>
            <Providers>{children}</Providers>
          </body>
        </html>
      );
    }
    
    // app/test.tsx
    'use client';
    import { Parallax } from 'react-scroll-parallax';
    
    export default function Test() {
      return (
        <Parallax scale={[1, 0]}>
          <div>Scaling Content</div>
        </Parallax>
      );
    }
  10. Implement horizontal parallax layers with targetElement

    To create a horizontal parallax effect where multiple layers move at different speeds relative to a container, use the useParallax hook.

    Key implementation details:

    1. Target Element: Assign a ref to the containing element and pass it as the targetElement to each useParallax configuration. This ensures the progress rate is calculated consistently across all layers.
    2. Speed: Assign different speed values to layers; higher values result in faster movement.
    3. Layer Positioning: Stack layers absolutely within the container. Extend the left and right boundaries of the images/layers to ensure edges are not visible during the scroll.
    function DemonWoods() {
      const target = useRef(null);
    
      const mid = useParallax({
        speed: 50,
        targetElement: target.current,
      });
      const close = useParallax({
        speed: 100,
        targetElement: target.current,
      });
    
      // Calculate extensions to prevent edges from showing
      const midExtend = 50 * 5 * -1;
      const closeExtend = 100 * 5 * -1;
    
      return (
        <div ref={target} style={{ position: 'relative', overflow: 'hidden' }}>
          {/* Parallax layers would be rendered here using the mid and close parallax objects */}
        </div>
      );
    }
  11. Apply scroll effects with the Parallax component

    The Parallax component is the primary tool for applying scroll-driven effects to an element based on its position in the viewport. It supports speed control for simple parallax and translate controls for fine-tuned movement. Translate values without units default to percentages (e.g., -20 becomes -20%).
    import { Parallax } from 'react-scroll-parallax';
    
    const ParallaxExample = () => (
      <>
        {/* Simple speed control: speeds up or slows down scroll */}
        <Parallax speed={-5}>
          <div>Slow Layer</div>
        </Parallax>
    
        {/* Fine-tuned translation: starts at -20% and ends at 10% translateY */}
        <Parallax translateY={[-20, 10]}>
          <div>Translated Layer</div>
        </Parallax>
    
        {/* Supports standard HTML props like style and className */}
        <Parallax style={{ background: 'blue' }} className="test">
          Hello
        </Parallax>
      </>
    );
  12. Add a headline or custom content to a ParallaxBanner

    You can add headlines or custom markup to a <ParallaxBanner> in two ways:

    1. Absolute Overlay: Pass children directly to the <ParallaxBanner> component. This content will be positioned absolutely over all parallax layers.
    2. Embedded in Scene: Define a layer object within the layers array and provide children to that specific layer. This allows the headline itself to move at a specific parallax speed, placing it 'between' other image layers.
    import { ParallaxBanner } from 'react-scroll-parallax';
    
    const Component = () => {
      return (
        <ParallaxBanner
          layers={[
            { image: '/static/banner-background.jpg', speed: -20 },
            {
              speed: -15,
              children: ( <h1>Hello World!</h1> ), // Embedded layer
            },
            { image: '/static/banner-foreground.png', speed: -10 },
          ]}
          className="aspect-[2/1]"
        >
          <h1>Absolute Overlay Headline</h1> {/* Absolute overlay content *}
        </ParallaxBanner>
      );
    };