Why we do not use AOS for scroll animation
The popular scroll-reveal library carries costs you cannot see in a demo. We replaced it with forty lines.
AOS is the library most people reach for when they want content to fade in as the page scrolls. It installs in a minute and works from a single attribute, which is exactly why it spread so widely.
The trouble starts on a server-rendered site. AOS runs after hydration, so for a fraction of a second the content renders normally, then gets hidden, then fades back in. A visitor reads that as a flicker. Core Web Vitals reads it as Cumulative Layout Shift.
The fix is to move the initial state into CSS, so the hidden state ships with the server-rendered HTML, and leave JavaScript exactly one job: set an attribute when IntersectionObserver reports the element has entered the viewport.
The result has no flash, no layout shift, and no additional library in the bundle. The whole thing is about forty lines.
The case people forget is what happens when JavaScript never runs. If content is hidden with opacity: 0 and only JavaScript can reveal it, a page loaded without scripts is a blank page — and that includes the case where the script simply fails to load. A rule inside noscript that undoes the hiding costs nothing and removes the failure mode entirely.
Finally, accessibility. Some people set their system to reduce motion because animation makes them ill. Respecting prefers-reduced-motion is a WCAG requirement rather than a nicety, and writing the component yourself puts that switch directly under your control.
