あまり知られてなさそうなメソッド element.scrollIntoView()

#はじめに

とあるHTML要素の位置までスクロールさせたい時、JavaScriptでどのように書いていますか？

要素が上端に来るようにスクロールさせたいなら……

```js:jQuery
var offset = $('#targetElement').offset() || {top: 0, left: 0};

$(window).scrollTop(offset.top);
```

要素が下端に来るようにスクロールさせたいなら……

```js:jQuery
var
  $target = $('#targetElement'),
  offset = $target.offset() || {top: 0, left: 0},
  outerHeight = $target.outerHeight();

$(window).scrollTop(offset.top - window.innerHeight + outerHeight);
```

はたまた、要素が画面中央に来るようにスクロールさせたいなら……

```js:jQuery
var
  $target = $('#targetElement'),
  offset = $target.offset() || {top: 0, left: 0},
  outerHeight = $target.outerHeight();

$(window).scrollTop(offset.top - (window.innerHeight - outerHeight) / 2);
```

なんかめんどくさい……

#`element.scrollIntoView()` の出番

とりあえずMDNで見てみましょう。

[element.scrollIntoView - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/Element/scrollIntoView)

> `scrollIntoView()` メソッドは、要素が（ブラウザのウィンドウ上の）表示範囲に入るまでページをスクロールします。

こんなのあったんですね。
引数を省略または `true` とすることで上端に来るようにスクロールし、`false` ならば下端に来るようにスクロールします。

```js:例
var element = document.getElementById('targetElement');

// 上端に来るようにスクロールさせたい
element.scrollIntoView();  // or
element.scrollIntoView(true);

// 下端に来るようにスクロールさせたい
element.scrollIntoView(false);
```

要素の位置によっては必ずしも上端・下端になるわけではないのはまぁわかりますよね。

#一部ブラウザでは更にオプションでいろいろできる

一部のブラウザでは細かいオプションが指定でき、スムーズスクロールなども可能になります。
[Can I use... - scrollIntoView](http://caniuse.com/#search=scrollIntoView)

また、英語版のMDNの方には細かい設定についても書かれています。
[Element.scrollIntoView() - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)

これを書いた時点では、最新の Firefox と Chrome のみ対応しているようです。

```js:初期値
element.scrollIntoView({
  behavior: 'auto',
  block: 'center',
  inline: 'nearest',
});

// このように書いても同じ
element.scrollIntoView({});
```

それぞれの指定方法は以下です。

##`behavior`

`behavior` プロパティは、その名の通りスクロールの動作を文字列で指定します。
アニメーションの速度は指定できないようです。

指定できる値は以下の3つです

####・`"auto"`

`behavior` プロパティの初期値です。
ブラウザの初期の動作です。多くの場合は `"instant"` と同じ、つまりアニメーションしません。

####・`"instant"`

アニメーションせずにすぐに特定の位置までスクロールします。

####・`"smooth"`

スムーズなアニメーションで特定の位置までスクロールします。

##`block`

`block` プロパティは、（通常は）垂直方向のスクロール位置を文字列で指定します。

####・`"start"`

要素が上端に来るようにスクロールします。

####・`"center"`

`block` プロパティの初期値です。
要素が画面の垂直方向中央に来るようにスクロールします。

####・`"end"`

要素が下端に来るようにスクロールします。

####・`"nearest"`

現在のスクロール位置から見て `"start"` か `"end"` のどちらか近い方が適用されます。


##`inline`

`inline` プロパティは、（通常は）水平方向のスクロール位置を文字列で指定します。
これは例えば `dir="rtl"` のように文章を右から左へ綴るページなどでは左右が反転する可能性があります。

####・`"start"`

要素が左端に来るようにスクロールします。

####・`"center"`

要素が画面の水平方向中央に来るようにスクロールします。

####・`"end"`

要素が右端に来るようにスクロールします。

####・`"nearest"`

`inline` プロパティの初期値です。
現在のスクロール位置から見て `"start"` か `"end"` のどちらか近い方が適用されます。

---

ということは、`true` or `false` は以下と同じということですね。

```js
var element = document.getElementById('targetElement');

// この3つは同じ
element.scrollIntoView();
element.scrollIntoView(true);
element.scrollIntoView({block: 'start', inline: 'nearest'});

// この2つは同じ
element.scrollIntoView(false);
element.scrollIntoView({block: 'end', inline: 'nearest'});
```

オプションを組み合わせて好きな動作ができます。

```js:記述例
var element = document.getElementById('targetElement');

// 要素が下端に来るスムーズなスクロール
element.scrollIntoView({behavior: 'smooth', block: 'end'});

// 横長いページで要素が画面中央に来るようにスクロール
element.scrollIntoView({inline: 'center'});
```

#おわりに

`true` / `false` の指定以外はまだ実用的ではないですが、無駄にスクロール位置の計算をしなくても済みそうですね。