Skip to content

Repository files navigation

VFX-JS Screenshot

VFX-JS: WebGL effects for HTML.

npm MIT License Star on GitHub

Website · Transitions · Examples · Docs

VFX-JS adds WebGL effects to the elements of your website. Attach a shader to an <img>, a <video> or a block of text, or run the live DOM through a shader when a page changes.

  • Element effects. Glitch, bloom, pixelate, halftone and more on images, videos and text. Stack them, or write your own in GLSL.
  • Page transitions (new). Glitch, pixel sort, datamosh and more between pages or tabs. VFX-JS captures the live DOM, so it works on your real markup, and the element is plain DOM again when the run ends. See the transitions site.
  • Any framework. Plain JS, plus bindings for React, Vue, Svelte and Astro, with router support for Next.js, React Router, Nuxt, Vue Router, SvelteKit and Astro.

Quick start

Element effects

npm i @vfx-js/core
import { VFX } from "@vfx-js/core";

const img = document.querySelector("#img");

const vfx = new VFX();
vfx.add(img, { shader: "glitch", overflow: 100 });

Or compose effects from @vfx-js/effects:

import { VFX } from "@vfx-js/core";
import { BloomEffect, PixelateEffect } from "@vfx-js/effects";

const vfx = new VFX();
vfx.add(img, {
    effect: [new PixelateEffect({ size: 10 }), new BloomEffect({ intensity: 5 })],
});

Page transitions

npm i @vfx-js/core @vfx-js/transitions
import { VFX } from "@vfx-js/core";
import { Swipe } from "@vfx-js/transitions";

// <div id="panel"> holds one <section> per tab, all but one hidden.
const vfx = new VFX();
const panel = document.querySelector("#panel");
const t = vfx.addTransition(panel, { transition: Swipe, duration: 0.6 });

for (const tab of document.querySelectorAll("[data-panel]")) {
    tab.addEventListener("click", () => t.show(tab.dataset.panel));
}

For page navigation, wrap your router outlet in <VFXTransition>. Getting Started has the setup for each framework.

Packages

Package Description
@vfx-js/core The VFX class: element effects and transitions
@vfx-js/effects Ready-made effects
@vfx-js/transitions Transition presets
@vfx-js/react React components and hooks, with Next.js and React Router support
@vfx-js/vue Vue components and directives, with Nuxt and Vue Router support
@vfx-js/svelte Svelte components and attachments, with SvelteKit support
@vfx-js/astro Astro components
react-vfx Old name of @vfx-js/react, kept for compatibility

Documentation

Browser support

VFX-JS needs WebGL. Without it, VFX.init() returns null, so you can leave the page as plain HTML. When the user prefers reduced motion, VFX-JS renders nothing, and transitions cut to the new content.

Effects on <img> and <video> work the same in every browser. For text, other HTML and transitions, VFX-JS has to capture the DOM:

  • With HTML-in-Canvas, the browser draws the element itself, so the capture matches the page. The API is still experimental and is only in Chrome Canary, or Chrome behind a flag.
  • Elsewhere, VFX-JS clones the element and draws it as an SVG image. This is a workaround and can't match the page exactly. Web fonts, ::before / ::after and <canvas> content, among others, don't make it into the capture.

See Limitations for the full list.

Use with AI agents

Install the VFX-JS skill for Claude Code, Codex, Cursor and other agents:

npx skills add fand/vfx-js

Or point your agent to llms.txt / llms-full.txt.

Development

Requires Node.js 24 and pnpm.

git clone https://github.com/fand/vfx-js.git
cd vfx-js
pnpm install
pnpm dev

pnpm dev starts the docs and transitions sites and watches the libraries they use. pnpm build, pnpm lint and pnpm test run across all packages. See CONTRIBUTING.md before you send a pull request.

Author

AMAGI

License

MIT