Annnimate
Every component, in every framework.
Dithering is one of 50+ GSAP components, each shipping in React, Vue, and HTML/CSS/JS with the same production tuning.
The library
Curated, not a catalog dump.
Every signature component, built for a real site. Filter, preview live, copy in React or Vue.
Browse the libraryLandmark Kits
Depth, not breadth.
A deep, stand-alone collection built around one system. The first Kit is Reveal - preloaders and hero sections, one mixable system, WebGL and GSAP. React, Vue, HTML / CSS / JS. Not for Webflow.
See the Reveal KitConcepts, patterns, tools
Learn the vocabulary.
Definitions and examples for the GSAP and animation concepts behind production motion. Free, citable, and cross-linked with the components that use each idea.
Open conceptsAnnnimate
Dithering is one of 50+ GSAP components, each shipping in React, Vue, and HTML/CSS/JS with the same production tuning.
A 2-color dithering shader for images and video. Point it at any img or video and it renders as an animated Bayer-dithered halftone (2x2, 4x4, 8x8, or random threshold), with a cursor reveal lens that recolours the dots with the real source under the mouse and a faint ambient shimmer in the dark areas. A 1-bit retro/print treatment for hero images, video backdrops, and editorial media.
Dithering ships as a copy-paste React component. The only dependencies are GSAP and the official @gsap/react adapter for the useGSAP hook. Both work in Next.js (App Router and Pages), Vite, Remix, and Create React App.
Dithering is a leaf-level interactive component, so it needs to render on the client. In a Next.js App Router project, add the 'use client' directive at the top of the file (it's already there in the component you copy).
The component is self-contained: it manages its own refs, useGSAP scope, and cleanup. Mount it inside any Server Component, Client Component, or page. It does not require a provider or wrapper.
If your project uses TypeScript, the component is typed - the props it accepts match the data-anm-* attributes documented on the main detail page.
Always use the useGSAP hook, not useEffect
useGSAP (from @gsap/react) handles cleanup automatically: kills tweens and ScrollTriggers on unmount, and uses gsap.context scoping so selectors only match inside your component. Plain useEffect works but leaks animations on hot-reload and Strict Mode double-invocations.Refs over className selectors
gsap.to / gsap.from, use refs (elementRef.current) instead of class selectors. Refs survive Strict Mode double-renders and don't accidentally match sibling components that share class names.Register plugins inside a window guard
gsap.registerPlugin(ScrollTrigger, SplitText, ...) must run client-side only. Wrap in if (typeof window !== 'undefined') or place inside the component body - never at module top level in SSR contexts.'use client' directive and uses useGSAP for proper cleanup across Server Component re-renders. Drop it into any page or component inside app/.useGSAP which is React-version-agnostic. It also handles Strict Mode double-invocation correctly via gsap.context scoping.gsap.set on mount before the first frame, so any visible jump is sub-frame and rarely perceived. For above-the-fold use, pair with a CSS opacity:0 default that the component clears on mount.The full React implementation lives on the component page, with the live demo, every format side by side, and the ability to edit and re-run it in the browser.
Open Dithering