名前付きタイムライン
scroll-timeline-name / view-timeline-name / timeline-scope。 離れた要素のスクロール / ビューに紐づける機能。
なぜ必要か
scroll(nearest) は最寄り、view() は自分自身。
「親 A のスクロールを子 B のアニメに使う」のような離れた紐付けには名前を介する必要がある。
scroll-timeline-name
スクロールコンテナに名前を付ける:
.scroller {
overflow: auto;
scroll-timeline-name: --my-scroll;
scroll-timeline-axis: block; /* y / x / inline / block */
}
.elsewhere {
animation: bar linear;
animation-timeline: --my-scroll;
}
scroll-timeline 短縮形
.scroller {
scroll-timeline: --my-scroll block;
}
view-timeline-name
.target {
view-timeline-name: --target-view;
view-timeline-axis: block;
view-timeline-inset: 100px 0;
}
.linked {
animation: react linear both;
animation-timeline: --target-view;
animation-range: entry 0% entry 100%;
}
timeline-scope
名前の探索範囲を制御。子孫だけでなく祖先からも名前を見えるようにできる:
body {
/* 子孫のどこかにある --my-timeline を body 配下全体で参照可能に */
timeline-scope: --my-timeline;
}
.scroller {
scroll-timeline-name: --my-timeline;
}
.fixed-bar {
/* fixed なので scroller の子孫ではないが参照できる */
animation: bar linear both;
animation-timeline: --my-timeline;
}
典型例 1: 別ペインの進捗バー
<header>
<div class="reading-bar"></div>
</header>
<main class="article">
...長文...
</main>
body { timeline-scope: --article; }
.article {
scroll-timeline: --article block;
/* この main 内にスクロールがある場合 */
}
.reading-bar {
animation: grow linear both;
animation-timeline: --article;
transform-origin: left;
transform: scaleX(0);
}
@keyframes grow { to { transform: scaleX(1); } }
ページ全体スクロールなら scroll(root) で済むが、
記事だけのスクロールに追従するならこれ。
典型例 2: スクロールと連動するナビ
main { scroll-timeline: --main block; }
.section1 {
view-timeline-name: --sec1;
}
.tab1 {
animation: highlight linear both;
animation-timeline: --sec1;
animation-range: contain 0% contain 100%;
}
@keyframes highlight {
to { background: #fff3; }
}
各セクションを view-timeline-name で名付け、対応するナビアイテムがそのセクション中だけハイライトされる。
名前と CSS 変数
- 名前は常に
--プレフィックス - CSS カスタムプロパティと同じ命名空間ではないが、視覚的に揃える
関連プロパティ一覧
| プロパティ | 用途 |
|---|---|
| scroll-timeline-name | スクロールタイムラインに名前 |
| scroll-timeline-axis | 軸(block / inline / x / y) |
| scroll-timeline | name + axis の短縮形 |
| view-timeline-name | view タイムラインに名前 |
| view-timeline-axis | 軸 |
| view-timeline-inset | 境界の内側オフセット |
| view-timeline | 短縮形 |
| timeline-scope | 名前の探索範囲 |
view-timeline-inset
ビューポート境界を内側に縮める:
.target {
view-timeline-name: --t;
view-timeline-inset: 100px 100px; /* 上下 100px ずつ縮める */
}
例: ヘッダーが固定で 80px 占めている場合、view-timeline-inset: 80px 0
にすると「ヘッダーで隠れる部分は無視」して進入扱いに。
scroll() vs view() vs 名前付き
| 用途 | 選択 |
|---|---|
| シンプル / 自要素 | scroll() / view() |
| 離れた要素同士の連動 | scroll-timeline-name / view-timeline-name |
| 祖先で参照 | timeline-scope |
動的に名前を切替
CSS 変数のように動的に切替えはできない(同じ要素が複数の名前を持つことは可)。 切替えたければ JS から CSS を書き換える。
失敗パターン
| 症状 | 対処 |
|---|---|
| 名前が見つからない | timeline-scope で見える範囲を広げる |
| 動かない | 名前付け要素が実際にスクロール / view 対象になっているか |
| 2 つ以上のスクロールに対応したい | 複数の scroll-timeline-name を持つ親を分ける |
典型レシピ
「サイドの目次が現在地をハイライト」
<aside class="toc">
<a href="#s1">セクション 1</a>
<a href="#s2">セクション 2</a>
<a href="#s3">セクション 3</a>
</aside>
<main>
<section id="s1">...</section>
<section id="s2">...</section>
<section id="s3">...</section>
</main>
body { timeline-scope: --s1, --s2, --s3; }
#s1 { view-timeline-name: --s1; }
#s2 { view-timeline-name: --s2; }
#s3 { view-timeline-name: --s3; }
.toc a:nth-child(1) { animation: hi linear both; animation-timeline: --s1; animation-range: contain 0% contain 100%; }
.toc a:nth-child(2) { animation: hi linear both; animation-timeline: --s2; animation-range: contain 0% contain 100%; }
.toc a:nth-child(3) { animation: hi linear both; animation-timeline: --s3; animation-range: contain 0% contain 100%; }
@keyframes hi { to { color: orange; font-weight: 700; } }
名前付きタイムラインを使うなら、共通の親(body や app ルート)に timeline-scope を入れて
全体で見えるようにすると組み立てが楽。