CSSだけでカルーセルを実装してみる
こんにちは!アルダグラムでエンジニアをしている柴田です。
はじめに
最近はCSSの進化が著しく、JavaScriptを使わずともCSSで高度なUIコンポーネントを実装できるようになってきました。特にカルーセルのようなUIもCSSだけで実現できることを知り、最新技術をキャッチアップしておきたいと感じました。
そこで今回は、CSSのscroll-snap
プロパティを活用して、3種類のカルーセルを実装する方法をご紹介します。
scroll-snap
プロパティの紹介
scroll-snap
プロパティとは、スクロール時に要素を特定の位置でピタリと止めることができるCSSの機能です。これにより、ユーザーはスムーズかつ直感的にコンテンツを閲覧できます。
主なプロパティ
-
scroll-snap-type:
- 要素がスクロールスナップコンテナかどうか、どの程度厳密にスナップするか、どの軸を考慮するかなどを定義するプロパティです。
スクロールコンテナに対してスナップスクロールの軸と挙動を指定します。 -
軸の指定:
x
(水平方向)、y
(垂直方向)、block
、inline
- 水平方向にスナップを効かせたい時は
x
を指定します - 垂直方向にスナップを効かせたい時は
y
を指定します
- 水平方向にスナップを効かせたい時は
-
挙動の指定:
-
mandatory
: スナップポイントに必ず停止 -
proximity
: ユーザーのスクロール速度に応じてスナップ
-
- 要素がスクロールスナップコンテナかどうか、どの程度厳密にスナップするか、どの軸を考慮するかなどを定義するプロパティです。
-
scroll-snap-align: 子要素がスクロール領域内でどの位置にスナップするかを指定します。
-
値:
-
start
: コンテナの開始位置に合わせてスナップ -
center
: コンテナの中央の位置に合わせてスナップ -
end
: コンテナの終わり位置に合わせてスナップ
-
-
値:
-
scroll-snap-stop: スナップ位置でのスクロール停止を強制するかを設定します。
-
値:
-
normal
:スナップ位置で停止しない (デフォルト) -
always
: ユーザーが素早くスクロールしても必ずスナップ位置で停止
-
-
値:
CSSだけでカルーセルを実装する
では、実際にCSSだけでカルーセルを実装してみましょう。
以下、3パターンを実装します。
- 横方向
- 縦方向
- 縦横方向
まずは、カルーセルの共通となるHTML構造を定義します。共通のHTMLを使って、CSSの変更だけで縦方向、横方向、縦・横両方向のカルーセルを実装します。
-
.carousel
がカルーセル全体のコンテナです。 -
.carousel-item
が各カルーセルのアイテムです。
<div class="carousel">
<div class="carousel-item item1">Item 1</div>
<div class="carousel-item item2">Item 2</div>
<div class="carousel-item item3">Item 3</div>
<div class="carousel-item item4">Item 4</div>
<div class="carousel-item item5">Item 5</div>
<div class="carousel-item item6">Item 6</div>
</div>
縦方向
縦方向にスクロールするカルーセルを実装します。
ポイントとしては、
-
.carousel
にoverflow-y: auto
とscroll-snap-type: y mandatory
を指定します。これで、縦方向のスナップスクロールを有効化します。 -
scroll-snap-align: start
で、スクロール時にアイテムが開始位置でスナップします。(今回は分かりやすいように、startを採用します。)
.carousel {
display: grid;
overflow-y: auto;
scroll-snap-type: y mandatory;
scroll-behavior: smooth;
/* その他のスタイル */
}
.carousel-item {
scroll-snap-align: start;
flex: none;
display: flex;
align-items: center;
justify-content: center;
/* その他のスタイル */
}
縦方向へのスムーズなスクロールを実現できました。これでより直感的な操作感が得られます。
横方向
横方向にスクロールするカルーセルを実装します。
ポイントとしては、
-
.carousel
にdisplay: flex
とoverflow-x: auto
を設定します。これにより、水平方向にスクロール可能にします。 -
scroll-snap-type: x mandatory
で、水平方向のスナップスクロールを有効化します。 -
scroll-snap-align: start
で、スクロール時にアイテムが開始位置でスナップになるように設定します。
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
/* その他のスタイル */
}
.carousel-item {
scroll-snap-align: start;
display: flex;
align-items: center;
justify-content: center;
flex: none;
/* その他のスタイル */
}
横方向も同様に、スクロールスナップも開始点をキーにスクロールできています。
縦横方向
縦方向・横方向の両方にスクロール可能なカルーセルを実装します。
ポイントとしては、
-
.carousel
にoverflow: auto
とscroll-snap-type: both mandatory
を指定し、縦横両方向のスナップスクロールを有効化します。
さらに、display: grid
を指定し、格子状にアイテムを配置します。 -
scroll-snap-align: start
で、スクロール時にアイテムが開始位置でスナップします。
.carousel {
width: 300px;
height: 300px;
overflow: auto;
scroll-snap-type: both mandatory;
scroll-behavior: smooth;
display: grid;
grid-template-columns: repeat(3, 300px);
grid-template-rows: repeat(
2,
300px
); /* アイテムが6つあるため、2行の設定 */
/* その他のスタイル */
}
.carousel-item {
width: 300px;
height: 300px;
scroll-snap-align: start;
display: flex;
align-items: center;
justify-content: center;
/* その他のスタイル */
}
縦横方向も同様に、スクロールスナップも開始点をキーにスクロールできています。
実装時のTips
スクロールスナップコンテナの厳密さを定義するには
スクロールスナップの厳密さは、scroll-snap-type
プロパティの挙動の指定で定義します。
-
mandatory: スナップポイントに必ずスナップします。ユーザーが速くスクロールしても、次のスナップポイントで止まります。
例:
.carousel { scroll-snap-type: x mandatory; /* 厳密にスナップする */ }
-
proximity: ユーザーのスクロール操作に応じて、スナップするかどうかをブラウザが判断します。近くにスナップポイントがあればスナップしますが、強制はされません。
例:
.carousel { scroll-snap-type: x proximity; /* ユーザーの操作を優先する */ }
スクロールした時に表示領域をピタッと移動するには
表示領域をピタッと移動させるためには、以下のポイントに注意します。
-
scroll-snap-align を適切に設定する: 子要素がスナップする位置を指定します。
start
、center
、end
から選択します。例:
.carousel-item { scroll-snap-align: start; }
-
アイテムのサイズを統一する: 各アイテムの幅や高さを統一することで、スナップが均等に働きます。
例:
.carousel-item { width: 100vw; height: 100vh; }
-
スムーズなスクロールを有効にする:
scroll-behavior: smooth;
を指定すると、スナップ時の移動がスムーズになります。例:
.carousel { scroll-behavior: smooth; }
スクロールバーの非表示したい場合
スクロールバーを非表示にしたい場合は、以下のCSSを使用します。
.carousel::-webkit-scrollbar {
display: none;
}
実装時の注意点
アクセシビリティの考慮
scroll-snap-stop: always;
を使用すると、ユーザーが意図しないスクロールを強制される場合があります。必要に応じて使用し、ユーザーがコンテンツを自由に操作できるように配慮しましょう。
参考
コンテンツのサイズ調整
カルーセル内のアイテムが異なるサイズの場合、レイアウトが崩れる可能性があります。flex: none;
やwidth
、height
を指定して、よしなに調整することをおすすめします。
最後に
今回は、CSSのscroll-snap
プロパティを活用して、3種類のカルーセルを実装する方法をご紹介しました。実装前は「CSSだけでカルーセルが実現できるのか」と半信半疑でしたが、実際に試してみるとその手軽さと効果に驚かされました。
今回触れなかった部分としては、さらなるカスタマイズ、アクセシビリティの深掘り、パフォーマンスの検証などがあります。これらについては今後学んでいき、より高品質なUIを提供できるようにしていきたいです!
ここまでご覧いただきありがとうございました!
参考情報
- MDN Web Docs - scroll-snap-type
- MDN Web Docs - scroll-snap-align
- MDN Web Docs - scroll-snap-stop
- CSSのscroll-snapの活用方法
もっとアルダグラムエンジニア組織を知りたい人、ぜひ下記の情報をチェックしてみてください!
株式会社アルダグラムのTech Blogです。 世界中のノンデスクワーク業界における現場の生産性アップを実現する現場DXサービス「KANNA」を開発しています。 採用情報はこちら: herp.careers/v1/aldagram0508/
Discussion