--- name: elite-css-animations description: | CSS-native animation techniques including Scroll-Driven Animations API, View Transitions, @property rule, and visual effects. Use when asked about: CSS animations, scroll-driven animations, CSS scroll timeline, view transitions, page transitions, @property, animating CSS variables, clip-path animations, backdrop-filter, mix-blend-mode, CSS masks, CSS-only animations, no-JavaScript animations, or when GSAP is not needed/wanted. Includes decision guide for CSS vs GSAP. --- # Elite CSS Animations Modern CSS animation capabilities - when JavaScript isn't needed. ## Quick Reference | Topic | Reference File | |-------|---------------| | Scroll-Driven API | [scroll-driven-api.md](references/scroll-driven-api.md) | | View Transitions | [view-transitions.md](references/view-transitions.md) | | @property Rule | [property-rule.md](references/property-rule.md) | | Visual Effects | [visual-effects.md](references/visual-effects.md) | --- ## CSS vs GSAP Decision Guide ### Use CSS When: - Simple reveal/fade animations - Progress indicators tied to scroll - Hover/focus state transitions - Performance is paramount (off-main-thread) - Safari support isn't critical (for scroll-driven) - You want to minimize JavaScript ### Use GSAP When: - Complex multi-element sequences - Pin/sticky behavior needed - Horizontal scrolling sections - Cross-browser consistency critical - Fine-grained control (scrub with snap) - Timeline orchestration ### Hybrid Approach CSS for simple interactions, GSAP for complex sequences: ```css /* CSS: Hover states, simple transitions */ .card { transition: transform 0.3s ease, box-shadow 0.3s ease; } .card:hover { transform: translateY(-4px); box-shadow: 0 10px 30px rgba(0,0,0,0.15); } ``` ```javascript // GSAP: Complex scroll-driven sequences gsap.timeline({ scrollTrigger: { trigger: '.section', scrub: 1 } }) .from('.title', { opacity: 0, y: 50 }) .from('.content', { opacity: 0 }, '-=0.3'); ``` --- ## Browser Support (2026) | Feature | Chrome | Firefox | Safari | Edge | |---------|--------|---------|--------|------| | Scroll-Driven Animations | ✓ 115+ | ✓ 132+ | ✗ (polyfill) | ✓ 115+ | | View Transitions | ✓ 111+ | ✗ | ✓ 18+ | ✓ 111+ | | @property | ✓ 85+ | ✓ 128+ | ✓ 15.4+ | ✓ 85+ | | clip-path animations | ✓ | ✓ | ✓ | ✓ | | backdrop-filter | ✓ | ✓ | ✓ | ✓ | --- ## Scroll-Driven Animations Quick Start ```css /* Progress bar that fills as you scroll */ .progress-bar { transform-origin: left; transform: scaleX(0); animation: progress linear; animation-timeline: scroll(); } @keyframes progress { to { transform: scaleX(1); } } ``` ```css /* Element reveals as it enters viewport */ @media (prefers-reduced-motion: no-preference) { .reveal { animation: fadeIn linear both; animation-timeline: view(); animation-range: entry 0% cover 30%; } } @keyframes fadeIn { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } ``` ### Safari Polyfill ```html ``` See [scroll-driven-api.md](references/scroll-driven-api.md) for complete patterns. --- ## View Transitions Quick Start ```javascript // Simple page transition document.startViewTransition(() => { // Update the DOM updateContent(); }); ``` ```css /* Customize the transition */ ::view-transition-old(root) { animation: fade-out 0.3s ease-out; } ::view-transition-new(root) { animation: fade-in 0.3s ease-in; } @keyframes fade-out { to { opacity: 0; } } @keyframes fade-in { from { opacity: 0; } } ``` See [view-transitions.md](references/view-transitions.md) for SPA integration. --- ## @property Quick Start Animate CSS custom properties that previously couldn't animate: ```css @property --progress { syntax: ''; initial-value: 0; inherits: false; } .progress-circle { --progress: 0; background: conic-gradient( var(--color-accent) calc(var(--progress) * 360deg), transparent 0 ); transition: --progress 1s ease-out; } .progress-circle.complete { --progress: 1; } ``` See [property-rule.md](references/property-rule.md) for gradient animations and more. --- ## Visual Effects Quick Start ### Clip-Path Reveal ```css .reveal { clip-path: inset(0 100% 0 0); transition: clip-path 0.6s cubic-bezier(0.4, 0, 0.2, 1); } .reveal.visible { clip-path: inset(0 0 0 0); } ``` ### Backdrop Filter ```css .glass { backdrop-filter: blur(10px) saturate(180%); background: rgba(255, 255, 255, 0.7); } ``` ### Mix Blend Mode ```css .text-overlay { mix-blend-mode: difference; color: white; } ``` See [visual-effects.md](references/visual-effects.md) for creative patterns. --- ## prefers-reduced-motion **Always wrap motion in preference checks:** ```css /* Default: No animation */ .animated { opacity: 1; transform: none; } /* Only animate if user allows */ @media (prefers-reduced-motion: no-preference) { .animated { animation: fadeIn 0.6s ease-out; } } ``` --- ## Performance Best Practices ### Animate Only Compositor Properties ```css /* GOOD - GPU accelerated */ .card { transition: transform 0.3s, opacity 0.3s; } .card:hover { transform: translateY(-4px) scale(1.02); opacity: 0.9; } /* BAD - Triggers layout/paint */ .card:hover { width: 110%; margin-left: -5%; box-shadow: 0 10px 30px rgba(0,0,0,0.3); } ``` ### Use will-change Sparingly ```css /* Apply only during animation */ .animating { will-change: transform, opacity; } /* Remove after animation */ .animation-complete { will-change: auto; } ``` ### Contain Property ```css /* Isolate expensive effects */ .animated-section { contain: layout style paint; } ``` --- ## Common Patterns ### Smooth Hover Transitions ```css .card { transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .card:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15); } ``` ### Staggered Entrance ```css .item { opacity: 0; animation: fadeIn 0.5s ease forwards; } .item:nth-child(1) { animation-delay: 0.1s; } .item:nth-child(2) { animation-delay: 0.2s; } .item:nth-child(3) { animation-delay: 0.3s; } /* ... or use CSS custom properties */ @keyframes fadeIn { to { opacity: 1; } } ``` ### Loading Spinner ```css .spinner { width: 40px; height: 40px; border: 3px solid var(--color-border); border-top-color: var(--color-accent); border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } ``` --- ## Resources - [MDN: CSS Animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations) - [MDN: Scroll-driven animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll-driven_animations) - [Chrome: View Transitions](https://developer.chrome.com/docs/web-platform/view-transitions/) - [Cubic Bezier Generator](https://cubic-bezier.com/)