Scroll-triggered reveal
An element sits hidden until it scrolls into the viewport, then plays its entrance once, usually a short fade and rise.
See it
What it is
A scroll-triggered reveal keeps an element in its hidden state until it crosses into the viewport, then fires its entrance once and leaves it alone. The house style is a 300ms to 500ms fade plus a 16px to 24px rise. Classic implementations: IntersectionObserver toggling a class, the AOS library, or GSAP ScrollTrigger. Native CSS 'animation-timeline: view()' looks like a fourth one but does something different: it ties progress to scroll position, so with an 'animation-range' of entry you get a scroll-linked reveal that rewinds when the user scrolls back up. Good if that is what you want, wrong if you wanted a one-shot.
Do not confuse it with scroll-linked animation. A reveal is a trigger: scroll position starts it, then time runs it, and scrolling back up does not rewind it. Scrubbing binds progress directly to scroll so it plays backwards when you do. Reveals are for content sections; scrubbing is for scrollytelling.
Gotchas, in order of how often they bite. One: if the initial state is 'opacity: 0' and the script fails, the whole page is blank forever, so gate the hidden state behind a 'js' class on the root. Two: never reveal above-the-fold content, since the user is already looking at it and gets a flash of nothing. Three: trigger a little before the element is fully in view (rootMargin around '0px 0px -15%') or the animation finishes off-screen. Four: honor prefers-reduced-motion by showing the content immediately.
Ask AI for it
Add scroll-triggered reveals to these sections: each starts at opacity 0 and translateY 20px, and when it enters the viewport it animates to opacity 1 and translateY 0 over 450ms with a cubic-bezier(0.16, 1, 0.3, 1) curve. Use IntersectionObserver with threshold 0.15 and rootMargin '0px 0px -10% 0px', unobserve after the first trigger so it never replays, and stagger children by 60ms. Skip the effect for anything above the fold, apply the hidden state only when JS is running, and show everything instantly under prefers-reduced-motion.