前置き
以下のような表示領域に複数スライドが表示されるスライダーを作りたいとき・・・
要素のscrollLeftやtranslateXの値を操作することが多いのではないかと思います。
しかし、リキッド対応が必要な場合、このscrollLeftやtranslateXを用いた実装方法だと、 resize イベントのたびにスライドの width を再計算し直して、移動させる位置を調整する必要があるので少し手間がかかります。
そんなときにはscrollIntoView
を使うとサクッと実装できちゃいます。
もっと楽ができる。そう、 scrollIntoView ならね
scrollIntoViewとは
Element インターフェイスの scrollIntoView() メソッドは、scrollIntoView() が呼び出された要素がユーザーに見えるところまで、要素の親コンテナーをスクロールします。
以下のように記述すると、要素を見えるところまで持ってきてくれるメソッドです。
element.scrollIntoView();
引数にboolean値を渡すことで表示要素を表示領域の上端/下端のどちらに来るようにするかを設定できます。
規定値はtrueです。
- true の場合、要素の上端がスクロール可能な祖先の表示範囲の上端に来るようにスクロールします。
- false の場合、要素の下端がスクロール可能祖先の表示範囲の下端に来るようにスクロールします。
スライダー実装に使う際の注意点
スライダーを作成する場合は、表示させたいスライドに対して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-neededとsmooth-scroll-into-view-if-needed。
scroll-into-view-if-neededとは
まだ標準化されていないscrollIntoViewIfNeeded
のPonyfill1のnpmパッケージです。
scrollIntoViewIfNeeded
は、表示したい要素が表示領域にない場合だけスクロールするという仕様のもので、要素を表示領域に持ってきてくれる、という点は基本的にscrollIntoView
と同じです。
このパッケージを使えば、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.
実にスムースですね。(※個人の感想です)
まとめ
- スライダー実装には
scrollIntoView
が便利 - どのブラウザでも
scrollIntoViewOptions
を使いたい場合はscroll-into-view-if-needed - どのブラウザでもスムーススクロールを有効にしたい場合はsmooth-scroll-into-view-if-needed
2020年ももう終わりですね。1年の思い出をスライダーにしてみてはいかがでしょうか。