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.

소스 정보

저장소
doodledood/claude-code-plugins
최근 소스 활동
2026년 1월 14일 06:35
감지된 SKILL.md 언어
영어
스타
20
포크
3

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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(() => {
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기