x ai css scroll animation 2026-06-14
Scroll-driven animations (also called scroll-linked or scroll-progress animations) in CSS let you tie CSS animations directly to the user's scroll position instead of time. As the user scrolls, the animation "scrubs" forward or backward smoothly.
This is a modern, declarative feature (part of the CSS Scroll-driven Animations module) that runs off the main thread for excellent performance — no JavaScript required for basic use cases.
Core Concepts
There are two main types of scroll timelines:
-
scroll()timeline — Links the animation to the overall scroll progress of a scroll container (e.g., the page or a specific overflowing element). The animation progresses from 0% to 100% as you scroll from start to end. -
view()timeline — Links the animation to an element’s position/visibility within the scrollport (viewport of the scroller). Great for “fade in as it enters view,” parallax, or reveal effects.
Basic Syntax
/* Define keyframes as usual */ @keyframes example { from { opacity: 0; transform: translateY(50px); } to { opacity: 1; transform: translateY(0); } } /* Apply the animation with a scroll timeline */ .element { animation: example 1s linear both; /* duration is often ignored or used as a hint */ animation-timeline: scroll(); /* or view(), or a named timeline */ animation-range: 0% 100%; /* optional: control start/end of the range */ }
Important notes:
animation-timelinemust come after theanimationshorthand.- Use
lineartiming for most scroll effects (oreasedepending on need). - Add feature detection:
@supports (animation-timeline: scroll()) { ... } - Respect
prefers-reduced-motion.
Common Examples
1. Reading Progress Bar (scroll() timeline)
.progress-bar { position: fixed; top: 0; left: 0; height: 4px; background: blue; transform-origin: left; animation: grow linear forwards; animation-timeline: scroll(root block); /* root = document, block = vertical scroll */ } @keyframes grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
2. Element Reveal / Fade-in on Scroll (view() timeline)
.card { animation: fadeUp linear both; animation-timeline: view(); animation-range: entry 0% cover 50%; /* animate during entry and part of coverage */ } @keyframes fadeUp { from { opacity: 0; transform: translateY(40px); } to { opacity: 1; transform: translateY(0); } }
3. Parallax Effect
.parallax-bg { animation: parallax-shift linear; animation-timeline: scroll(); } @keyframes parallax-shift { from { transform: translateY(0); } to { transform: translateY(-200px); } }
Key Properties
animation-timeline:scroll(),view(), or a named--timeline-name.animation-range: Controls when the animation starts and ends relative to the timeline (e.g.,entry,exit,cover, percentages).scroll-timeline-name/scroll-timeline-axis(on the scroller): For named timelines when you need more control (horizontal scroll, specific containers).view-timeline-name/view-timeline-axis: Similar for view timelines.
Browser Support
- Chrome/Edge: Excellent support (115+).
- Safari: Good and improving (recent versions).
- Firefox: Behind (often behind a flag).
Always test and use progressive enhancement.
Tips & Best Practices
- Combine with
position: stickyfor advanced effects. - For horizontal carousels, use
scroll(inline). - You can still use JavaScript (Web Animations API) for more complex control.
- Performance is generally very good because it leverages the compositor.
Would you like a complete self-contained HTML demo, help with a specific effect (progress bar, image reveal, sticky header shrink, etc.), or examples for named timelines? Just let me know!