CSS scroll-state()

コンテナクエリに似ていますが、停止したクエリ、スナップされたクエリ、オーバーフローしたクエリに使用します。

公開日: 2025 年 1 月 15 日

Chrome 133 では、コンテナクエリを拡張して、スクロール状態のコンテナクエリを導入しています。固定位置、スクロール スナップポイント、スクロール可能な要素のブラウザ管理状態を CSS からクエリして適応できるようになりました。

概要

スクロール状態のクエリが導入される前は、JavaScript を使用して要素が固定されているか、スナップされているか、スクロール可能かを把握する必要がありました。標準トラックで、この情報を把握して適切に適応する、よりパフォーマンスの高い方法が提案されています。また、アニメーションをトリガーする新しい方法も追加され、CSS からスクロール トリガー アニメーションを解放できるようになりました。

Chrome 133 以降で利用できる状態クエリの概要は次のとおりです。

停止状態:
要素が端に固定されたときにスタイルの変更をトリガーします。
スナップされた状態:
要素が軸にスナップされたときにスタイルの変更をトリガーします。
スクロール可能な状態:
要素がオーバーフローしているときにスタイルの変更をトリガーします。

コンテナクエリで学んだことはすべて、スクロール状態クエリの操作に役立ちます。

また、スクロール駆動アニメーションとスクロール状態コンテナ クエリの間には未知の領域もあります。スクロール駆動アニメーションとスクロールによってトリガーされるスクロール状態アニメーションのどちらが最適かを判断するには、タイミングとコンテキストをテストする必要があります。次の動画とデモは、スティッキー トリガー アニメーションとスクロール駆動アニメーションの比較を示しています。

(左)scroll-state() によってトリガーされるアニメーション、(右)スクロール駆動アニメーション
https://codepen.io/web-dot-dev/pen/emOrBaV

最初のスクロール状態クエリ

最初のステップは、container-type プロパティに新しい値を使用してコンテナを定義することです。コンテナクエリと同様に、クエリ対象の要素には container-type を指定し、必要に応じて container-name も指定します。スクロール状態のクエリでは、スナップ、スタック、またはオーバーフローしている要素に container-type: scroll-state を指定します。

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;
}

2 つ目のステップは、状態に応答するコンテナの子を特定することです。コンテナ クエリと同様に、container-type が付加されている要素は選択できません。

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  > nav {
    @container scroll-state(stuck: top) {
      background: Highlight;
      color: HighlightText;
    }
  }
}

3 つ目のステップは、実際に試すことです。次の CSS の例では、.stuck-top 要素が 0 で上部に固定されたときに、背景を赤色にします。すでに記述している CSS に数行追加し、ブラウザの状態をプロキシする追加のコンテナ要素を追加することで、コンポーネントは周囲の状況をより賢く認識できるようになります。

https://codepen.io/web-dot-dev/pen/ByBxpwR

プログレッシブ エンハンスメント

@supports アットルールとネストを使用すると、コードを数行追加するだけで、段階的な拡張や条件付き機能の使用を追加できます。

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  @supports (container-type: scroll-state) {
    > nav {
      @container scroll-state(stuck: top) {
        background: Highlight;
        color: HighlightText;
      }
    }
  }
}

また、スクロール状態のクエリを使用してページ内の要素をアニメーション化する場合は、モーションの周囲に @media (prefers-reduced-motion: no-preference) {} を使用することも忘れないでください。

ユースケース

保留

このセクションは「難しい状況」という名前にすべきかもしれません。ここに、スティッキー状態のユースケースをいくつか紹介します。また、構築する必要があるアイデアについては、ボーナス セクションをご覧ください。

@container scroll-state(stuck: top) {}
@container scroll-state(stuck: bottom) {}

完全な構文リスト

スタックしたときにシャドウを追加する

固定されたクエリの最も一般的なユースケースの 1 つは、固定されたときに box-shadow を追加して、オーバーレイするコンテンツの上に浮かんでいるように表示するナビゲーション バーです。

