Scroll-Driven View Transitions
See the Pen Scroll-Driven View Transitions.
Tech & Dependencies
Features
- ✓ Scroll Timeline
- ✓ Scroll Snap
- ✓ View Transitions
- ✓ Pure CSS
Browser Support
Core
This is a Scroll-Driven View Transitions component. It simulates app-like, full-screen transitions between content sections using only native CSS properties. Its function is to replace traditional vertical scrolling with a more engaging, cinematic experience, where each scroll action triggers a complex animation (like a “melt”, slide, or zoom) rather than a simple positional change.
Specs
- Weight: ~2 KB. Zero dependencies (though a polyfill is used for Firefox
animation-timelinesupport). - Performance: Ultra-high. By tying CSS animations directly to the scrollbar position (
animation-timeline: --section), the component offloads all the heavy lifting to the browser’s compositor, avoiding janky JavaScript scroll event listeners. - Theming / Customization: Easily adaptable. The user can switch between different animation types (
blink,horizontal-scroll,zoom-scroll) via radio buttons, which are linked to the component using the CSS:has()pseudo-class. - Responsiveness: Native. Uses dynamic viewport height units (
100dvh) to ensure sections are always full-screen. - Graceful Degradation: [!] Highly experimental. Relies heavily on
scroll-snap-type,timeline-scope, andview-timeline. In unsupported browsers (like current versions of Safari), it will behave like a standard, long-scrolling webpage without the snapping or transition effects.
Anatomy
The component uses a clever layering hack to separate the scrolling mechanism from the visual content.
- HTML (The Skeleton): A
<main>wrapper contains five full-height<section>elements. Inside each section is a.contentdiv. - CSS (The Skin): This is where the magic happens. The
<section>elements are part of the normal document flow and provide the scrollable height. The.contentdivs, however, are taken out of the flow withposition: fixed, stacking them all on top of each other. - JS (The Nervous System): Absent. Interaction is handled by the browser’s native scroll and input state mechanisms.
Logic
The core logic is the “Fixed Content Swap”:
.section {
scroll-snap-align: start;
view-timeline: --section;
height: 100dvh;
}
.content {
position: fixed;
inset: 0;
animation: blink ease-in-out both;
animation-timeline: --section;
}
As the user scrolls, they are actually scrolling through the invisible <section> elements. The scroll-snap-align forces the viewport to lock perfectly to the start of each section. Crucially, each .content div’s animation is tied to its parent <section>’s visibility via animation-timeline: --section. The @keyframes blink animation is designed to be fully visible only at the 50% mark of the timeline (when the section is centered in the viewport). As you scroll from one section to the next, the old content animates out (from 50% to 100%) while the new content animates in (from 0% to 50%), creating a seamless cross-fade.
Feel
Cinematic and immersive. The “melt” effect, created by animating filter: blur() contrast(), makes the content appear to dissolve and reform with each scroll. Because scroll-snap-type: y mandatory hijacks the standard scroll behavior, the experience feels less like a webpage and more like presenting slides in a high-end application like Keynote or a polished mobile app.


