`calc-size()` や `interpolate-size: allow-keywords;` で `height: auto;` な要素のアニメーションをサポートする
CSS において height プロパティを 0 から auto に変化させた場合に、アニメーションが適用されないのはよく知られた問題です。この記事では calc-size() 関数を使って height: auto; な要素のアニメーションを実装する方法を紹介します。
calc-size()
は 2024 年 9 月 14 日時点で Chrome v129 で #enable-experimental-web-platform-features フラグを有効にすることで利用可能です。
CSS において height
プロパティを 0
から auto
に変化させた場合に、アニメーションが適用されないのはよく知られた問題です。アニメーションを適用するためには、具体的な値を指定する必要があるためです。そのため、JavaScript を使って要素の高さを計算してアニメーションを実装することが一般的でした。
このような問題を解決するために、calc-size()
関数が提案されました。この関数は calc()
とよく似ていますが、calc-size()
は auto
, min-content
, max-content
, fit-content
, stretch
, contain
などの値をサポートしていることが特徴です。calc-size()
関数はこのような値を具体的な値に変換して返すことができます。
アコーディオンの開閉をアニメーションする
実際に calc-size()
を使ってアコーディオンの開閉をアニメーションする例を見てみましょう。アコーディオンには HTML の details
要素を使います。
<details>
<summary>Like Pokémon</summary>
<div class="content">
<ul>
<li>Pikachu</li>
<li>Charmander</li>
<li>Bulbasaur</li>
</ul>
</div>
</details>
CSS では details
要素の中身が閉じているときに height: 0
にし、開いているときに height: auto
にして、高さが変化した際にアニメーションを適用します。details
要素の中身は CSS 擬似要素 ::details-content
で指定します。details
要素が開いているかどうかは、open
属性が付与されているかどうかで判定できます。
details::details-content {
display: block;
height: 0;
opacity: 0;
overflow: hidden;
transition: height 0.5s;
}
details[open]::details-content {
height: calc-size(auto, size);
opacity: 1;
overflow: auto;
}
details
が開いているときの height
には calc-size(auto, size)
を指定しています。これにより、height
が具体的な値に変換されるため、transition: height 0.5s
で設定したアニメーションが適用されます。calc-size()
関数の第 2 引数は第 1 引数のからの相対的な値を指定します。ここでは size
のみを指定しているので、auto
と同じ値です。calc-size(auto, size + 10px)
のように指定することで、auto
から 10px
大きくなる値を指定することもできます。
実際にアコーディオンの開閉時にアニメーションが適用されていることが確認できます。
interpolate-size: allow-keywords;
interpolate-size
プロパティは auto
, min-content
, max-content
といったキーワード値によるアニメーションを許可させるかどうかを指定するプロパティです。root
要素において interpolate-size: allow-keywords;
を指定することでキーワード値によるアニメーションを許可します。
:root {
interpolate-size: allow-keywords;
}
details::details-content {
display: block;
height: 0;
opacity: 0;
overflow: hidden;
transition: height 0.5s;
}
details[open]::details-content {
/* interpolate-size: allow-keywords; により calc-size が不要 */
height: auto;
opacity: 1;
overflow: auto;
}
このプロパティは Web の互換性を保つ目的で導入されました。デフォルトの値は numeric-only
であり、キーワード値によるアニメーションは許可されていません。そのため互換性が問題にならない場合には、:root
要素でページ全体にオプトインする使用方法が推奨されています。
まとめ
height: auto;
な要素のアニメーションを実装するためには、calc-size()
関数を使うことができるcalc-size()
関数を使うことで、auto
,min-content
,max-content
,fit-content
,stretch
,contain
などの値を具体的な値に変換して返すことができるcalc-size(auto, size)
はauto
と同じ値を返すcalc-size(auto, size + 10px)
のように指定することで、auto
から10px
大きくなる値を指定することもできるinterpolate-size: allow-keywords;
はキーワード値によるアニメーションを許可するプロパティである