sibling-index() と sibling-count():CSS がついに自分が何番目かを知る
Firefox 154 がこの二つの関数を Baseline に押し上げた。兄弟の中での位置と兄弟の総数を返すので、時間差アニメーション、順序に応じた配色、均等割りまで CSS で計算でき、要素ごとのインライン変数が要らなくなる。
Firefox 154 が sibling-index() と sibling-count() に対応し、両関数は Baseline Newly available になりました。
やることは小さくありませんが、単純です。
sibling-index()は現在の要素の兄弟内での位置を返す(1 始まり)sibling-count()は親コンテナ内の兄弟 DOM 要素の総数を返す(要素自身を含む)
この二つの数は、以前は JavaScript からしか取れませんでした。
以前の書き方
「カードが順に現れる」演出の定番はこうでした。
<li style="--i: 0">…</li>
<li style="--i: 1">…</li>
<li style="--i: 2">…</li>
li {
animation-delay: calc(var(--i) * 60ms);
}
要素を足すたびに --i を手で書き、一つ漏らせば並び全体がずれます。テンプレート言語ならループ変数が要り、静的サイトならビルド成果物とソースの同期に気を使います。
インラインスタイルは消せます。
li {
animation-delay: calc((sibling-index() - 1) * 60ms);
}
1 始まりに注意。最初の要素に遅延を付けたくなければ 1 を引きます。忘れると最初の項目が 60ms 待ち、小さなつっかえとして見えます。
本当に役立つ三つの場面
時間差アニメーション
上記のとおり。要素を足してもスタイルシートに触らず、順序は DOM にそのまま従います。
順序に応じた配色
色相環に均等に並べる:
.swatch {
background: hsl(calc(sibling-index() * 360deg / sibling-count()) 70% 55%);
}
要素数が変われば配色は自動で計算し直されます。パレット変数を保守する必要はありません。
余った空間を均等に割る
sibling-count() は「いくつあるか分からない」を障害でなくします。
.bar {
width: calc(100% / sibling-count());
}
たいていは flex や grid のほうが適切です。この書き方が価値を持つのはflex が使えない場面 —— 絶対配置の子要素や、幅を明示的に計算したい場合です。
既存のセレクタとの違い
CSS には以前から :nth-child()、:first-child、:last-child がありました。違いはここです。
:nth-child(3)はセレクタ —— どの規則がどの要素に当たるかを決め、当たって初めてスタイルを変えられるsibling-index()は値 —— 数を返し、calc()に入り、hsl()に入り、animation-delayになる
前者は「三番目を赤くする」と言えます。後者は「N 番目の遅延は N × 60ms」と言えます。後者は以前、JavaScript かインライン変数が必要でした。
対応状況
| ブラウザ | バージョン |
|---|---|
| Chrome / Edge | 138 |
| Firefox | 154 |
| Safari | 26.2 |
三家とも到達したので Baseline Newly available です。つまり「使えるが古いブラウザでは退行する」。この二つの関数は見た目(遅延、配色、幅)にしか影響しないので、退行の結果は「全部同時に出る/同色/等幅」であり、レイアウトが壊れたりエラーになったりはしません。安心して漸進的強化として使える類です。
私の結論
多くの行数を節約するものではありません。消えるのは長らく慣習で維持されてきた結合の一種です。
「この要素が何番目か」は DOM の内在的な性質なのに、ビルドツールやテンプレート変数で外から注入しなければなりませんでした。注入とは同じ事実を二か所が知っているということで、二か所は必ずずれます。要素を足して --i を直し忘れるのが典型症状です。
今は数が DOM から直接読めます。真実は一つです。外部の取り決めを内部への問い合わせに変える変更は、節約した行数よりも、消したバグの原因のほうに価値があります。

コメント
…