scroll-state() CSS コンテナクエリを使用して sticky で張り付いたときに境界線を出す
scroll-state() はコンテナ要素のスクロール状態に応じてスタイルを変更することができるコンテナクエリです。例えば、スクロール中にヘッダーを sticky な場合の境界線を表示することが挙げられます。
scroll-state() は 2025 年 1 月現在 Chrome v133 以降のみでサポートされています。
scroll-state() はコンテナクエリの一種であり、コンテナ要素のスクロール状態に応じてスタイルを変更できます。
よくある使い方としては、スクロール中にヘッダーを sticky な場合の境界線を表示することが挙げられます。従来は要素が sticky によりスナップされているかどうかを JavaScript を使って判定する必要がありましたが、scroll-state() を使うことで CSS だけで実現できます。
スクロールがスタックされている状態
はじめに container-type プロパティを使ってコンテナを定義します。container-type の値には scroll-state を指定します。
.scroll-container {
position: sticky;
top: 0;
container-type: scroll-state;
}続いて @container アットルールを使い先ほど定義したコンテナの状態に応じてスタイルを変更するルールを定義します。scroll-state(stuck: top) はコンテナがスクロールにより上部にスタックされている状態を表します。このルールはコンテナ要素自身は選択できません。
@container scroll-state(stuck: top) {
.header {
border-bottom: 1px solid #e0e0e0;
}
}stuck の値には以下のいずれかを指定できます。
- none
- top
- right
- bottom
- left
- block-start
- inline-start
- block-end
- inline-end
それでは実際にスクロールがスタックされたときに境界線が表示されるか確認してみましょう。
スクロールがスナップされた状態
scroll-state(snapped: xxx) は CSS スクロールスナップ でスクロールがスナップした状態を表します。このクエリは scrollsnapchanging イベントの代替として使用できます。
snap の値には以下のいずれかを指定できます。
- none
- x:スクロールスナップが水平(
scroll-snap-type: x)の場合にスナップされた状態にマッチする - y:スクロールスナップが垂直(
scroll-snap-type: y)の場合にスナップされた状態にマッチする - block:スクロールスナップがブロック(
scroll-snap-type: block)の場合にスナップされた状態にマッチする - inline:スクロールスナップがインライン(
scroll-snap-type: inline)の場合にスナップされた状態にマッチする
例としてスナップされた要素のみを強調して表示するスタイルを定義してみましょう。
.snap-scroll-container {
/* 水平方向のスクロールスナップを有効にする */
scroll-snap-type: x mandatory;
}
.card {
/** スクロールが中央でスナップされる */
scroll-snap-align: center;
container-type: scroll-state;
}
.card > * {
transform: scale(0.9);
opacity: 0.5;
transition:
transform 0.5s,
opacity 0.5s;
}
@container scroll-state(snapped: x) {
.card > * {
transform: scale(1.2);
opacity: 1;
}
}スクロール可能な状態
scroll-state(scrollable: xxx) はスクロール領域が実際にスクロール可能な状態を表します。scrollable の値には以下のいずれかを指定できます。
- none
- top
- right
- bottom
- left
- block-start
- inline-start
- block-end
- inline-end
- x
- y
- block
- inline
scrollable を使う例として、トップへ戻るボタンの表示を切り替えてみましょう。トップへ戻るボタンは上方向にスクロール可能なときのみ表示されるようにしたいはずです。scrollable: top はスクロールが上方向に可能な状態を表します。
.scrollable-container {
container-type: scroll-state;
}
.top-button {
transform: translateY(100px);
transition: transform 0.3s;
position: fixed;
bottom: 20px;
right: 20px;
}
@container scroll-state(scrollable: top) {
.top-button {
transform: translateY(0);
}
}まとめ
scroll-state()はスクロール状態に応じてスタイルを変更するためのコンテナクエリです。scroll-state(stuck: xxx)はスクロールがスタックされた状態を表します。scroll-state(snapped: xxx)はスクロールがスナップされた状態を表します。scroll-state(scrollable: xxx)はスクロール領域が実際にスクロール可能な状態を表します。
