progress() でコンテナの幅を 0〜1 の数値にして、カードが広がるにつれキャプションをフェードインさせる
progress(100cqi, 300px, 500px) は「コンテナ幅が 300px のとき 0、500px のとき 1」になる数値を返すので、opacity などに直接入れるとメディアクエリの段階切り替えなしに連続的に変化させられる。
どんな時に使う?
- カードが狭いときは補足のキャプションを隠し、広くなるにつれて少しずつ見せたい時
@container (min-width: …)でパッと切り替えるのではなく、幅に応じてなめらかに見た目を変えたい時- 透明度だけでなく、拡大率・ぼかし・余白なども「幅に比例して」変えたい時
コード
css
.card {
container-type: inline-size; /* カード自身をサイズコンテナにする */
}
.caption {
/* コンテナ幅 300px で 0、400px で 0.5、500px で 1 */
opacity: progress(100cqi, 300px, 500px);
}progress(値, 始点, 終点)は「値が始点〜終点のどこにいるか」を 0〜1 の数値で返す CSS の数学関数。始点より小さければ 0、終点より大きければ 1 に張り付く(範囲外にはみ出さない)。100cqiは「一番近いサイズコンテナのインライン方向の幅の 100%」。container-type: inline-sizeを付けた.cardの幅がそのまま入る。- 返り値は単位のない数値なので、
opacityにはそのまま、長さに使うときはcalc()で単位を掛ける。
css
.caption {
--p: progress(100cqi, 300px, 500px);
opacity: var(--p);
translate: 0 calc((1 - var(--p)) * 8px); /* 広がるほど下から定位置へ */
filter: blur(calc((1 - var(--p)) * 4px));
}注意点・対応状況
progress()は比較的新しい関数で、Chrome / Edge は 138 以降で使える。Firefox・Safari の対応状況は導入前に caniuse などで確認し、未対応ブラウザ向けにopacity: 1;を先に書いておくと「常に表示」に落ちる。cqiなどのコンテナクエリ単位は、祖先にcontainer-typeを持つ要素が無いとビューポート基準(小さい方のsvi相当)として計算されてしまう。コンテナ指定を忘れないこと。- 透明度 0 のキャプションも、スクリーンリーダーには読まれ、クリックも受ける。完全に隠したい幅では
@containerでvisibility: hiddenを併用する。 - 元の投稿は動画のデモ付き。上の2つ目のコード(translate や blur の併用)は応用例として組み立てたもの。