スクロール駆動アニメーション(animation-timeline: scroll() / view())が全主要ブラウザで使えるようになった
Firefox 159 の対応で、スクロール量や要素の見え具合にアニメーションを連動させる CSS が Baseline(新たに利用可能)になった。読了バーや表示時のフェードを JS なしで本番に入れやすくなった。
どんな時に使う?
- ページ上部の「どこまで読んだか」バー、要素が画面に入るにつれて浮かび上がる演出、ヘッダーの縮小など、これまで
scrollイベントや IntersectionObserver で書いていた動き。 - 「一度だけ再生」したい場合は animation-trigger でスクロールトリガーアニメーションを CSS だけで のほうが向く。こちらはスクロール量そのものに動きを結びつけたい時に使う。
コード
css
/* 1. 読了バー: ページ全体のスクロール量に連動 */
.progress {
position: fixed;
inset: 0 0 auto;
height: 4px;
background: currentColor;
transform-origin: left;
animation: grow linear both;
animation-timeline: scroll(root block);
}
@keyframes grow {
from { scale: 0 1; }
to { scale: 1 1; }
}
/* 2. 要素が画面に入るにつれてフェードイン */
.card {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
@keyframes reveal {
from { opacity: 0; translate: 0 2rem; }
to { opacity: 1; translate: 0 0; }
}scroll()はスクロールコンテナの位置(0〜100%)、view()は要素がスクロールポート内のどこに見えているかをタイムラインにする。animation-rangeで「画面に入り始め〜入りきるまで(entry)」のように区間を絞れる。animation-durationは時間ではなくスクロール量で決まるので指定不要(linearにしておくと指の動きと一致して自然)。- 名前付きタイムライン(
scroll-timeline/view-timelineとtimeline-scope)を使えば、別の要素のスクロールにも連動できる。応用例は ナビが溢れたら CSS だけでドロワーに切り替える(scroll-timeline で溢れ検知) を参照。
注意点
- 「Baseline 新たに利用可能」は最新版の主要ブラウザで揃ったという意味。古い Firefox などのユーザーが多いサイトでは
@supports (animation-timeline: view())で囲み、未対応時は最初から表示されている状態にしておく。 - 動きが苦手な人向けに
@media (prefers-reduced-motion: reduce)ではアニメーションを外す。 animationの一括指定はanimation-timelineをリセットするので、animation-timelineは必ずanimationより後に書く。