https://codepen.io/web-dot-dev/pen/GgKdryj
.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  > nav {
    transition: box-shadow .3s ease;

    @container scroll-state(stuck: top) {
      box-shadow: var(--shadow-5);
    }
  }
}

現在のスタックしたヘッダーを有効にする

別の一般的なスティッキー UI フィードバック シナリオは、現在固定されている要素をハイライト表示することです。アルファベット順に並べられたバンドのリストでは、この機能が非常に役立ち、ユーザー エクスペリエンスをサポートします。

https://codepen.io/web-dot-dev/pen/pvzVRaK
.sticky-slide {
  dt {
    container-type: scroll-state;
    position: sticky;
    inset-block-start: 0;
    inset-inline: 0;

    > header {
      transition: 
        background .3s ease,
        box-shadow .5s ease;

      @container scroll-state(stuck: top) {
        background: hsl(265 100% 27%);
        box-shadow: 0 5px 5px #0003;
      }
    }
  }
}

ヘッダーがリストアイテムの横にある別のバリエーションもご覧ください。さまざまな用途にご利用いただけます。

https://codepen.io/web-dot-dev/pen/azoGpGg

アイデアのオーバーフロー

スクロール状態のクエリを使用して、デモに少しスパイスを加えたり、JavaScript を削除したりする際に役立つ、固定表示のデモのリストを示します。気に入ったものを 1 つ作成することをおすすめします。構文とアイデアを覚えるのに役立ちます 😏?。

スナップされました

スナップされた状態クエリを使用すると、JavaScript と スナップイベントの負担を軽減し、処理を CSS に移行できます。

@container scroll-state(snapped: x) {}
@container scroll-state(snapped: y) {}
@container scroll-state(snapped: inline) {}
@container scroll-state(snapped: block) {}

完全な構文リスト

最初のスクロール状態クエリのセクションをスキップした場合は、スナップクエリのコンテナは scroll-snap-align が付加された要素であり、適応できる要素はその要素の子要素である必要があることを思い出してください。つまり、この設定には次の 3 つの要素が必要です。

a scroll container with `scroll-snap-type`
⤷ a snap target with both `scroll-snap-align` and `container-type: scroll-state`
    ⤷ a child of the snap target that can query the container for snap state

スナップされたアイテムを視覚的に強調する

中央にスナップされたスクロールバーでは、中央にスナップされたアイテムをハイライト表示または目立たせることがよくあります。この例のお客様の声では、not キーワードが使用されているため、スナップされていないお客様の声はすべて不透明度が低く、スナップされたお客様の声は自然な表示状態になっています。

https://codepen.io/web-dot-dev/pen/NPKMdBX
.demo {
  overflow: auto hidden;
  scroll-snap-type: x mandatory;

  > article {
    container-type: scroll-state;
    scroll-snap-align: center;

    @supports (container-type: scroll-state) {
      > * {
        transition: opacity .5s ease;

        @container not scroll-state(snapped: x) {
          opacity: .25;
        }
      }
    }
  }
}

スナップされたアイテムのキャプションを表示する

これは、スクロール状態のクエリによってスクロール トリガー アニメーションを有効にする方法の良い例です。また、CSS で低モーションの尊重が有益な場合の良い例でもあります。

https://codepen.io/web-dot-dev/pen/XJrqpBG
.demo {
  overflow-x: auto;
  scroll-behavior-x: contain;
  scroll-snap-type: x mandatory;

  > .card {
    container-type: scroll-state;
    scroll-snap-align: center;

    @supports (container-type: scroll-state) {
      @media (prefers-reduced-motion: no-preference) {
        figcaption {
          transform: translateY(100%);

          @container scroll-state(snapped: x) {
            transform: translateY(0);
          }
        }
      }
    }
  }
}

スライド要素のアニメーション

講演の際にスライドショーやプレゼンテーションの要素をアニメーション化することは非常に一般的です。以前は、スライドにクラスを設定するだけのインターセクション オブザーバーを記述するのはかなり面倒でした。これで JavaScript は不要になりました。

