スクロールの状態変化でスタイル切替が可能に! CSSコンテナークエリーのscroll-state()入門

52

@container scroll-state()は、CSSコンテナークエリーの一種です。従来はJavaScriptを使って実装していた、「スクロールされたらヘッダーのスタイルを切り替える」等のインタラクションをCSSだけで実装できるようになります。

本記事では、scroll-state()の使い方とできることを作例で紹介します。

コンテナークエリーは、記事『要素の幅でレスポンシブ対応を行える!コンテナークエリーの使い方』で紹介しています。コンテナー幅でのレイアウト制御にかかわらず、インタラクティブなUI構築にも役立ちます。コンテナークエリーの可能性の広さを感じ取っていただけたら嬉しいです。

本記事の作例は、Chrome・Edgeでご覧ください。

@container scroll-state()の使い方

このクエリーは、container-type: scroll-stateが指定された要素の子孫要素に対して利用できます。@container scroll-state()の丸かっこ内には、stuckscrollablesnappedscrolledを指定できます。それぞれを利用できる条件は以下の通りです。

  • stuck
    • position: stickyで要素が固定されている
  • scrollable
    • 上下左右いずれかの方向に要素をスクロールできる
  • snapped
    • scroll-snap-typeプロパティで要素がピタッと止まる
  • scrolled
    • 直近のスクロール方向を検知できる

コロン(:)のあとには、検知する端・方向・軸を指定します。

stuckの記述例

<div class="item-container">
  <div class="item"></div>
</div>
.item-container {
  container-type: scroll-state;
  position: sticky;
  top: 0;
  left: 0;
}

.item {
  @container scroll-state(stuck: top) {
    /* .item-container が固定されたときのスタイルを記述する */
  }
}

次の章からは、stuckscrollablesnappedscrolledのそれぞれで、どのようなUI構築ができるか紹介します。

stuck: 要素が固定された瞬間を検知する

@container scroll-state(stuck: top)を指定すると、position: stickyで画面上部へ固定された瞬間にスタイルを適用できます。次の作例では、画面の最上部にいるかどうかで、ヘッダーの背景色を切り替えています。画面の最上部から少しでもスクロールすると、背景色が白に変わります。

固定したら要素を追加表示する

次の作例では、画面上部にボタンが到達した瞬間に、ボタンの横幅を広げています。

※この作例は、キーボードでの操作やスクリーンリーダーでの読み上げはうまく動かない可能性があります。

固定が終わったらスタイルを適用する

@container scroll-state(stuck: bottom)not条件(@container not scroll-state(stuck: bottom))を利用することで、position: stickyの固定が終了した瞬間にスタイルを適用できます。次の作例では、「セクション01」に配置したボタンを画面下部に固定表示し、スクロールで通過したらボタンにスタイルを追加します。

scrollable: スクロールできることを検知する

@container scroll-state(scrollable: top)を指定すると、要素が上方向へスクロールできるときにスタイルを適用できます。次の作例は、上方向へスクロールできるとき、画面上部に補助メッセージを追加表示しています。

snapped: 要素がピタッと止まることを検知する

@container scroll-state(snapped: y)を指定すると、scroll-snap-typeを指定したスクロールコンテナー内で、対象要素がy軸方向にスナップされている、またはスナップされようとしているときにスタイルを適用できます。次の作例では、要素を少し拡大して強調表示しています。

カルーセルUIに適用する

次の作例は、記事『JavaScript不要! HTMLとCSSでつくるカルーセルUI』で紹介したカルーセルUIに適用したものです。「▶」ボタンのクリック時に写真が水平方向にスライドしますが、スライド中だけサイズが縮小するような効果を与えています。snappedの値には、インライン方向を示すinlineを指定しています。

▼追加したCSSを抜粋

.item {
  container-type: scroll-state;
  img {
    transition: scale 0.3s;
    transition-delay: 0.2s;

    @container not scroll-state(snapped: inline) {
      scale: 0.85;
      transition-delay: 0s;
    }
  }
}

scrolled: 直近のスクロール方向を検知する

@container scroll-state(scrolled: bottom)を指定すると、コンテナーが直近で下方向へスクロールされたときにスタイルを適用できます。topを指定すると、直近の上方向へのスクロールを検知できます。

たとえば、下スクロール時だけヘッダーを隠し、上スクロール時だけ表示するには次のように記述します。

html {
  container-type: scroll-state;
}

.site-header {
  position: sticky;
  top: 0;
  translate: 0 0;
  transition: translate 0.3s;
}

@container scroll-state(scrolled: bottom) {
  .site-header {
    translate: 0 -100%;
  }
}

@container scroll-state(scrolled: top) {
  .site-header {
    translate: 0 0;
  }
}

対応ブラウザー

scroll-state()は、stuckscrollablesnappedがChrome 133・Edge 133(2025年2月)以上で利用できます。scrolledはChrome 144・Edge 144(2026年1月)以上で利用できます。

参照:Can I use…

まとめ

@container scroll-state()でできることを紹介しました。これまでJavaScriptでしか実現できなかった「スクロールの状態に応じたスタイル変更」をCSSだけで実装できます。

まだ対応ブラウザーが限られていますが、多くの場面で活用できる機能です。CSSでシンプルな演出を追加したいときに、ぜひ活用してみてください。

SNSでシェアしよう
シェアいただくと、サイト運営の励みになります!
Xへポスト
はてなブックマークへ投稿
共有
URLをコピー