とほほのCSSカルーセル入門

目次

CSSカルーセルとは

使用例

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 でサポートされました。(サポート状況(↗))

.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;
      }
    }
  }
}