Modern CSS scroll-triggered animations using animation-timeline: view()
No JavaScript required for basic scroll animations!
✅ Supported: Chrome 115+, Edge 115+, Opera 101+
⚠️ Experimental: Firefox (behind flag), Safari (not yet supported)
Fallback: Elements display normally without animations in unsupported browsers
Elements fade in and slide up as they enter the viewport
This box fades up as you scroll down. The animation triggers when the element enters the viewport.
Each element animates independently based on its viewport position.
No JavaScript needed - pure CSS with animation-timeline: view()!
Alternate sliding directions create visual interest
Cards appear sequentially with slight delays
First Feature
Second Feature
Third Feature
Fourth Feature
Fifth Feature
Sixth Feature
Number scales and fades in (For actual counting, use JavaScript)
Bars fill horizontally as they scroll into view
Images unveil from left to right using clip-path
Background moves at different speed than scroll
The background moves at a different speed creating depth
.fade-up {
opacity: 0;
animation: fadeUp linear forwards;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
@keyframes fadeUp {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
Ensure content is accessible even without animation support:
/* Show content normally in unsupported browsers */
@supports not (animation-timeline: view()) {
.fade-up {
opacity: 1 !important;
transform: none !important;
}
}
For browsers that don't support animation-timeline: view():
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate');
}
});
}, {
threshold: 0.1
});
document.querySelectorAll('.fade-up').forEach(el => {
observer.observe(el);
});
entry 0% - Animation starts when element enters viewportcover 30% - Animation completes when element covers 30% of viewportprefers-reduced-motion media queryanimation-timeline: view()