Skip to main content

scrollytelling

Implements scroll-driven storytelling experiences with pinned sections, progressive reveals, and scroll-linked animations. Use when asked to build scrollytelling, scroll-driven animations, parallax effects, narrative scroll experiences, or story-driven landing pages.

Informations de source

Dépôt
doodledood/claude-code-plugins
Dernière activité de la source
14 janvier 2026 à 06:35
Langue détectée de SKILL.md
anglais
Étoiles
20
Forks
3

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
scrollytelling
description
Implements scroll-driven storytelling experiences with pinned sections, progressive reveals, and scroll-linked animations. Use when asked to build scrollytelling, scroll-driven animations, parallax effects, narrative scroll experiences, or story-driven landing pages.
# Scrollytelling Skill Build scroll-driven narrative experiences that reveal content, trigger animations, and create immersive storytelling as users scroll. ## What is Scrollytelling? **Definition**: "A storytelling format in which visual and textual elements appear or change as the reader scrolls through an online article." When readers scroll, something other than conventional document movement happens. **Origin**: The New York Times' "Snow Fall: The Avalanche at Tunnel Creek" (2012), which won the 2013 Pulitzer Prize for Feature Writing. **Why it works**: Scrollytelling exploits a fundamental psychological principle—humans crave control. Every scroll is a micro-commitment that increases engagement. Users control the pace, creating deeper connection than passive consumption. **Measured impact**: - 400% longer time-on-page vs static content - 67% improvement in information recall - 5x higher social sharing rates - 25-40% improved conversion completion ## Core Principles ### 1. Story First, Technology Second The biggest mistake is leading with technology instead of narrative. Scrollytelling should enhance the story, not showcase effects. ### 2. User Agency & Progressive Disclosure Users control the pace. Information reveals gradually to maintain curiosity. This shifts from predetermined pacing to user-controlled narrative flow. ### 3. Sequential Structure Unlike hierarchical web content, scrollytelling demands linear progression with clear narrative beats. Each section builds on the previous. ### 4. Meaningful Change Every scroll-triggered effect must serve the narrative. Gratuitous animation distracts rather than enhances. ### 5. Restraint Over Spectacle Not every section needs animation. Subtle transitions often work better than constant effects. The format should amplify the content's message, not fight it. ## The 5 Standard Techniques Research analyzing 50 scrollytelling articles identified these core patterns: | Technique | Description | Best For | |-----------|-------------|----------| | **Graphic Sequence** | Discrete visuals that change completely at scroll thresholds | Data visualizations, step-by-step explanations | | **Animated Transition** | Smooth morphing between states | State changes, evolution over time | | **Pan and Zoom** | Scroll controls which portion of a visual is visible | Maps, large images, spatial narratives | | **Moviescroller** | Frame-by-frame progression creating video-like effects | Product showcases, 3D object reveals | | **Show-and-Play** | Interactive elements activate at scroll waypoints | Multimedia, audio/video integration | ## Layout Patterns ### Pattern 1: Side-by-Side Sticky (Most Common) The classic scrollytelling pattern: a graphic becomes "stuck" while narrative text scrolls alongside. When the narrative concludes, the graphic "unsticks." ``` ┌─────────────────────────────────────┐ │ ┌──────────┐ ┌─────────────────┐ │ │ │ Text │ │ │ │ │ │ Step 1 │ │ STICKY │ │ │ ├──────────┤ │ GRAPHIC │ │ │ │ Text │ │ │ │ │ │ Step 2 │ │ (updates with │ │ │ ├──────────┤ │ active step) │ │ │ │ Text │ │ │ │ │ │ Step 3 │ │ │ │ │ └──────────┘ └─────────────────┘ │ └─────────────────────────────────────┘ ``` **When to use**: Data visualization stories, step-by-step explanations, educational content requiring persistent visual context. **Implementation**: Use CSS `position: sticky` (not JavaScript scroll listeners) for better performance and graceful degradation. ### Pattern 2: Full-Width Sections Content spans the entire viewport with section-based transitions. **When to use**: Highly visual narratives, immersive brand storytelling, portfolio showcases, timeline-based stories. ### Pattern 3: Layered Parallax Multiple visual layers (background, midground, foreground) move at different speeds to create depth. **When to use**: Atmospheric storytelling, game/product launches, long-form narratives where depth adds emotional impact. **Accessibility warning**: Parallax triggers vestibular disorders (dizziness, nausea, migraines). Always provide reduced-motion fallback; limit to one subtle parallax effect per page maximum. ### Pattern 4: Multi-Directional Combines vertical scrolling with horizontal sections or sideways timelines. **When to use**: Timeline-based content, visually-driven showcases, unconventional layouts where surprise enhances the message. ## When to Use Scrollytelling **Good candidates**: - Long-form journalism with multimedia - Brand storytelling celebrating achievements - Product pages showcasing features - Chronological/historical content - Complex narratives broken into digestible chunks - High-consideration products needing depth **Avoid when**: - You lack strong visual assets - You're tight on time/budget (good scrollytelling requires more investment) - The story lacks distinct chronology - Content is brief - Performance is critical on low-end devices ## Discovery Questions Before implementing, clarify with the user: ``` header: "Scrollytelling Pattern" question: "What scrollytelling pattern fits your narrative?" options: - "Pinned narrative - text changes while visual stays fixed (NYT, Pudding.cool style)" - "Progressive reveal - content fades in as you scroll down" - "Parallax depth - layers move at different speeds (requires reduced-motion fallback)" - "Step sequence - discrete sections with transitions between" - "Hybrid - multiple patterns combined" ``` ``` header: "Tech Stack" question: "What's your frontend setup?" options: - "React + Tailwind" - "React + CSS-in-JS" - "Next.js" - "Vue" - "Vanilla JS" - "Other" ``` ``` header: "Animation Approach" question: "Animation library preference?" options: - "CSS-only (scroll-timeline API, IntersectionObserver) - best performance" - "GSAP ScrollTrigger - most powerful, cross-browser" - "Framer Motion / Motion - React ecosystem" - "Lenis + custom - smooth scroll" - "No preference - recommend based on complexity" ``` ## Technical Implementation (2025-2026) ### Technology Selection Guide | Complexity | Recommendation | Bundle Size | |------------|----------------|-------------| | Simple reveals, progress bars | Native CSS scroll-timeline | 0 KB | | Viewport-triggered effects | IntersectionObserver | 0 KB | | Complex timelines, pinning | GSAP ScrollTrigger | ~23 KB | | React projects | Motion (Framer Motion) | ~32 KB | | Smooth scroll + effects | Lenis + GSAP | ~25 KB | ### CSS Scroll-Driven Animations (Native - 2025+) **Browser support**: - Chrome 115+: Full support (since July 2025) - Safari 26+: Full support (since September 2025) - Firefox: Requires flag (`layout.css.scroll-driven-animations.enabled`) **Key properties**: - `animation-timeline: scroll()` - links animation to scroll position - `animation-timeline: view()` - links animation to element visibility - `animation-range` - controls when animation starts/stops **Example - View-triggered fade in**: ```css @supports (animation-timeline: scroll()) { .reveal-on-scroll { animation: reveal linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; } @keyframes reveal { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } } ``` **Example - Scroll-linked progress bar**: ```css .progress-bar { animation: grow linear; animation-timeline: scroll(); } @keyframes grow { from { transform: scaleX(0); } to { transform: scaleX(1); } } ``` **Performance benefit**: Tokopedia achieved 80% code reduction and CPU usage dropped from 50% to 2% by switching to native CSS scroll-driven animations. ### IntersectionObserver Pattern For scroll-triggered effects without continuous scroll tracking: ```tsx const RevealOnScroll = ({ children, delay = 0 }) => { const ref = useRef(null); const [isVisible, setIsVisible] = useState(false); useEffect(() => { // Check reduced motion preference if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { setIsVisible(true); return; } const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setIsVisible(true); observer.disconnect(); } }, { threshold: 0.1, rootMargin: '-50px' } ); if (ref.current) observer.observe(ref.current); return () => observer.disconnect(); }, []); return ( <div ref={ref} style={{ opacity: isVisible ? 1 : 0, transform: isVisible ? 'translateY(0)' : 'translateY(30px)', transition: `all 0.6s ease ${delay}ms`, }} > {children} </div> ); }; ``` ### GSAP ScrollTrigger (Complex Animations) For pinned sections, timeline orchestration, and cross-browser reliability: ```tsx const ScrollytellingSection = ({ steps }) => { const containerRef = useRef(null); const [activeStep, setActiveStep] = useState(0); useEffect(() => { // Check reduced motion preference if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { return; } const ctx = gsap.context(() => { steps.forEach((_, index) => { ScrollTrigger.create({ trigger: `.step-${index}`, start: 'top center', end: 'bottom center', onEnter: () => setActiveStep(index), onEnterBack: () => setActiveStep(index), }); }); }, containerRef); return () => ctx.revert(); }, [steps]); return ( <section ref={containerRef} className="relative"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> {/* Text column - scrolls naturally */} <div className="space-y-[100vh]"> {steps.map((step, i) => ( <div key={i} className={`step-${i} min-h-screen flex items-center transition-opacity duration-300 ${ activeStep === i ? 'opacity-100' : 'opacity-30' }`} > <div className="max-w-md"> <h3 className="text-2xl font-bold mb-4">{step.title}</h3> <p className="text-lg">{step.description}</p> </div> </div> ))} </div> {/* Visual column - sticky */} <div className="relative hidden md:block"> <div className="sticky top-0 h-screen flex items-center justify-center"> <StepVisual step={activeStep} data={steps[activeStep]} /> </div> </div> </div> </section> ); }; ``` ### Motion (Framer Motion) for React ```tsx import { motion, useScroll, useTransform } from 'motion/react'; const ScrollLinkedSection = () => { const ref = useRef(null); const { scrollYProgress } = useScroll({ target: ref, offset: ['start end', 'end start'], }); const opacity = useTransform(scrollYProgress, [0, 0.5, 1], [0, 1, 0]); const scale = useTransform(scrollYProgress, [0, 0.5, 1], [0.8, 1, 0.8]); return ( <section ref={ref} className="h-[200vh] relative"> <motion.div className="sticky top-0 h-screen flex items-center justify-center" style={{ opacity, scale }} > <h2 className="text-6xl font-bold">Scroll-Linked Content</h2> </motion.div> </section> ); }; ``` ### Scroll Progress Hook ```tsx const useScrollProgress = (ref) => { const [progress, setProgress] = useState(0); useEffect(() => { const element = ref.current; if (!element) return; const updateProgress = () => { const rect = element.getBoundingClientRect(); const windowHeight = window.innerHeight; // 0 when element top enters viewport, 1 when bottom exits const start = rect.top - windowHeight; const end = rect.bottom; const current = -start; const total = end - start; setProgress(Math.max(0, Math.min(1, current / total))); }; window.addEventListener('scroll', updateProgress, { passive: true }); updateProgress(); return () => window.removeEventListener('scroll', updateProgress); }, [ref]); return progress; }; ``` ## Accessibility Requirements Accessibility is non-negotiable. Scrollytelling can trigger vestibular disorders and exclude keyboard/screen reader users if not implemented correctly. ### Critical WCAG Criteria | Criterion | Requirement | |-----------|-------------| | **SC 2.2.2** | Auto-playing content >5 seconds needs pause/stop/hide controls | | **SC 2.3.3** | User-triggered animations must be disableable | | **SC 2.3.1** | No flashing more than 3 times per second | ### Reduced Motion Support (Mandatory) **Always** respect user preferences: ```css @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0s !important; animation-iteration-count: 1 !important; transition-duration: 0s !important; scroll-behavior: auto !important; } } ``` ```tsx const prefersReducedMotion = () => window.matchMedia('(prefers-reduced-motion: reduce)').matches; // In components - check before animating useEffect(() => {
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub