scroll-animation
Use when building scroll-driven animations — GSAP ScrollTrigger, CSS scroll-timeline, frame sequences, parallax, pin/scrub effects. Covers Apple-style scroll playback, progress-linked animations, and smooth scroll integration.
- License 许可
- Apache-2.0
- 最近更新
- 2026-10-11
- Stars
- ★ 7
- Forks
- 8
01 前言 Front Matter
- name
- scroll-animation
- arguments
- [ { "name": "technique", "required": false, "description": "Technique: gsap, css-native, frame-sequence, parallax, hybrid (auto-detect if omitted)" }, { "name": "framework", "required": false, "description": "Framework: react, next, astro, vue, svelte, vanilla (auto-detect if omitted)" } ]
- description
- Use when building scroll-driven animations — GSAP ScrollTrigger, CSS scroll-timeline, frame sequences, parallax, pin/scrub effects. Covers Apple-style scroll playback, progress-linked animations, and smooth scroll integration.
03 SKILL.md 正文
Scroll Animation Skill
Decision Matrix — Pick Technique
| Need | Technique | Why |
|---|---|---|
| Pin + scrub + snap | GSAP ScrollTrigger | Most mature, free since Webflow acquisition |
| Simple fade/slide on scroll | CSS animation-timeline |
Zero JS, native performance |
| Apple-style frame playback | Canvas frame sequence | Smoothest result for product reveals |
| Parallax layers | CSS or GSAP | CSS for simple, GSAP for complex |
| Smooth scroll feel | Lenis + GSAP | Industry standard combo |
1. GSAP ScrollTrigger
License: 100% FREE including all plugins
Install: npm i gsap
Core API
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
// Pin + Scrub
gsap.to(".hero-content", {
y: -100,
opacity: 0,
scrollTrigger: {
trigger: ".hero",
start: "top top",
end: "bottom top",
pin: true,
scrub: 1,
snap: { snapTo: 1 / 4, duration: 0.3, ease: "power1.inOut" }
}
});
// Batch — stagger elements entering viewport
ScrollTrigger.batch(".card", {
onEnter: (elements) => {
gsap.to(elements, { opacity: 1, y: 0, stagger: 0.1 });
},
start: "top 85%"
});
React Integration (useGSAP hook)
import { useGSAP } from "@gsap/react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
function Section({ children }) {
const container = useRef(null);
useGSAP(() => {
gsap.from(".animate-in", {
y: 50,
opacity: 0,
stagger: 0.2,
scrollTrigger: { trigger: container.current, start: "top 80%" }
});
}, { scope: container });
return <section ref={container}>{children}</section>;
}
Key: useGSAP = drop-in for useEffect, auto-cleanup via gsap.context().
Astro Integration
<section id="scroll-section">
<div class="pin-target">Content</div>
</section>
<script>
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
gsap.to(".pin-target", {
x: 500,
scrollTrigger: { trigger: "#scroll-section", pin: true, scrub: true }
});
</script>
Performance Best Practices
- Use
will-change: transformon pinned elements - Prefer
transformandopacity— GPU-composited, no layout recalc scrub: 1(or higher) smooths jank vsscrub: true(instant)invalidateOnRefresh: truefor responsive layouts- Call
ScrollTrigger.refresh()after dynamic content loads - Avoid animating
width,height,top,left— triggers reflow
2. CSS Scroll-Driven Animations (Native)
Scroll Progress Timeline
@keyframes fade-in {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-on-scroll {
animation: fade-in linear both;
animation-timeline: scroll();
animation-range: entry 0% entry 100%;
}
View Progress Timeline
.reveal {
animation: fade-in linear both;
animation-timeline: view();
animation-range: entry 25% cover 50%;
}
Progressive Enhancement
@supports (animation-timeline: scroll()) {
.animate { animation-timeline: scroll(); }
}
/* Fallback: use IntersectionObserver + classList toggle */
What CSS Can Replace from GSAP
| Feature | CSS Native | Still Need GSAP |
|---|---|---|
| Fade/slide on scroll | Yes | No |
| Progress-linked animation | Yes | No |
| View-enter/exit triggers | Yes | No |
| Pin element | No | Yes |
| Snap to sections | No (scroll-snap is separate) | Yes (integrated) |
| Batch stagger | No | Yes |
| Timeline sequencing | Limited | Yes |
| Complex easing curves | Limited | Yes |
| JS callbacks on progress | No | Yes |
Rule of thumb: CSS for simple reveal animations. GSAP for anything with pin, snap, stagger, or JS logic.
3. Lenis Smooth Scroll
Install: npm i lenis
Bundle: ~14KB min+gzip (no dependencies)
import Lenis from "lenis";
const lenis = new Lenis({
duration: 1.2,
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
orientation: "vertical",
smoothWheel: true,
});
// Connect to GSAP ticker for sync
gsap.ticker.add((time) => { lenis.raf(time * 1000); });
gsap.ticker.lagSmoothing(0);
// Connect to ScrollTrigger
lenis.on("scroll", ScrollTrigger.update);
When to use: Agency-style smooth scroll feel. Pairs with GSAP ScrollTrigger. When NOT to use: Content-heavy sites, accessibility-first projects.
4. Frame Sequence on Scroll (Apple-Style)
Pipeline
Video (MP4/MOV)
→ FFmpeg frame extraction (PNG)
→ Convert to WebP (90% size reduction vs PNG)
→ Canvas playback synced to scroll
FFmpeg Extraction
ffmpeg -i source.mp4 -vf "fps=30,scale=1280:720" frames/frame_%04d.png
for f in frames/*.png; do cwebp -q 80 "$f" -o "${f%.png}.webp"; done
Optimal Parameters
| Parameter | Desktop | Mobile |
|---|---|---|
| Frame count | 120-180 | 60-90 |
| Resolution | 1920x1080 | 960x540 |
| Format | WebP q80 | WebP q75 |
| Total budget | 2-4 MB | 1-2 MB |
Canvas Implementation
const canvas = document.getElementById("sequence-canvas");
const ctx = canvas.getContext("2d");
const frameCount = 150;
const frames = [];
function preloadFrames() {
for (let i = 1; i <= frameCount; i++) {
const img = new Image();
img.src = `/frames/frame_${String(i).padStart(4, "0")}.webp`;
frames.push(img);
}
}
gsap.to({ frame: 0 }, {
frame: frameCount - 1,
snap: "frame",
ease: "none",
scrollTrigger: {
trigger: "#sequence-section", start: "top top", end: "+=3000", pin: true, scrub: 0.5,
},
onUpdate: function() {
const index = Math.round(this.targets()[0].frame);
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (frames[index]?.complete) {
ctx.drawImage(frames[index], 0, 0, canvas.width, canvas.height);
}
}
});
Alternative: Video Scrub
const video = document.getElementById("scrub-video");
gsap.to(video, {
currentTime: video.duration,
ease: "none",
scrollTrigger: { trigger: "#video-section", start: "top top", end: "+=4000", pin: true, scrub: true }
});
Tradeoff: Video scrub = smaller payload, less smooth on mobile. Frame sequence = more bytes, smoother everywhere.
Accessibility
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (prefersReduced) { ScrollTrigger.getAll().forEach(st => st.kill()); }
Workflow
- Define scroll sections — wireframe which content pins, reveals, or plays
- Pick technique — use Decision Matrix above
- Implement with GSAP — pin/scrub/snap for complex, CSS for simple reveals
- Add Lenis — only if smooth scroll feel is required
- Test performance — Chrome DevTools Performance panel, aim for <16.6ms/frame
- Add a11y —
prefers-reduced-motion, keyboard nav still works - Test mobile — reduce frame counts, disable heavy effects on low-end
04 同仓库更多 Skills
wave-audit
3-wave parallel audit — Wave 1 discovery (4 agents), Wave 2 verification (4 agents), Wave 3 cross-optimization (1 synthesizer). Each wave runs agents in parallel. Combines security review, runtime analysis, quality check, and constructor pattern into one unified workflow with evidence grading and Go/No-Go verdict.
vm-provision
End-to-end VPS provisioning — select provider → plan → provision → harden → verify (ssh-check + firewall-diff hard-gate) → handoff. 6 phases, ≥6 AskUserQuestion calls, defensive-only. Stops if either verification primitive fails.
visual-explainer
Generate beautiful, self-contained HTML pages that visually explain systems, code changes, plans, and data. Use when the user asks for a diagram, architecture overview, diff review, plan review, project recap, comparison table, or any visual explanation of technical concepts. Also use proactively when you are about to render a complex ASCII table (4+ rows or 3+ columns) — present it as a styled HTML page instead.
video-gen
Use when generating video from frame sequences — FFmpeg extraction, WebP/AVIF conversion, sprite sheets, scroll-synced playback, video encoding/transcoding. Covers the full pipeline from video source to web-ready frame sequence or optimized video.
test-matrix
Use when a project needs testing BEYOND unit tests — fuzzing, property-based, load, E2E, or mutation. Five-phase hub-and-spoke pipeline composes the right mix per language × critical path × CI target, scaffolds configs + corpus + fixtures, wires CI jobs, and defines the crash/regression triage workflow. Pure-click: every decision except intake is an AskUserQuestion.
test-gen
Use when generating tests for untested code — happy path, edge cases, error handling