O hirunewani blog

CSSカルーセルを試す

Created at

Chrome 135でサポートされたCSS Overflow Module Level 5によるCSSカルーセルの実装方法を紹介します。

CSS Overflow Module Level 5では、CSSのみでカルーセルを実装できる次の機能が定義されています。

  • Scroll Buttons:カルーセルのスクロール領域を85%スクロールさせるボタンを提供する。
  • Scroll Markers:特定のカルーセルのアイテムまでスクロールするアンカーを提供する。

Chrome 135では、これらの機能が他のブラウザに先行して実装されました。Chrome公式によるCSSカルーセルの解説記事も公開されています。この記事では、基本的な説明を多少は行いつつ、実装例をいくつか紹介します。

 

今までのCSSカルーセル

スクロールボタンやスクロールマーカーが存在しないカルーセルは、スライダーやスライドショーと呼ばれることが多いですが、次のようなカルーセルであれば以前からCSSのみで実装が出来ました。

このカルーセルは、スクロールバーまたはキーボードの矢印キーで操作することが出来ます。 また、中途半端な位置で止まらずに、ちょうど良い位置で止まるようになっています。 これは、比較的新しいscroll-snap-typescroll-snap-alignプロパティによるものです。

実装は、次のようになっています。

<ul class="carousel">
  <li class="item"><img src=""></li>
  <li class="item">...</li>
  ...
</ul>
.carousel {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 300px;
    gap: 8px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    > .item {
        scroll-snap-align: center;
    }
}

また内部リンクを利用することでJavaScriptを利用せずにスクロールマーカーを配置することも出来ました。

1 2 3 4 5

次のように実装できます。

<ul class="carousel">
  <li class="item" id="item-1"><img src=""></li>
  <li class="item" id="item-2">...</li>
  ...
</ul>
<div class="scroll-markers">
  <a href="#item-1">1</a>
  <a href="#item-2">2</a>
  ...
</div>

スクロールボタンを配置する

スクロールボタンは、::scroll-button()疑似要素に有効なcontentプロパティを指定することで配置できます。

::scroll-button()は、scroll-button(right)scroll-button(left)のように指定することで左右のボタンのスタイルや位置を調整することも出来ます。またrightleftの代わりにinline-startinline-endを指定することで、テキストの方向に応じてボタンの位置を調整することも可能です。

::scroll-button()によるスクロールボタンを押すとスクロール領域の85%をスクロールするため、デフォルトでは中途半端な位置でスクロールが止まります。

スクロールボタンを配置する実装は、次のようになります。

.carousel {
    &::scroll-button(inline-start){
        content: "⬅" / "Scroll left";
    }
    &::scroll-button(inline-end){
        content: "⮕" / "Scroll right";
    }
    &::scroll-button(*){
        inline-size: 48px;
        aspect-ratio: 1;
        cursor: pointer;
    }
}

100%のスクロールを行う

スクロールボタンを押すと、デフォルトではスクロール領域の85%をページングします。 ですがsroll-snap-typescroll-snap-alignを利用すれば、次のように100%のスクロールを実現することができます。

実装は次のようになります。

.carousel {
 scroll-snap-type: x mandatory;
    > .item {
        scroll-snap-align: start;
    }
}

ボタンの位置を調整する

現状::scroll-buttonは親要素によるレイアウトシステムが直接適用されないため、ボタンの配置には工夫が必要です。

配置方法としては次のような方法が考えられます。

  • Grid areaを利用する
  • カルーセル要素のさらに親要素にposition: relativeを指定してposition: absoluteなどでボタンを配置する
  • Anchor Positioningを利用する

Grid areaはやりたいことに対して記述量が多く、positionによる方法は余計な要素を追加しなければいけないため、個人的にはおすすめしません。一方、Anchor Positioningは理解さえすれば、シンプルな記述で縦横無尽にボタンを配置できるため、個人的にはおすすめです。サポートしている環境は少ないですが、CSS Overflow Module Level 5も同様なので問題ではないでしょう。

これは、Anchor Positioningを利用して次のように実装できます。

.carousel{
    anchor-name: --carousel;

    &::scroll-button(inline-start){
        content: "⬅" / "Scroll left";
        position-area: center span-end;
    }
    &::scroll-button(inline-end){
        content: "⮕" / "Scroll right";
        position-area: center span-start;
    }
    &::scroll-button(*){
        position: fixed;
        position-anchor: --carousel;
    }
}

スクロールマーカーを配置する

スクロールマーカーは、::scroll-marker-group疑似要素と::scroll-marker疑似要素に加えてscroll-marker-groupプロパティを指定することで配置できます。

次のように実装できます。

.carousel {
    scroll-marker-group: after;
    &::scroll-marker-group {
        display: grid;
        grid-auto-flow: column;
        justify-content: center;
        gap: 8px;
        margin-block-end: 48px;
    }
    > .item {
        &::scroll-marker {
            content: "";
            inline-size: 24px;
            aspect-ratio: 1;
            border: 1px solid #252525;
            border-radius: 1e3px;
        }
        &::scroll-marker:hover,
        &::scroll-marker:focus-visible {
            background-color: #555;
        }
        &::scroll-marker:target-current {
            background-color: #252525;
        }
    }
}

少し実装が複雑なので、各機能の軽く説明をしておきます。

  • scroll-marker-group:マーカーの親要素の配置位置を指定するためのプロパティです。値はnonebeforeafterの3つです。デフォルトがnoneのため、指定しないと何も表示されません。
  • ::scroll-marker-group:複数のマーカーの親要素です。主にマーカーの配置方法や余白を調整するために利用されるでしょう。縦方向にマーカーを配置するようなことも出来ます。
  • ::scroll-marker:個々のマーカー要素です。これはカルーセル要素ではなくカルーセルのアイテム要素に紐づいているため、例えばアイテム毎に見た目を変えたり表示させないといったことも出来ます。
  • :target-current:アンカー要素がアクティブである(現在表示されている)ことを表します。::scroll-makerと組み合わせることで現在表示されているスライドのマーカーを強調出来ます。この機能もCSS Overflow Module Level 5一部であり、Chrome 135でサポートされました。

マーカーに番号を入れる

マーカーに番号を入れるには、::scroll-markercontentプロパティに番号を入れるだけです。 counter関数を利用すれば、簡単に実装出来ます。

次のように実装できます。

.carousel {
    counter-reset: count;
    > .item {
        counter-increment: count;
        &::scroll-marker {
            content: counter(count);
        }        
    }
}

まとめ

ここまでに紹介したスクロールボタンとスクロールマーカーを組み合わせると、次のようなカルーセルを実装できます。

CSSのみで、ここまで多機能なカルーセルを実装できるのは革新的です。 ただし、現在はChrome 135以降しかサポートしておらず、実験的なフェーズであるため利用には注意が必要です。