Scroll to an Element with JavaScript

Call element.scrollIntoView({ behavior: 'smooth', block: 'start' }) to bring an element into view. block decides where it lands vertically: start, center, end or nearest. If a sticky header covers the target, give the target scroll-margin-top equal to the header height in CSS instead of calculating offsets in JavaScript.

scrollIntoView options
OptionValuesDefault
behavior"smooth", "instant", "auto" (follows CSS scroll-behavior)"auto"
block (vertical)"start", "center", "end", "nearest""start"
inline (horizontal)"start", "center", "end", "nearest""nearest"
true / false instead of optionstrue = block start, false = block end (inline nearest)true

Updated

There are three ways to move the page to an element: scrollIntoView on the element, scrollTo with a pixel position, and a plain link to an id. The playground shows what each block value does and how scroll-margin-top keeps a heading clear of a fixed bar, then the examples cover the code you need for menus, form errors and chat style lists.

Scroll to element code

Smooth scroll to a section

Looks the element up by id and brings its top edge to the top of the view.

document.getElementById("pricing")
  ?.scrollIntoView({ behavior: "smooth", block: "start" });

Sticky header offset in CSS

One rule fixes the overlap for scripted scrolls and for links that end in #id. The media query skips the animation for people who prefer reduced motion.

:root { --header-h: 72px; }

[id] { scroll-margin-top: calc(var(--header-h) + 8px); }

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

Bring the first invalid field into view

center keeps the field and its label in the middle of the screen; focus moves keyboard users there too.

form.addEventListener("submit", (e) => {
  const bad = form.querySelector(":invalid");
  if (!bad) return;
  e.preventDefault();
  bad.scrollIntoView({ behavior: "smooth", block: "center" });
  bad.focus({ preventScroll: true });
});

Scroll only inside a panel

Uses the item's position inside the panel, so the page around it does not move.

function scrollPanelTo(panel, item, offset = 0) {
  const top = item.getBoundingClientRect().top
            - panel.getBoundingClientRect().top
            + panel.scrollTop - offset;
  panel.scrollTo({ top, behavior: "smooth" });
}

React: scroll to a ref

The ref points at the DOM node once it has rendered, so the call happens in a click handler or an effect.

function Faq() {
  const answerRef = useRef(null);
  return (
    <>
      <button onClick={() => answerRef.current?.scrollIntoView({ behavior: "smooth" })}>
        Jump to the answer
      </button>
      <section ref={answerRef}>...</section>
    </>
  );
}

Choosing a block value

start suits jumps to a section or heading, because the reader begins at the top of it. center works well for drawing attention to a single field, such as the first invalid input on a form. end fits a chat or log where the newest item should sit at the bottom.

nearest is the polite option: it moves the least distance needed and leaves visible items alone, which is what you want when an arrow key moves the highlight through a list.

Doing it without JavaScript

An ordinary link such as <a href="#pricing"> already scrolls to the element with id pricing, updates the address bar and works with the back button. Add scroll-behavior: smooth to the html element and scroll-margin-top to the targets, and many table of contents menus need no script at all.

Reach for JavaScript when the scroll follows something that is not a click on a link: a form failing validation, a new message arriving or a search result being selected.

How it works

  1. Pick a target row and a block value, then press Scroll. Only the demo box moves, so this page stays put.
  2. Raise the scroll margin to match the grey sticky bar and watch the target stop just below it.
  3. Switch behavior between smooth and instant to compare the two.
  4. Copy the generated scrollIntoView call and CSS rule for your own page.

Tips

Frequently asked questions

How do I scroll to an element with an offset for a fixed header?

Add scroll-margin-top to the target, for example h2 { scroll-margin-top: 80px }. The CSS scroll snap specification asks browsers to honour that margin for scrollIntoView and for links to #ids, even with no snapping in use.

How do I make scrolling smooth?

Pass behavior: 'smooth' to scrollIntoView or scrollTo, or set scroll-behavior: smooth on the html element so every programmatic scroll and in-page link animates. scroll-behavior has no effect on scrolling done by the user with a wheel or touch.

What is the difference between scrollIntoView and scrollTo?

scrollIntoView works from an element and figures out the position for you. window.scrollTo({ top, behavior }) moves to an exact pixel position, and scrollBy moves by a relative amount. Use scrollTo when you already have a number, such as returning to a saved position.

How do I scroll to the top of the page?

window.scrollTo({ top: 0, behavior: 'smooth' }). For a scrollable panel, call the same method on the panel element instead of window.

Why does scrollIntoView do nothing?

Common causes are calling it before the element exists (run it after render, for example in a React effect), the element being display: none, or the nearest option with an element that is already fully visible.

Related: Sticky header guide, Scroll animations, CSS scroll snap, JavaScript event listeners, JavaScript loops compared.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Guides

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap