Quick tip: using scrollIntoView() to show added elements to a container with overflow
Tags: dom, javascript, api, tops
Published: 2019-08-09 14:14:25

---
title: Quick tip: using scrollIntoView() to show added elements to a container with overflow
published: true
description: How to add new elements to a scrolling container and showing them immediately
tags: DOM,JavaScript,API,tops
---

Often we want to have an interface where we have a container with overflow: scroll with a header and a footer. 

One problem with that is that when we add new elements to the container, they do get added to the end of it but the element won't show up before the user scrolls down. 

In the past we hacked around this issue by comparing `scrollHeight` and `clientHeight` and setting the `scrollTop` property of the element. This is error prone and seems overly complicated. 

Enter [scrollIntoView()](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView). Using this API ensuring that a new element shows up to the user is as simple as calling it on the element itself. 

Say we have the following list of characters and a button to add more of them.

```xml
<div class="scrollbody">
    <ul>
        <li>Billy Butcher</li>
        <li>Hughie Campbell</li>
        <li>Mother's Milk</li>
        <li>The Frenchman</li>
  </ul>
</div> 
<button>Add new character</button>
```

In the CSS, we limit the body to scroll and set it to overflow.

```css
.scrollbody {
  height: 6em;
  overflow: scroll;
}
```
With a bit of JavaScript, we can now add new characters every time we click the button:

```javascript
let characters = ['The Female (of the Species)',
'Lieutenant Colonel Greg D. Mallory','The Legend','The Homelander',
'Black Noir','Queen Maeve','A-Train','The Deep','Jack from Jupiter',
'The Lamplighter','Starlight','Mister Marathon','Big Game',
'DogKnott','PopClaw','Blarney Cock','Whack Job',
'Gunpowder','Shout Out'];

let count = 0;
document.querySelector('button').addEventListener('click', (ev) => {
    if (count < characters.length) {
    let item = document.createElement('li');
    item.innerText = characters[count];
    document.querySelector('ul').appendChild(item);
    count = count + 1;
  }
  ev.preventDefault;
});
```
Now, if you try this out, you see that the new characters are in fact added, but not visible until you scroll down to them.

{% codepen https://codepen.io/codepo8/pen/xvarxB %}


![elements not showing until the user scrolls](https://christianheilmann.com/wp-content/uploads/2019/08/without-scrollintoview.gif)

That's bad. To remedy this, you all you need to to is to add the scrollIntoView call after adding the new list item:

```javascript
/* list of characters */
let count = 0;
document.querySelector('button').addEventListener('click', (ev) => {
    if (count < characters.length) {
    let item = document.createElement('li');
    item.innerText = characters[count];
    document.querySelector('ul').appendChild(item);

    item.scrollIntoView();

    count = count + 1;
  }
  ev.preventDefault;
});
```

{% codepen https://codepen.io/codepo8/pen/RXYgJK %}


![scrollintoview showing the new elements](https://christianheilmann.com/wp-content/uploads/2019/08/scrollintoview-without-smooth.gif)

As an extra bonus, you can define the behaviour of the scroll to be smooth, which scrolls it in slowly and not as jarringly:

```javascript
/* list of characters */
let count = 0;
document.querySelector('button').addEventListener('click', (ev) => {
    if (count < characters.length) {
    let item = document.createElement('li');
    item.innerText = characters[count];
    document.querySelector('ul').appendChild(item);

    item.scrollIntoView({behavior: 'smooth'});

    count = count + 1;
  }
  ev.preventDefault;
});
```
{% codepen https://codepen.io/codepo8/pen/wVEeQm %}

![scrollintoview showing the new elements smoothly](https://christianheilmann.com/wp-content/uploads/2019/08/scrollintoview-with-smooth.gif)

Another reminder to keep looking into what's in the standard these days rather than finding an old solution on StackOverFlow and keep too complex and not browser-optimised code alive.