とほほのCSSカルーセル入門
CSSカルーセルとは
- 英語の carousel は回転木馬、回転台などの意味を持ちます。
- 複数のスライドを横方向(または縦方向)にスクロールして切り替えていくものです。
- Slick.js や Swiper.js などの JavaScript ライブラリを用いるのが一般的でしたが、CSS の標準機能のみで実装できるようになってきました。
- 下記の関連仕様があります。
- scroll-snap-type : スクロールスナップする方向と強制タイプ
- scroll-snap-stop : スクロールスナップの1枚1枚の停止
- scroll-snap-align : スクロールスナップする位置
- ::scroll-button : スクロールボタン
- scroll-marker-group : スクロールマーカーグループの表示位置
- ::scroll-marker-group : スクロールマーカーグループ
- ::scroll-marker : スクロールマーカー
- scroll-target-group : スクロールターゲットグループ
使用例
2025年4月の Chrome 135 でサポートされたスクロールボタン(::scroll-button())、スクロールマーカー(::scroll-marker) を使用しています。Chrome 135 以降で確認してください。左右のスクロールボタンを押すとスライドが切り替わります。どのスライドが表示されているかを下部のスクロールマーカーが示します。マーカーをクリックするとそのスライドにジャンプします。
説明
HTMLの準備
まずは HTML で表示したい画像を並べます。
<div class="container">
<div class="carousel">
<img src="https://picsum.photos/id/1/600/300" alt="">
<img src="https://picsum.photos/id/2/600/300" alt="">
:
</div>
</div>
横スクロール
下記のスタイルで横方向にスクロールできるようにします。
.container {
--img-width: 600px; /* スライドの横幅 */
--img-height: 300px; /* スライドの高さ */
.carousel {
display: flex; /* スライドを横方向に並べる */
gap: 100px; /* スライド間に隙間をあける */
overflow-x: auto; /* はみ出した領域はスクロールする */
padding: 0 calc((100% - var(--img-width)) / 2); /* 左右にスライド横幅の半分程度のパディング */
background-color: #ddd; /* 背景色をつける */
img {
width: var(--img-width); /* スライドの横幅 */
height: var(--img-height); /* スライドの高さ */
}
}
}
@media (width < 720px) { /* 画面が狭い時はスライドを小さめに */
.container {
--img-width: 360px;
--img-height: 180px;
}
}
スクロールスナップ(scroll-snap-*)
scroll-snap-type, scroll-snap-stop, scroll-snap-align を用いて、スマホでスワイプスクロールする際にスライドを1スライドずつ、中央にスナップ(停止)させることができます。
.container {
.carousel {
scroll-snap-type: x mandatory; /* X方向に強制的にスナップする */
scroll-snap-stop: always; /* 1枚1枚スナップする */
img {
scroll-snap-align: center; /* コンテンツの中央位置でスナップする */
}
}
}
スクロールボタン(::scroll-button())
::scroll-button() はスクロールボタンを生成します。right, left は左右スクロールボタン、* はすべてのボタンを意味します。content: でボタンの中身を指定します。親要素(.container)に対する相対位置を指定しています。scroll-behavior でボタン押下時もスムーススクロールするようにしています。スクロールボタンを押すと、スクロール領域の 85% 分スクロールします。
2025年4月の Chrome 135 でサポートされました。(サポート状況)
.container {
position: relative; /* スクロールボタン配置用 */
.carousel {
scroll-behavior: smooth; /* ボタン押下時にスムーススクロールする */
&::scroll-button(*) { /* スクロールボタン */
position: absolute; /* カルーセルの親要素に対して */
top: calc(var(--img-height) / 2 - 10px); /* 画像高さの1/2のちょっと上に配置 */
width: 50px; /* ボタンの横幅 */
height: 50px; /* ボタンの高さ */
border-radius: 50%; /* 丸型ボタンにする */
border: none; /* ボーダーは不要 */
background-color: #ddd8; /* 背景色をすこし透明で設定 */
}
&::scroll-button(*):hover {
background-color: #ddd9; /* マウスを乗せると少し透明度を変える */
}
&::scroll-button(right) { /* 右ボタン */
right: 20px; /* 右端から少し内側に配置 */
content: "\21E8"; /* 右矢印(U+21E8) */
}
&::scroll-button(left) { /* 左ボタン */
left: 20px; /* 左端から少し内側に配置 */
content: "\21E6"; /* 左矢印(U+21E6) */
}
}
}
スクロールマーカー(scroll-marker-group, ::scroll-marker-group, ::scroll-marker)
::scroll-marker-group 疑似要素はスクロールマーカーグループを、::scroll-marker 疑似要素は個々のスクロールマーカーを生成します。各スライドの目次のようなものです。scroll-marker-group プロパティはその位置を指定します。
2025年4月の Chrome 135 でサポートされました。(サポート状況)
2025年11月の Chrome 142 で :target-before と :target-after がサポートされました。(サポート状況)
.container {
margin-bottom: 40px; /* マーカー分下部に余白をつける */
.carousel {
scroll-marker-group: after; /* マーカーを下部に表示する */
&::scroll-marker-group { /* マーカーグループ */
margin-top: 10px;
display: flex;
justify-content: center;
gap: 10px;
}
img {
&::scroll-marker { /* 個々のマーカーアイテム */
content: "";
width: 20px;
height: 10px;
border: 1px solid #ccc;
}
&::scroll-marker:target-current { /* 表示中のマーカー */
background-color: #666;
}
&::scroll-marker:target-before,
&::scroll-marker:target-after { /* 前後のマーカー */
background-color: #eee;
}
}
}
}
スクロールターゲットグループ(scroll-target-group)
2025年9月の Chrome 140 では scroll-target-group がサポートされ、::scroll-marker-group 疑似要素ではなく通常の要素をスクロールマーカーグループとして利用することが可能となりました。詳細は scroll-target-group を参照してください。
リンク
- https://drafts.csswg.org/css-overflow-5/
- https://developer.chrome.com/blog/carousels-with-css?hl=ja
- https://chrome.dev/carousel/