Library / SDK
geosigno/simpleParallax.js avatar
geosigno/simpleParallax.js

simpleParallax.js: a parallax effect you put on the img tag itself

Easy Parallax Effect for React & JavaScript

2,158 stars147 forksTypeScriptMIT

At a glance

What is it?
A small TypeScript library that applies parallax directly to real image and video elements in React, Next.js or plain JavaScript, with settings for orientation, scale, delay and overflow.
Who is it for?
The decision that makes this library pleasant to use is that it works on the element you already have rather than asking you to restructure your markup into a background image with fixed dimensions. Everything else follows from keeping that surface small: two entry points, one settings object, and a core shared between them so the React and vanilla builds cannot drift.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 84 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Parallax without background-image wrappers

Most parallax implementations ask you to hide a real image behind a `background-image` on a wrapper with a fixed height, because that is how the technique was done before transforms were cheap. simpleParallax.js takes the other route: it applies the effect to the `<img>` element itself. No wrapper divs, no background images, no duplicated assets.

That constraint produces a library with a very small API surface. It works out of the box with React, Next.js and plain JavaScript, and the README's framing is that the effect is applied directly to your image tags while other plugins are often more complex.

The project is MIT licensed and TypeScript, with 2158 stars and 147 forks across only 12 open issues, which is a low ratio for a library this widely used. It is not archived and the last push was on 2026-07-14, so it is actively worked on. The homepage is simpleparallax.com, and the README points to a Medium case study explaining the technique behind the approach.

One package, two entry points, four package managers

The install block lists every major package manager, which is a small signal about how the author expects this to be consumed:

sh
npm install simple-parallax-js
yarn add simple-parallax-js
pnpm add simple-parallax-js
bun add simple-parallax-js

React and react-dom are peer dependencies at `>=17`, so the library uses whatever React your project already has instead of bundling its own copy. The README also notes that the package ships type definitions for both entry points, so no separate `@types` package is needed.

The import path tells you which build you get:

javascript
//React version
import SimpleParallax from 'simple-parallax-js';

//Vanilla Version
import SimpleParallax from "simple-parallax-js/vanilla";

The default import is the React component, and the `/vanilla` subpath is the framework-free build. Same default export name, same options, different host environment.

Version 7 moved the package to ESM-first packaging, which is the one thing in the release notes likely to affect you directly. `require()` from Node CommonJS is no longer supported and needs a dynamic `import()` instead. Bundlers and the browser UMD build are unaffected, so this only matters if you consume the package from a CommonJS Node context.

Initialization differs by more than syntax

In React the component wraps the image, and settings arrive as props:

javascript
import SimpleParallax from "simple-parallax-js";

const Component = () => (
  <SimpleParallax>
    <img src={"thumbnail.jpg"} alt={"image"} />
  </SimpleParallax>
)

In vanilla JavaScript the constructor takes an element or a collection, which means a class selector and a `querySelectorAll` are both valid starting points:

javascript
const image = document.getElementsByClassName('thumbnail');
new SimpleParallax(image);
javascript
const images = document.querySelectorAll('img');
new SimpleParallax(images);

Both builds add the `simple-parallax-initialized` class to the container once setup succeeds, which is the documented way to confirm initialization worked and a useful hook for your own styling.

Video works the same way, which is worth knowing because a video background that parallaxes is a fairly common hero pattern:

html
<video>
  <source src="video.mp4" type="video/mp4">
</video>

Settings are the same six knobs in both builds

The settings table is short, which is the clearest sign of the project's simplicity claim. `orientation` is a string defaulting to `up`, with the options up, right, down, left, up left, up right, down left and down right, and combining two gives a diagonal. `scale` is a number that must be above 1, `overflow` is a boolean defaulting to false, `delay` is a number in seconds, `transition` is any CSS transition string, and `maxTransition` is a percentage between 1 and 99.

Two of those are marked vanilla-only: `customContainer` and `customWrapper`, the latter being a selector string.

The React form passes them as props:

javascript
import SimpleParallax from "simple-parallax-js";

const Component = () => (
  <SimpleParallax
    delay={0}
    orientation={"down"}
    scale={1.5}
    overflow
    maxTransition={60}
  >
    <img src={"thumbnail.jpg"} alt={"image"} />
  </SimpleParallax>
)

The vanilla form is a plain options object, and the Next.js example is the React form with `next/image` inside, so a Next project gets lazy loading and responsive images without giving up the effect.

