CSSとJavaScriptでスワイプ操作にも対応した簡単なスライドを自作する
どんな記事に需要があるのかなぁ、とアクセス解析を眺めていたらJavaScriptを使ったスライドショーの自作記事へのアクセスが案外多くてちょっと驚いています。
でもあれは自動再生にしか対応していないので、手動操作できるスライダーが欲しい人もいるのではないか、とササっと軽くシンプルなスライダーを作ってみました。
また、今時はスマホ対応も必須なのでスワイプ操作にも対応します。
おおまかな仕様としてはこんな感じですかね。
- 画像や写真に限らず、文字などでもスライドできる
- スライドの左右10pxくらいに操作用の矢印を配置する
- スマホで開いた場合はスワイプでもスライドできるようにする
- スワイプした際、画像がスナップ(吸着)して真ん中に来るようにする
ほとんどCSSで実現できることなので、JavaScriptを使っているのは矢印クリックの部分だけです。
スライドの実行例
あれこれ書かれるより、まずはどんな動作なのか知りたいと思うので、早速動作サンプルです。
PCで開いている場合は画像の左右にある矢印をクリックすることでスライド操作が可能で、スマホの場合はスワイプでのスクロールも可能です。
PCでChromeをお使いの方なら[F12]キーでコンソールを開き、上にある[デバイスのツールバーを切り替えボタン]というアイコンをクリック。Edgeなら同じく[F12]から開発者ツールの[デバイス エミュレーションの切り替え]アイコンをクリックすることでスマホ操作のエミュレーションが出来ますので良ければお試しください。
HTML部分の実装
<div class="hscroll">
<ul>
<li><a href="sample (1).jpg"><img src="sample (1).jpg"></a></li>
<li><a href="sample (2).jpg"><img src="sample (2).jpg"></a></li>
<li><a href="sample (3).jpg"><img src="sample (3).jpg"></a></li>
<li><a href="sample (4).jpg"><img src="sample (4).jpg"></a></li>
<li><a href="sample (5).jpg"><img src="sample (5).jpg"></a></li>
</ul>
<span class="arrow left"></span>
<span class="arrow right"></span>
</div>
HTML部分はシンプルにUL/LIタグで画像(文字列でも可)をリストアップし、その上からスクロール用の枠であるDIVタグ(クラス名hscroll)をかぶせる形にしています。
左右に配置する矢印はSPANタグでarrow leftとarrow rightというクラス名を付けています。
CSS部分の実装
JavaScriptの操作はほんの数行なので、CSSがメインと言っても過言ではありません。
<style>
.hscroll {
width:200px;
height:200px;
position:relative;
border:1px solid lightgray;
}
.hscroll ul {
padding:0;
margin:0;
width:100%;
height:100%;
overflow:hidden;
white-space:nowrap;
scroll-snap-type:x mandatory;
scroll-behavior:smooth;
}
.hscroll img {
width:100%;
height:100%;
object-fit:contain;
}
.hscroll li {
list-style:none;
display:inline-block;
scroll-snap-align:center;
width:100%;
height:100%;
}
.arrow {
top:0;
position:absolute;
width:8%;
height:100%;
background:rgba(255,255,255,0.3);
cursor:pointer;
}
.arrow:before {
content:'';
position:absolute;
width:10px;
height:10px;
border-left:4px solid gray;
border-bottom:4px solid gray;
}
.left {
left:0px;
}
.left:before {
top:calc(50% - 10px);
left:calc(50% - 4px);
transform:rotate(45deg);
}
.right {
right:0;
}
.right:before {
top:calc(50% - 10px);
right:calc(50% - 6px);
transform:rotate(-135deg);
}
@media screen and (max-width:480px) {
.hscroll ul {
overflow-x:auto;
}
}
</style>
CSSの解説
.hscroll
スライドの枠であり、ここで指定された幅/高さの中に納まるように画像が表示されることになります。
スライド操作用の矢印はこの枠を基点として配置されるため、position:relativeも必須。
.hscroll ul
スライド枠内のULタグの部分。横スクロールになるように、white-space:nowrap;でLIタグが折り返さないようにして、枠からはみ出した部分はoverflow:hidden;で隠しています。
また、scroll-snap-type:x mandatory;で画像をスクロールしたときにスナップされるようになり、scroll-behavior:smooth;でスクロール自体が流れるようなスムーズなアニメーションになります。昔はJavaScriptで実装していた部分がCSSで実現できるのは楽ちんですね~。
.hscroll li
LIタグの部分はdisplay:inline-block;で横並びになるように調整しています。これはナビゲーションバーでもよく使われる書き方ですね。
また、scroll-snap-align:center;で画像の中央でスナップするようにも指定しています。
.arrow
矢印用は親となるDIVタグを基点に配置するため、position:absolute;を指定。横幅は全体の8%、高さは一杯に広がるように100%を指定。背景色は透明度に0.3を指定して後ろが透けて見えるようにしています。
.arrow:before
ここは矢印を描画するための疑似要素で、border-leftとborder-bottomでL字の線を描画しています。これを右45度に傾けると左矢印になり、左に135度(=-135度)傾けると右矢印になるというわけです。大きさの指定は相対的に指定するのが面倒くさかったので10px固定。
.left / .left before
先述したとおり、左矢印はL字を右45度に傾けて実現するため、transform:rotate(45deg);を指定しています。配置する座標は真ん中へんにしたかったのですが、50%の指定では矢印の大きさ分ちょっとだけズレるので、calcを使い微調整しています。
.right / .right before
左矢印と変わらないので説明は省略。右矢印を表現するために角度が違うだけです。
@media screen and (max-width:480px)
スマホで開かれたときだけ適用するスタイルを指定しています。
PCで開かれたときはoverflow:hiddenでスクロールバーを(ダサイので)隠したいのですが、スクロールバーがないとスマホではスワイプできません。よって、スマホのときだけはoverflow-x:auto;と指定することで、横スクロールバーを表示しています。
JavaScript部分の実装
<script>
document.querySelectorAll('.left').forEach(elm => {
elm.onclick = function () {
let ul = elm.parentNode.querySelector('ul');
ul.scrollLeft -= ul.clientWidth;
};
});
document.querySelectorAll('.right').forEach(elm => {
elm.onclick = function () {
let ul = elm.parentNode.querySelector('ul');
ul.scrollLeft += ul.clientWidth;
};
});
</script>
以前、「CSSとJavaScriptで横スクロールするお知らせ画面を作成する」でやった内容とほとんど同じで、スクロール量が違うだけです。
以前の記事では半分量だけスクロールして後はCSSに任せてるのです(ドヤァ)みたいな恥ずかしいことを言っていましたが、同じ長さをまんま加減算しても、アニメーションすることがわかったので、無駄な「÷2」の操作をなくしました。……………以前は要素の長さ分加算したら、アニメーションしないと思ってたんですよ…。やだ…恥ずかしい…。
まとめ
今回はJavaScriptによるスライドショー(自動再生)の記事が案外読まれているので、手動操作できるスライダーも需要あるんじゃないのかな?と思い、記事にしてみました。
たまにGoogle Search Consoleで検索語句をチェックしていると「JavaScript スライドショー」などで検索されていて、これはまぁ良いんですけども、それ以外に「JavaScript 画像 横スライド」とか「JavaScript 画像切り替え」とかで検索して当ブログにたどり着いた人は自動再生機能は求めてないと思ったんですよね。
簡単なわりには少し冗長な記事となってしまった気もしますが、この記事がどこかに存在する(かもしれない)駆け出しエンジニアさんのお役に立てば幸いです。