https://codepen.io/web-dot-dev/pen/dPbeNqY
html {
  scroll-snap-type: y mandatory;
}

section {
  container-type: scroll-state;
  scroll-snap-align: start;
  scroll-snap-stop: always;

  @supports (container-type: scroll-state) {
    @media (prefers-reduced-motion: no-preference) {
      > h1 {
        transition: opacity .5s ease, transform .5s var(--ease-spring-3);
        transition-delay: .5s;
        opacity: 0;
        transform: scale(1.25);

        @container scroll-state(snapped: block) {
          opacity: 1;
          transform: scale(1);
        }
      }
    }
  }
}

スナップされた CSS 状態クエリはすべて、scrollsnapchange ではなく scrollsnapchanging のように動作します。これにより、スナップされた要素の視覚的なフィードバックをできるだけ早く提供できます。早すぎる場合は、JavaScript イベントを検討してください。

スクロール可能

スクロール可能な状態のクエリは、スクロール領域を実際にスクロールできる場合に視覚的なアフォーダンスを表示するのに非常に役立ちます。スクロール状態のクエリが導入されるまでは、この情報は把握するのが困難でした。

@container scroll-state(scrollable: top) {}
@container scroll-state(scrollable: right) {}
@container scroll-state(scrollable: bottom) {}
@container scroll-state(scrollable: left) {}

完全な構文リスト

スクロールを影で示す

background-attachment: local を使用してこのような効果を実現する Lea Verou による有名な CSS トリックや、スクロールドリブン アニメーションで実現する方法があります。それぞれの手法にはトレードオフがあります。これらの手法が最適なタイミングと場所を探すのは私たちの責任です。

次の例では、スクロールポート全体にまたがる 1 つのスティッキー要素を使用しています。上部と下部のグラデーションの不透明度は、コンテキスト スクロール状態のクエリ(@container scroll-state(scrollable: top))が適用されると、@property でアニメーション化されます。

また、これは size コンテナと scroll-state コンテナの両方である最初のコンテナです。

https://codepen.io/web-dot-dev/pen/OPLZWBj
.scroll-container {
  container-type: scroll-state size;
  overflow: auto;

  &::after {
    content: " ";

    background: var(--_shadow-top), var(--_shadow-bottom);
    transition: 
      --_scroll-shadow-color-1-opacity .5s ease,
      --_scroll-shadow-color-2-opacity .5s ease;

    @container scroll-state(scrollable: top) {
      --_scroll-shadow-color-1-opacity: var(--_shadow-color-opacity, 25%);
    }

    @container scroll-state(scrollable: bottom) {
      --_scroll-shadow-color-2-opacity: var(--_shadow-color-opacity, 25%);
    }
  }
}

矢印プロンプト

矢印を表示すると、ユーザーがスクロール可能な領域を認識しやすくなる場合があります。スクロールが可能な方向を指す傾向があり、不要になると消えます。次のコードで実行できます。

https://codepen.io/web-dot-dev/pen/OPLZWBj
@container scroll-state((scrollable: top) or (not (scrollable: bottom))) {
  translate: 0 calc(100% + 10px);
}

@container scroll-state((scrollable: top) and (not (scrollable: bottom))) {
  translate: 0 calc(100% + 10px);
  rotate: .5turn;
}

トップへ戻る

スクロール状態の操作としてよく使われるものに、「上へスクロール」の便利なボタンがあります。次のコードを使用すると、上にスクロールする場所がなくなったときに、一番上にスクロールするボタンが表示されなくなります。

このソリューションは少し逆転していますが、CSS の量を減らすことができます。ボタンの自然な位置はビュー内にあるため、スクロールする場所がなくなったときに非表示にするように指示する必要があります。

https://codepen.io/web-dot-dev/pen/OPLZWBj
@container not scroll-state(scrollable: top) {
  translate: 0 calc(100% + 10px);
}

継続的な調査

詳細については、仕様の詳細から、このトピックに関するその他の優れた記事まで、以下のリソースをご覧ください。