LoginSignup
8
2

More than 3 years have passed since last update.

【スムーススクロール対応】scrollIntoViewで手軽にスライダー作成

Last updated at Posted at 2020-12-25

前置き

以下のような表示領域に複数スライドが表示されるスライダーを作りたいとき・・・

slider.png

要素のscrollLeftやtranslateXの値を操作することが多いのではないかと思います。

しかし、リキッド対応が必要な場合、このscrollLeftやtranslateXを用いた実装方法だと、 resize イベントのたびにスライドの width を再計算し直して、移動させる位置を調整する必要があるので少し手間がかかります。

そんなときにはscrollIntoViewを使うとサクッと実装できちゃいます。

もっと楽ができる。そう、 scrollIntoView ならね

scrollIntoViewとは

Element インターフェイスの scrollIntoView() メソッドは、scrollIntoView() が呼び出された要素がユーザーに見えるところまで、要素の親コンテナーをスクロールします。

引用元: scrollIntoView() - MDN

以下のように記述すると、要素を見えるところまで持ってきてくれるメソッドです。

element.scrollIntoView();

引数にboolean値を渡すことで表示要素を表示領域の上端/下端のどちらに来るようにするかを設定できます。
規定値はtrueです。

  • true の場合、要素の上端がスクロール可能な祖先の表示範囲の上端に来るようにスクロールします。
  • false の場合、要素の下端がスクロール可能祖先の表示範囲の下端に来るようにスクロールします。

引用元: scrollIntoView() - MDN

スライダー実装に使う際の注意点

スライダーを作成する場合は、表示させたいスライドに対してscrollIntoVeiwメソッドを呼び出すだけでOK!と、言いたいところなのですが、1点注意が必要です。

scrollIntoView();を実行するだけだと、

  • スライダーだけでなく画面全体がスクロールしてしまう
  • スムーススクロールの対応ができない
  • スライドを表示領域の中央に表示する、などの位置調整ができない

という問題が起こります。
以下は上記の問題が起こっている実装例です。


See the Pen
scrollIntoViewSlider
by yuki-kojima (@kjkj_ongr)
on CodePen.


これはいかん。

これを解決するためには、scrollIntoViewの引数にオプションとして渡せるscrollIntoViewOptionsを指定する必要があります。

scrollIntoViewOptionsとは

IE と Safari を除くブラウザで対応している、scrollIntoViewオプション設定です。
boolean値の代わりに、以下のようにscrollIntoViewOptionsを引数で渡すことで、対象要素を表示させる位置とスムーススクロールの有無を設定できます。

element.scrollIntoView({
  behavior: "smooth",  // スムーススクロールを有効化: auto/smooth
  block: "end",  // 上下方向の位置: start/center/end/nearest
  inline: "start" // 水平方向の位置: start/center/end/nearest
});

先述した通り、引数を渡さない場合はtrueを渡した状態がセットされるのですが、scrollIntoViewOptionsで言う所の{block: "start", inline: "nearest"}が適用されてしまうため、画面全体が上部にスクロールしてしまったのでした。

スライダー実装時は、block: "nearest"とすることで画面全体がスクロールしてしまうことを防ぎます。

以下はクリックしたボタンに応じたスライドを表示するスライダーをscrollIntoViewを用いて実装した例です。
対象要素の水平方向の表示位置をスライダーの中央とし、スムーススクロールを適用しています。
一応リキッド対応もしております。

See the Pen scrollIntoViewSlider-options by yuki-kojima (@kjkj_ongr) on CodePen.

これでスライダーもお手軽に実装できちゃいますね。
そう、 IE と Safari 以外なら。

先生、IEとSafariでもscrollIntoViewOptionsを使いたいです

そんな時におすすめなのはscroll-into-view-if-neededsmooth-scroll-into-view-if-needed

scroll-into-view-if-neededとは

まだ標準化されていないscrollIntoViewIfNeededのPonyfill1のnpmパッケージです。

scrollIntoViewIfNeededは、表示したい要素が表示領域にない場合だけスクロールするという仕様のもので、要素を表示領域に持ってきてくれる、という点は基本的にscrollIntoViewと同じです。

scrollIntoViewIfNeeded - MDN

このパッケージを使えば、scrollIntoViewをほぼ同じOptionで表示位置・スムーススクロールの有無を設定できます。
呼び出し方についても、表示したい要素を第一引数に渡す以外はscrollIntoViewとほぼ同じです。

import scrollIntoView from 'scroll-into-view-if-needed'

scrollIntoView(taregtElement, {
  behavior: "smooth",  // スムーススクロールを有効化: auto/smooth
  block: "end",  // 上下方向の位置: start/center/end/nearest
  inline: "start" // 水平方向の位置: start/center/end/nearest
});

ただし注意したいのは、behaviorオプションをsmoothにしても、スムーススクロール対応のブラウザでしか有効になりません。
IEやSafariなどでもスムーススクロールを実装したい場合は、 smooth-scroll-into-view-if-needed を使います。

smooth-scroll-into-view-if-needed とは

scroll-into-view-if-neededのスムーススクロールも Ponyfill してくれるパッケージです。同じ開発者によるパッケージで、利用方法も全く同じです。
全ブラウザでスムーススクロールを有効にすることが優先ならば、こちらを利用しましょう。

import smoothScrollIntoViewIfNeeded from 'smooth-scroll-into-view-if-needed'

smoothScrollIntoViewIfNeeded(taregtElement, {
  behavior: "smooth",  // スムーススクロールを有効化: auto/smooth
  block: "end",  // 上下方向の位置: start/center/end/nearest
  inline: "start" // 水平方向の位置: start/center/end/nearest
});

ちなみにIE対応する場合は、PromiseのPolyfillが必要なので適宜追加してください。

IEとSafariでもスムースなスライダーを作ってみる

以下は smooth-scroll-into-view-if-needed を用いてスライダーを作った例です。

See the Pen smooth-scroll-into-view-if-needed-slider by yuki-kojima (@kjkj_ongr) on CodePen.

実にスムースですね。(※個人の感想です)

まとめ

2020年ももう終わりですね。1年の思い出をスライダーにしてみてはいかがでしょうか。


  1. Ponyfillについてはこちらを参照ください 

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2