ブラウザを上下に移動する縦スクロールは、普通だけれど、横スクロールはどうすれはいいか?
とても簡単でコンテナ(スクロールさせたい部分)に overflow-x: hidden
というCSSを入れれば簡単にできる。
See the Pen Horizontai scroll by Mayo Tobita (@mayognaise) on CodePen.
携帯やタブレット、デスクトップのトラックパッド、もしくは横スクロール対応のマウスであればこれは完璧に動きます。
しかし、デスクトップでトラックパッドがない場合や横スクロールが対応していないマウスの場合はどうすれば良いでしょうか。
キーボードの場合、アクセシビリティ用に、コンテナに tabindex="0"
を加えてください。キーボードのタブキーでコンテナをフォーカスした後、左右のキーボードで移動することができます。
マウスの場合、下についているスクロールバーをドラッグして移動させる方法がひとつありますが、多少やりずらいし、携帯のようにスクリーンをスワイプして移動させたいですよね。
残念ながら現在のところはJavascriptを使用しないといけないのです。
いろいろなJSライブラリがありますが、自分でできるだけ簡単に作ってみたい!
ということで、極力コードを少なくして作ってみました!
See the Pen Horizontal scroll with keyboard and mouse gesture including accessibility support by Mayo Tobita (@mayognaise) on CodePen.
まずは、左右のボタンから。仕組みは簡単で、ボタンを押したら、
右の場合はコンテナの幅分を増やして、左の場合はコンテナの幅分を減らしてスクロールさせる
const container = document.body.querySelector(".container");
const { width } = container.getBoundingClientRect();
// 右
container.scrollLeft += width;
// 左
container.scrollLeft -= width;
たったこれだけです。
ここでどうやってスムーズにスクロールしているのか?コンテナに scroll-behavior: smooth
を入れるだけです。そうすると、スムーズに移動してくれます。
アクセシビリティ用に、ユーザーが過度なアニメーションを望まない設定をしている場合は、この設定を無効にするのを忘れないでください。
.container {
overflow-x: auto;
scroll-behavior: smooth;
}
@media (prefers-reduced-motion) {
.container {
scroll-behavior: auto;
}
}
さて、次にスワイプの設定です。マウスイベントには、movementX
という、前回からの x
の値からの差分を教えてくれる便利なプロパティがあります。それを使って、スクロールさせるだけです。
const container = document.body.querySelector(".container");
container.addEventListener("mousemove", (event) => {
container.scrollLeft -= event.movementX * 10
});
実際のコードは、コンテナ内でマウスダウンをしたときや、マウスを離したり等の設定をつける必要があります。
最終的なものはこれです。
const container = document.body.querySelector(".container");
let flag = false;
container.addEventListener("mousedown", () => (flag = true));
container.addEventListener("mouseup", () => (flag = false));
container.addEventListener("mouseleave", () => (flag = false));
container.addEventListener("mousemove", (event) => {
flag && (container.scrollLeft -= event.movementX * 10);
});
container.addEventListener("wheel", (event) => {
event.preventDefault();
container.scrollLeft += (event.deltaX + event.deltaY) * 5;
});
もちろん、コードをもっと書けば、もっとなめらかに動くよう設定できますが、これが一番コードが少なくて、スワイプを実現しているのではないでしょうか。
もちろん、もっと簡単にできるなら、是非教えてください!
読んでいただいてありがとうございました。
【追加修正】
@akebi_mhからマウスホイールを使っての修正をいただきましたのでコードを変更しました!
container.addEventListener("wheel", (event) => {
event.preventDefault();
container.scrollLeft += (event.deltaX + event.deltaY) * 5;
});
あと、scrollLeft
はread-onlyではないので、scrollTo
を使わずに直接設定しました!
const x = 10;
// container.scrollTo(container.scrollLeft + x, 0);
container.scrollLeft += x;
@akebi_mhさんありがとうございます!!!