Scroll an element into the center of the viewport

Published 2018-12-10 category: code

Say your page displays a list of names and you want a certain person to be highlighted and scrolled into view. There’s a browser API for that: Element.scrollIntoView(), which scrolls an element into view.

Element.scrollIntoView() can take two types of elements: a boolean or an object. The object argument gives developers more control over how elements ‘in view’ are aligned, but has slightly less browser support. Let’s look at what we can do with both.

The boolean argument

Say, you have a couple of people in a list:

<ul>
  <li id="alice">Alice Cruz</li>
  <li id="daniel">Daniel Ho</li>
  …
  <li id="julie">Julie Howard</li>
  …
</ul>

(Example on Codepen)

If you want Julie to be scrolled into view, find the relevant element, then call scrollIntoView():

const julie = document.getElementById('julie');

julie.scrollIntoView();

This scrolls the element into view. With a boolean argument, you can have some control over alignment. If you pass true (default), the browser will scroll so that the element is at the top of your viewport or other scrollable element. With false, it scrolls so the element is at the bottom of the viewport:

julie.scrollIntoView(true) // align top
julie.scrollIntoView(false) // align bottom

Note that the underlying terminology is not ‘top’ or ‘bottom‘, I’ll get into that in the next section.

For most use cases, this boolean argument may be all you need. It lets you choose if you want the element to align top or bottom.

This isn’t always ideal, sometimes you may have a sticky header, so scrollling an element to the top of the document would not actually get it into view. If something like that is the case in your project, the object argument comes in handy. It gives more control over alignment and allows for smooth scroll.

The object argument

In the latest version, you can also pass Element.scrollIntoView() an object, which lets you set two things:

julie.scrollIntoView({
  behavior: "smooth" | "auto";
  block: "start" | "center" | "end" | "nearest";
  inline: "start" | "center" | "end" | "nearest";
});

Smooth scroll

With the behavior parameter, you can set whether scrolling should be instant, so the page just jumps to the element, or smoothly, over a number of seconds (to be decided by the browser).

Unsurprisingly, the "smooth" value triggers smooth scroll. The "auto" value triggers instant scroll, as long as the element’s computed value for the scroll-behavior in CSS is not "smooth".

Alignment

Where I’ve been saying ‘top’ and ‘bottom’, I should have said ‘start‘ or ‘end’. They are the logical properties that you might recognise from other recent CSS specs like Grid Layout and flexbox.

As a quick reminder, the inline direction is the direction in which your text runs: it is the direction in which the words of this article are added. The block direction is the opposite of that, it is where block level elements are stacked, or where paragraphs of this text are added.

In a page with a vertical scrollbar, on the block axis, start means top, end means bottom. That’s the case on this page, for instance. But if your page uses vertical writing mode, you’d scroll horizontally, like in Hui-Jing Chen’s example of Chinese typography; in those cases, start means right, end means left on the block axis.

Fallbacks can be tricky

All browsers that understand element.scrollIntoView() accept the boolean argument. But only some accept the object argument. The good thing is, browsers will fallback for you. The default for the boolean argument is true, which sets the equivalent to block: start. If you use the object argument to use block: center or block: end, browsers that don’t do the object argument, will regard the argument to be true (because objects are truthy). So you’ll end up with block: start in those browsers. That’s often great, except when it is the opposite of what you’re fallbacking for.

If your interface requires precisely control over scroll alignment, fallbacks can be tricky. As an alternative you can also roll your own alignment with element.scrollTo(), as Jan Hoogeveen pointed out (thanks Jan!). If you end up going for that, I would recommend using coordinates as an argument, as the object argument does not work in some recent browsers, including Edge. See also window.scrollTo on MDN.

In the works: scroll snap

If you find scrollIntoView interesting, you may be interested in Scroll Snap, too. This is new CSS, currently being worked on, which lets you define things like a padding for the scroll container. Rachel Andrew has written a guide on the basic concepts of Scroll Snap on MDN. Some of the properties are already available in some browsers.

Comments, likes & shares (23)

Marc Stalfoort, Anselm Hannemann, Jan Hoogeveen, Koen Kivits, TvGeest, Scott O'Hara and Rufus Witt liked this

Chris Heilmann wrote on 10 December 2018:
Scroll an element into the center of the viewport hiddedevries.nl/en/blog/2018-1…
Ilya Streltsyn wrote on 10 December 2018:
Оказывается, теперь можно делать scrollIntoView не только к верхнему/нижнему краю окна, но и к центру — через объектную нотацию (правда, с фолбэками есть нюансы)
Web Platform News wrote on 10 December 2018:
Scrolling an element into the center of the viewport:

elem.scrollIntoView({ block: 'center' });

Safari and Edge don’t support this option and fall back to aligning the element to the top of the viewport.
CSS Basics wrote on 10 December 2018:
Heading structures are tables of contents, by @hdv hiddedevries.nl/en/blog/2018-0…
CSS Basics wrote on 10 December 2018:
Heading structures are tables of contents, by @hdv hiddedevries.nl/en/blog/2018-0…
David liu wrote on 10 December 2018:
RT codepo8: Scroll an element into the center of the viewport hiddedevries.nl/en/blog/2018-1…
Designer+Developer Day wrote on 14 December 2018:
[For Developer - JS] Scroll an element into the center of the viewport.

hiddedevries.nl/en/blog/2018-1…?
Designer+Developer Day wrote on 14 December 2018:
[For Developer - performance] Up to speed with web performance. hiddedevries.nl/en/blog/2018-1…
Calum Ryan | calumryan.com wrote on 14 December 2018:
Scroll an element into the center of the viewport - no weighty frameworks or additional markup. » (hiddedevries.nl/en/blog/2018-1…) (calumryan.com/note/2251)
HTML & CSS wrote on 14 December 2018:
css: Scroll an element into the center of the viewport hiddedevries.nl/en/blog/2018-1…
CSS-Tricks wrote on 14 December 2018:
Scroll an element into the center of the viewport hiddedevries.nl/en/blog/2018-1…
Mr. HAW ✪ wrote on 28 December 2018:
Scroll an element into the center of the viewport hiddedevries.nl/en/blog/2018-1… #js #webdesign
Momin Riyadh wrote on 18 January 2019:
Scroll an element into the center of the viewport !

hiddedevries.nl/en/blog/2018-1… https://t.co/3gdAYUs0OI
rajakvk wrote on 18 January 2019:
Nice method, never knew before !!!
Scroll an element into the center of the viewport
hiddedevries.nl/en/blog/2018-1…
Junior Gantin wrote on 14 September 2020:
Scroll an element into the center of the viewport hiddedevries.nl/en/blog/2018-1…
Digitalworx wrote on 15 September 2020:
Here's how to scroll to an element into view. #webdeveloper #webdevelopment #webdev hiddedevries.nl/en/blog/2018-1…