Skip to main content
Jarallax can be seamlessly integrated into React and Next.js applications using custom wrapper components. This guide shows you how to build reusable components and handle server-side rendering.

Installation

First, install Jarallax in your React or Next.js project:
npm install jarallax

React Component Setup

Create reusable React components for Jarallax functionality:
1

Create the Jarallax Component

Build a wrapper component that manages the parallax lifecycle:
components/Jarallax.js
import React, { useRef, useEffect } from 'react';
import { jarallax, jarallaxVideo } from 'jarallax';
import 'jarallax/dist/jarallax.min.css';

// Optional video extension
jarallaxVideo();

export default function Jarallax({ className = '', children, ...props }) {
  const $el = useRef();

  // Init Jarallax
  useEffect(() => {
    if ($el.current) {
      jarallax($el.current, props);
    }

    // Destroy Jarallax on cleanup
    return function destroy() {
      if ($el.current) {
        jarallax($el.current, 'destroy');
      }
    };
  }, []);

  // Update options when props change
  useEffect(() => {
    if ($el.current) {
      jarallax($el.current, 'destroy');
      jarallax($el.current, props);
    }
  }, [props]);

  return (
    <div ref={$el} className={`jarallax ${className}`}>
      {children}
    </div>
  );
}
This component properly handles initialization, cleanup, and prop updates to prevent memory leaks.
2

Create the Image Component

Create a simple component for parallax images:
components/JarallaxImage.js
export default function JarallaxImage({ className = '', ...props }) {
  return <img className={`jarallax-img ${className}`} {...props} />;
}
3

Use in Your Application

Import and use the components in your React app:
App.js
import Jarallax from './components/Jarallax';
import JarallaxImage from './components/JarallaxImage';

function App() {
  return (
    <div>
      <Jarallax speed={0.2}>
        <JarallaxImage 
          src="https://jarallax.nkdev.info/images/image1.jpg" 
          alt="Parallax background" 
        />
        <div className="content">
          <h1>Your Content Here</h1>
        </div>
      </Jarallax>
    </div>
  );
}

Next.js Integration

Next.js requires special handling due to server-side rendering (SSR). Jarallax needs to run only on the client side.

Basic Next.js Setup

Here’s how to integrate Jarallax in a Next.js application:
pages/index.js
import Head from 'next/head';
import dynamic from 'next/dynamic';

// Disable SSR for Jarallax component
const Jarallax = dynamic(() => import('../components/Jarallax'), { ssr: false });
import JarallaxImage from '../components/JarallaxImage';

export default function Index() {
  return (
    <>
      <Head>
        <title>Next.js Parallax Example</title>
      </Head>

      <div className="section">
        <h1>Next.js Example</h1>
      </div>

      <Jarallax speed={0.2}>
        <JarallaxImage src="https://jarallax.nkdev.info/images/image1.jpg" alt="" />
      </Jarallax>

      <Jarallax speed={0.2} videoSrc="https://youtu.be/mru3Q5m4lkY" />

      <div className="section" />
    </>
  );
}
Always use dynamic import with { ssr: false } for the Jarallax component to prevent server-side rendering issues.

App Router Setup (Next.js 13+)

For Next.js App Router, mark your component as a Client Component:
components/Jarallax.js
'use client';

import React, { useRef, useEffect } from 'react';
import { jarallax, jarallaxVideo } from 'jarallax';
import 'jarallax/dist/jarallax.min.css';

jarallaxVideo();

export default function Jarallax({ className = '', children, ...props }) {
  const $el = useRef();

  useEffect(() => {
    if ($el.current) {
      jarallax($el.current, props);
    }

    return function destroy() {
      if ($el.current) {
        jarallax($el.current, 'destroy');
      }
    };
  }, []);

  useEffect(() => {
    if ($el.current) {
      jarallax($el.current, 'destroy');
      jarallax($el.current, props);
    }
  }, [props]);

  return (
    <div ref={$el} className={`jarallax ${className}`}>
      {children}
    </div>
  );
}

Advanced Next.js Example

Here’s a complete example with dynamic state management and interactive controls:
pages/index.js
import React, { useState } from 'react';
import Head from 'next/head';
import dynamic from 'next/dynamic';

const Jarallax = dynamic(() => import('../components/Jarallax'), { ssr: false });
import JarallaxImage from '../components/JarallaxImage';