The `scale` documentation contains the advice most likely to save you a blurry image. Since the effect scales the image up, an image at 500px rendered with scale 1.5 needs to be 750px wide to stay sharp. Version 7 raised the default scale to 1.5, which means more projects than before are now subject to that calculation.

Version 7 unified two builds that had drifted apart

The v7.0.0 release, published 2026-06-22, is a rewrite rather than a feature release, and its release notes are specific about what broke.

The breaking changes are the defaults: `scale` is now 1.5 for both builds, where vanilla previously defaulted to 1.3 and React to 1.4, and the vanilla `delay` is now 0.4 seconds where it was 0. `maxTransition` semantics were unified across the two builds, which the notes flag as needing a check if you use it.

The improvements are the reason to upgrade. Vanilla and React now run on the same framework-agnostic `core` module for the parallax math plus `shared` for browser helpers, so the two builds share one source of truth and can no longer drift. The package no longer touches a browser API at import time, which is what makes it SSR-safe in Next.js. And the React engine stopped re-rendering on every scroll frame: the transform is now computed inside the animation frame and written straight to the element, which also restored the transition on Safari.

That last change is the most interesting engineering decision in the library. A React component that re-renders on each scroll event looks fine in a demo and falls over on a real page, and moving the write out of the render path is the standard fix.

Accessibility, tooling and where the docs stop

Two earlier releases show the maintainer treating this as more than a visual trick. Version 6.1.0 added support for `prefers-reduced-motion` and fixed an initial animation glitch on page load in the React build. Version 6.2.1 was a performance pass that removed unnecessary re-renders and optimised the calculations, described as a return to the project's performance laboratory roots after the React rewrite.

The toolchain matches a modern TypeScript library. Vite 8 builds both entry points from separate modes, TypeScript 6 does the typechecking, Biome through ultracite handles format and lint, lefthook installs the git hooks, and the test script is `bun test`. The `lint:pkg` script is the detail worth copying: it runs publint and the arethetypeswrong CLI with a specific ignore list, which catches the packaging mistakes that silently break consumers, such as a CommonJS entry resolving to ESM or a missing default export.

The README documents settings well but stops short of anything deeper. There is no page on how the effect is computed, on performance characteristics, or on how it composes with scroll-linked CSS animations, which is the honest boundary of what you can learn from it. For the reasoning behind the img-tag approach, the linked case study is where the detail lives.

Editorial conclusion

The decision that makes this library pleasant to use is that it works on the element you already have rather than asking you to restructure your markup into a background image with fixed dimensions. Everything else follows from keeping that surface small: two entry points, one settings object, and a core shared between them so the React and vanilla builds cannot drift. The costs are equally legible. Version 7 changed the default scale and delay, dropped CommonJS support in favour of ESM, and unified maxTransition, so a project upgrading needs to check its motion values. Start on version 7 with the defaults, raise scale only as far as your image resolution supports, and leave delay alone on iOS unless you have read the linked issue.

Frequently asked questions

What is simpleParallax.js and how is it different from other parallax plugins?

It is a lightweight TypeScript library that applies a parallax effect directly to img and video tags rather than to a background image on a wrapper element. That means you keep real image markup and skip the fixed-height div structure older parallax approaches required. It ships both React and vanilla entry points.

How do I use it with Next.js and next/image?

Import the default entry point and wrap `next/image` in the `SimpleParallax` component, passing settings as props. Version 7 is SSR-safe, so no browser API is touched at import time and it works in the Next.js server environment without extra configuration.

What changed in version 7.0.0 and are there breaking changes?

Yes. The default `scale` is now 1.5 for both builds (previously 1.3 vanilla and 1.4 React), the vanilla `delay` default is now 0.4 seconds instead of 0, and `maxTransition` semantics are unified. Packaging also became ESM-first, so `require()` from Node CommonJS is no longer supported and needs a dynamic `import()`.

How do I avoid blurry images when using this?

Scale up your source image to match the `scale` setting. The README's example is that an image 500px wide with scale 1.5 should be a 750px file, because the effect enlarges it. Since version 7 defaults scale to 1.5, more images need this treatment than in earlier releases.

Does simpleParallax.js respect reduced motion preferences?

Yes. Version 6.1.0 added support for `prefers-reduced-motion`, so the effect respects a visitor who has asked the operating system to reduce animation.

Official sources

  1. geosigno/simpleParallax.js on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/geosigno-simpleparallax-js.svg)](https://hysenlabs.com/projects/geosigno-simpleparallax-js)