scrollIntoView is the best thing since sliced bread
Tags: html, javascript, webdev, angular
Published: 2019-04-11 14:54:36

Making elements scroll into view used to be hard, especially with animation. Now it's super easy with `Element.prototype.scrollIntoView`!  

I've been working on an online art gallery for [@sueish](https://www.instagram.com/sueish/). She is an amazing artist. Curators need to focus on her artwork, so going for the super minimal look.

![](https://thepracticaldev.s3.amazonaws.com/i/qqwgdk4rxzqh39dc6xwe.png)

I need the digital equivalent of walking through a gallery so here I am again building an image carousel. I tried to think of all the times I coded a carousel but then I remembered I lost count a long time ago. There was one point an image carousel I built was used on every lexus.com car model page in the US. 

Years ago it took a lot of code to animate the slides in and out of view. The solution involved some simple math and a mechanism for dynamically calculating width of each slide and the overall container. Once you figured out where the position the carousel started and where it had to land, you had to implement a way to tween the position of the element. It took several lines of code. Now all you need is one.

```typescript
document.querySelector('some-element').scrollIntoView({behavior: 'smooth'});
```

![](https://media.giphy.com/media/1lDEF1FpUmag6r37rc/giphy.gif)


The above line of code selects an element and animates it scrolling into view.


I'm coding this app with Angular just because that's what I use all the time. I have been venturing into web components lately, but I need to ship this site quick. The template of my Angular Component looks like this. 

```html
<img class="ctrl --left" src="/assets/arrow-left.svg" (click)="slide('-')">
<img class="ctrl --right" src="/assets/arrow-right.svg" (click)="slide('+')">

<div class="gallery" #gallery>
  <div class="slide" #slide *ngFor="let media of (media$ | async)" >
    <img [attr.src]="fetchImage(media.filename)" />
  </div>
</div>

```

There's some stuff going on here. Event listeners for click are bound to the left and right buttons. `ngFor` loops through a data model, an array of Media. I'm using the `async` Pipe because `media$` is an Observable. In a service an http request fetches the data model and this component is subscribed to the response. The `src` of each image gets set by a property on the `Media` object. 

I select each slide with `ViewChildren` in my Angular component.

```typescript
@ViewChildren('slide') slides: QueryList<ElementRef>;
```

In the template I tagged each div with `#slide`, allowing me to select the slide elements.

When the user clicks either arrow button, the slide method is called on my component.

```html
<img class="ctrl --left" src="/assets/arrow-left.svg" (click)="slide('-')">
<img class="ctrl --right" src="/assets/arrow-right.svg" (click)="slide('+')">
```


In the slide method we keep track of the current index and call the `animate` method, making sure the user can't go past the first slide into negative territory or beyond the last slide. 

```typescript
 slide(ctrl: string) {
    if (ctrl === '-') {
      if (this.index > 0) {
        this.index = this.index - 1;
        this.animate('-');
      }
    }
    if (ctrl === '+') {
      if (this.index < this.length - 1) {
        this.index = this.index + 1;
        this.animate('+');
      }
    }
  }
```


When I started coding this carousel I assumed `animate` would need to know direction. If you remember from earlier, it used to take a lot of math to animate a slide. The positive or negative direction was essential to figure out if the carousel needed to move left or right. Turns out `scrollIntoView` doesn't need to interpret the direction. `scrollIntoView` just animates in the element.

This is the method I ended up with that animates the slides in this carousel.

![](https://media.giphy.com/media/9Jcw5pUQlgQLe5NonJ/giphy-downsized-large.gif)

```typescript
animate() {
  this.slides.toArray()[this.index].nativeElement.scrollIntoView({behavior: 'smooth'});
}

```

For a complete reference of Element.prototype.scrollIntoView, [visit MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView).


I just think this `scrollIntoView` API the best thing since sliced bread. At least if you ❤️ to carb it up like I do. Animating an element scrolling into view is a very nice way to provide feedback to the user. We get this behavior practically for free with `Element.prototype.scrollIntoView`. Like all other bright and shiny new APIs I am left to wonder if I can use this in every browser. 

Looking at the [Can I use](https://caniuse.com/#feat=scrollintoview) table nearly every browser shows only partial support, having left out the only feature I really care about: the smooth behavior!

![](https://media.giphy.com/media/sANGK3xBT0ipq/giphy.gif)

Luckily [there is a polyfill](https://www.npmjs.com/package/smoothscroll-polyfill) that fixes this behavior until browsers widely support 'smooth', that is if they ever do.

There's still some work to do on this carousel, but so far I am impressed I could animate images so quickly. There is a cost to this approach. The native scrollbar remains. This carousel won't look so minimal in Windows. Looks like I am back to figuring out a way to transition slides once again. Good thing we have the Web Animations API.

![](https://media.giphy.com/media/NHUONhmbo448/giphy.gif)

To be continued...