export default function Index() {
  const [blocks, updateBlocks] = useState([
    {
      uid: 1,
      options: {
        type: 'scroll',
        src: 'https://source.unsplash.com/random/1280x720',
        speed: 0.6,
      },
    },
  ]);

  function addNewBlock() {
    const randomImage = `https://source.unsplash.com/random/1280x72${blocks.length % 10}`;
    let uid = 1;

    if (blocks[blocks.length - 1]) {
      uid = blocks[blocks.length - 1].uid + 1;
    }

    updateBlocks([
      ...blocks,
      {
        uid: uid,
        options: {
          type: 'scroll',
          src: randomImage,
          speed: 0.6,
        },
      },
    ]);
  }

  function removeBlock(id) {
    updateBlocks(
      blocks.filter((data, i) => {
        return id !== i;
      })
    );
  }

  function changeBlockOptions(id, newOptions) {
    updateBlocks(
      blocks.map((data, i) => {
        if (id === i) {
          return {
            ...data,
            options: {
              ...data.options,
              ...newOptions,
            },
          };
        }

        return data;
      })
    );
  }

  return (
    <>
      <Head>
        <title>Next.js Advanced Example</title>
      </Head>

      <div className="section">
        <h1>Next.js Advanced Example</h1>
      </div>

      <div className="wrapper">
        <button className="btn btn-primary" onClick={addNewBlock}>
          + Add New Parallaxed Block
        </button>

        <br />
        <br />

        {blocks.map(({ uid, options }, i) => (
          <div className="jarallax-wrap" key={uid}>
            <Jarallax type={options.type} speed={options.speed}>
              <JarallaxImage src={options.src} alt="" />
            </Jarallax>
            <div className="jarallax-controls">
              <div className="form-group">
                <label>Parallax Type</label>
                <select
                  className="form-control"
                  value={options.type}
                  onChange={(e) => {
                    changeBlockOptions(i, {
                      type: e.target.value,
                    });
                  }}
                >
                  <option value="scroll">Scroll</option>
                  <option value="scale">Scale</option>
                  <option value="opacity">Opacity</option>
                  <option value="scroll-opacity">Scroll Opacity</option>
                  <option value="scale-opacity">Scale Opacity</option>
                </select>
                <label>Parallax Speed</label>
                <input
                  className="form-control"
                  type="number"
                  min="-1"
                  max="2"
                  step="0.1"
                  value={options.speed}
                  onChange={(e) => {
                    changeBlockOptions(i, {
                      speed: e.target.value,
                    });
                  }}
                />
                <button
                  className="btn btn-remove"
                  onClick={() => {
                    removeBlock(i);
                  }}
                >
                  Remove Block
                </button>
              </div>
            </div>
          </div>
        ))}
      </div>
    </>
  );
}
This advanced example demonstrates how to dynamically add, remove, and update parallax blocks with different configurations in real-time.

Common Props

The Jarallax component accepts all standard Jarallax options as props:
<Jarallax
  // Parallax type
  type="scroll"  // scroll, scale, opacity, scroll-opacity, scale-opacity
  
  // Parallax speed
  speed={0.5}  // -1.0 to 2.0
  
  // Image options
  imgSrc="path/to/image.jpg"
  imgSize="cover"
  imgPosition="50% 50%"
  
  // Video options
  videoSrc="https://www.youtube.com/watch?v=ab0TSkLe-E0"
  videoStartTime={0}
  videoEndTime={0}
  videoLoop={true}
  
  // z-index
  zIndex={-100}
  
  // Disable on mobile
  disableParallax={/iPad|iPhone|iPod|Android/}
  
  // Event handlers
  onInit={() => console.log('Initialized')}
  onDestroy={() => console.log('Destroyed')}
  onScroll={(calculations) => console.log(calculations)}
>
  <JarallaxImage src="path/to/image.jpg" alt="" />
  {/* Your content */}
</Jarallax>

Video Backgrounds in React

Enable video backgrounds by ensuring the video extension is initialized:
<Jarallax 
  speed={0.2} 
  videoSrc="https://www.youtube.com/watch?v=ab0TSkLe-E0"
  videoLoop={true}
>
  <div className="content">
    <h2>Content over video</h2>
  </div>
</Jarallax>

Styling

Add CSS to control the appearance and layout:
styles/globals.css
/* Set parallax container height */
.jarallax {
  height: 80vh;
  position: relative;
}

/* Style content inside parallax */
.jarallax .content {
  position: relative;
  z-index: 1;
  padding: 2rem;
  color: white;
  text-align: center;
}

/* Section spacing */
.section {
  height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

TypeScript Support

Jarallax includes TypeScript definitions. Create typed components:
components/Jarallax.tsx
import React, { useRef, useEffect, ReactNode } from 'react';
import { jarallax, jarallaxVideo, JarallaxOptions } from 'jarallax';
import 'jarallax/dist/jarallax.min.css';

jarallaxVideo();

interface JarallaxProps extends JarallaxOptions {
  className?: string;
  children?: ReactNode;
}

export default function Jarallax({ 
  className = '', 
  children, 
  ...props 
}: JarallaxProps) {
  const $el = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if ($el.current) {
      jarallax($el.current, props);
    }

    return function destroy() {
      if ($el.current) {
        jarallax($el.current, 'destroy');
      }
    };
  }, []);

  useEffect(() => {
    if ($el.current) {
      jarallax($el.current, 'destroy');
      jarallax($el.current, props);
    }
  }, [props]);

  return (
    <div ref={$el} className={`jarallax ${className}`}>
      {children}
    </div>
  );
}

Performance Optimization

Lazy load parallax components for better initial page load:
import dynamic from 'next/dynamic';

const Jarallax = dynamic(() => import('../components/Jarallax'), {
  ssr: false,
  loading: () => <div className="loading-placeholder" />
});

Troubleshooting

Ensure you’re using dynamic import with { ssr: false } for the Jarallax component. The library requires browser APIs that aren’t available during server-side rendering.
const Jarallax = dynamic(() => import('../components/Jarallax'), { ssr: false });
Make sure you’re properly handling prop changes in the useEffect hook. The component should destroy and reinitialize Jarallax when props change:
useEffect(() => {
  if ($el.current) {
    jarallax($el.current, 'destroy');
    jarallax($el.current, props);
  }
}, [props]);
Always clean up Jarallax instances in the useEffect cleanup function:
useEffect(() => {
  // Initialize
  return function destroy() {
    if ($el.current) {
      jarallax($el.current, 'destroy');
    }
  };
}, []);

Next Steps

Vanilla JavaScript

Learn basic Jarallax usage without frameworks

jQuery Integration

Use Jarallax with jQuery

API Reference

Explore all available methods and options

Configuration

Advanced configuration options