Scroll Animation Snippets — Free HTML CSS JS Scroll Effects
9 scroll-triggered effects · Reveal, Parallax, Pinned sections, Sticky stacks, Image-sequence scrub · Exports to React, Vue, Angular & Tailwind
What's included
Features
About this tool
Scroll Animation Snippets — Free Scroll-Triggered Reveals, Parallax, and Pinned Storytelling
Scroll is the primary way people move through a web page, which makes it the richest surface for motion. A well-timed reveal, a layer that drifts at its own pace, a section that pins while its content advances — these are the effects that make modern marketing sites, product tours, and editorial stories feel alive. This collection gathers every common scroll-driven pattern as plain HTML, CSS, and vanilla JavaScript (with a few using GSAP ScrollTrigger where it earns its place), so you can drop a real, performant scroll effect into any page without wiring up a heavy animation framework yourself.
Every snippet is copy-paste ready and exports to React, Vue, Angular, and Tailwind from the same source, so the same effect works whether you are prototyping in a static HTML file or wiring it into a component tree.
Reveal on scroll — the workhorse
The most common pattern is content that fades and lifts into place as it enters the viewport. These snippets use an IntersectionObserver rather than a scroll listener: the browser tells you when an element crosses a threshold, so there is no per-frame work and no layout thrashing. The observer typically fires once and then unobserves the element, so the reveal never re-runs on scroll-back. Staggered grids extend this by delaying each child, producing the cascading entrance you see on feature sections.
Scroll-linked animation — tie motion to position
Some effects map an element's progress directly to the scroll position: a progress bar that fills as you read, a hero that zooms or blurs as it exits, text whose letters stagger in as the section scrolls through. These read the scroll offset (or use the modern scroll-timeline where supported) and interpolate a value, so the animation scrubs backward and forward exactly with the wheel or finger rather than playing on a fixed timer.
Pinning and sticky storytelling
The most cinematic patterns pin a section in place while its inner content advances — horizontal card galleries that scroll sideways, stacking cards that pile up, panels that split apart, an image sequence that scrubs frame by frame like a flipbook. The pin-based snippets lean on GSAP ScrollTrigger for robust cross-browser pinning; the simpler stacks use CSS position: sticky, which pins with zero JavaScript.
Parallax and depth
Parallax layers move at different speeds to fake depth — a background drifting slower than the foreground, a tilted grid, a hero image that lags the scroll. Done with transforms rather than background-position, they stay smooth because the browser can composite them off the main thread.
Performance and accessibility first
Because scroll effects run constantly, they must be cheap: these snippets favour IntersectionObserver over scroll listeners, animate transform and opacity (the two properties the compositor handles without repaint), and gate motion behind prefers-reduced-motion so users who opt out of animation get a static, fully readable page. Each snippet renders from readable vanilla JS, making the collection a clear reference for how scroll animation actually works under the hood.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Most do not. Reveal and enter-view effects use an IntersectionObserver, which lets the browser notify you when an element crosses a viewport threshold instead of running a handler on every scroll frame. That avoids layout thrashing and keeps scrolling smooth. The few scrub-linked effects that need continuous progress read the scroll offset inside a requestAnimationFrame loop or use a scroll-timeline, and the pin-based ones delegate to GSAP ScrollTrigger.
The simple reveals, staggers, parallax layers, sticky stacks, and progress indicators are plain HTML, CSS, and vanilla JavaScript with no dependency — position: sticky and IntersectionObserver do the work. The advanced pinning effects (horizontal pin, pin-story, image-sequence scrub, some perspective galleries) use GSAP ScrollTrigger because robust cross-browser pinning is genuinely hard to do by hand. Each snippet states its dependency, and the exported versions defer any ScrollTrigger setup to the framework mount hook.
Not if you keep to the patterns here. The snippets animate transform and opacity — the two properties the browser compositor can handle without repainting or reflowing — and prefer IntersectionObserver over scroll listeners, so there is little main-thread work. Reveal-once effects unobserve their element after firing so nothing accumulates. Avoid animating layout properties like top, height, or margin on scroll, which is what causes jank.
Wrap the motion in a @media (prefers-reduced-motion: no-preference) query, or check window.matchMedia("(prefers-reduced-motion: reduce)") in JS and skip the animation, leaving the content in its final visible state. Because the reveal snippets set the end state as the default and only animate toward it, honouring the preference is usually as simple as not adding the animating class — the page stays fully readable and static.
Export any snippet to your framework from the editor. The exporter places IntersectionObserver setup and any GSAP ScrollTrigger initialisation inside the mount hook — useEffect in React, onMounted in Vue, ngAfterViewInit in Angular — and returns a cleanup that disconnects the observer or kills the ScrollTrigger on unmount, so effects do not leak across route changes. Refs replace getElementById, and the CSS ports directly or converts to Tailwind utilities.