Smooth scrolling and scroll-to-anchor

scroll-behavior: smooth with scroll-margin-top

Baseline widely available
  • Chrome61
  • Edge79
  • Firefox36
  • Safari15.4

Features it needs

One CSS declaration makes every in-page anchor and every scrollIntoView call animate instead of jump. The piece people miss is scroll-margin-top, which stops a sticky header from covering the heading you just scrolled to, and it works for both anchor links and focus. Gate the whole thing behind prefers-reduced-motion, because a long smooth scroll is a common motion-sickness trigger.

When this applies

Making in-page anchor links scroll smoothly to their target.

The native approach

@media (prefers-reduced-motion: no-preference) {
  :root {
    scroll-behavior: smooth;
  }
}

/* Stop a sticky header covering the target. */
:target,
[id] {
  scroll-margin-top: 5rem;
}

MDN reference

When the dependency is still right

An answer that always says "the platform covers it" is worse than no answer. These are the cases where this one does not hold.

  • You need to control the duration or easing of the scroll. CSS gives you no handle on either, and browsers differ.
  • You need a callback when the scroll finishes. scrollend helps, but it is newer than scroll-behavior itself.
  • You need to scroll to a coordinate that is computed rather than to an element.
  • You need scroll spy, meaning highlighting the nav item for the section currently in view. That is a separate problem and still needs JavaScript or scroll-driven animations.

Building it

This catalog stops at the swap. These guides go through the implementation and the fallbacks. They come from Google Chrome's modern-web-guidance, Apache-2.0.

Packages this covers