Skip to content
All posts
· 5 min read

Motion that respects the user: reveals, reduced motion, and LCP

Scroll reveals are cheap to add and expensive to get wrong. How to animate with intent — without breaking accessibility or your Core Web Vitals.

UXPerformanceAccessibility
Motion that respects the user: reveals, reduced motion, and LCP — cover

Scroll reveals are the seasoning of modern web design: a little lifts the whole dish, too much ruins it. The difference between the two isn't taste — it's whether each animation has a job.

Every animation needs a job

  • Entrances confirm reading order — stagger siblings by index, around 80ms apart
  • Hover states confirm interactivity — a lift, a glow, an arrow nudge
  • Route transitions preserve context — one shared page-enter, nothing bespoke

Reduced motion is a requirement, not a nice-to-have

The classic failure: hide content with opacity zero, reveal it on scroll. If JavaScript fails — or the visitor prefers reduced motion — the content simply never appears. The fix is to do the hiding inside the media query, so the animated state is the exception, not the default.

css
/* hide for animation ONLY when motion is welcome */
@media (prefers-reduced-motion: no-preference) {
  [data-reveal] {
    opacity: 0;
    transform: translateY(22px);
  }
  [data-reveal].is-visible {
    opacity: 1;
    transform: none;
  }
}

Never gate the LCP on hydration

Hero entrances should be pure CSS animation, so the first paint never waits for a JavaScript bundle. Save observer-driven motion for below the fold, where a few dropped milliseconds cost nothing.

If the user notices your animation system, it's too loud. If they'd miss it when it's gone, it's right.

Motion done this way disappears into the experience: the page feels assembled rather than animated, and nobody can quite say why it feels good. That's the goal.