animation-timeline: view()
Reveal on scroll, with no observer
Scroll this panel.
- Each row fades in
- as it enters the view,
- driven by its own position
- inside the scroller.
- No IntersectionObserver,
- no listener, no classes
- toggled from a callback.
- Scroll back up:
- it plays in reverse.
CaveatPut the hidden state in the keyframe’s from, never on the element itself. Engines without view() ignore the timeline, the animation runs its zero-second duration and finishes — content simply appears. Hide elements with opacity: 0 in their own styles instead and those engines show a blank page forever. That inversion is the entire safety of this pattern.
Fallbackanimation-range: entry keeps the whole reveal inside the moment of arrival — without it the element keeps animating the entire way across the scroller. And unlike an observer, this reverses for free when the reader scrolls back.
li {
animation: rise linear both;
animation-timeline: view();
/* only while it is arriving */
animation-range: entry 0% entry 85%;
}
/* hidden lives HERE, not on li */
@keyframes rise {
from { opacity: 0; translate: 0 16px; }
}
Published