shiromi osashimi 7881-768x591

`calc-size()` や `interpolate-size: allow-keywords;` で `height: auto;` な要素のアニメーションをサポートする

CSS において height プロパティを 0 から auto に変化させた場合に、アニメーションが適用されないのはよく知られた問題です。この記事では calc-size() 関数を使って height: auto; な要素のアニメーションを実装する方法を紹介します。

Note

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; はキーワード値によるアニメーションを許可するプロパティである

参考

記事の理解度チェック

以下の問題に答えて、記事の理解を深めましょう。

details 要素の中身を対象とする疑似要素はどれか?

  • ::details-content

    正解!

  • ::content

    もう一度考えてみましょう

  • ::details

    もう一度考えてみましょう

  • ::summary

    もう一度考えてみましょう

interpolate-size プロパティでキーワード値によるアニメーションを許可するためにはどのような値を指定するか?

  • numeric-only

    もう一度考えてみましょう

  • allow-keywords

    正解!

  • allow-all

    もう一度考えてみましょう

  • allow-interpolation

    もう一度考えてみましょう


Contributors

> GitHub で修正を提案する
この記事をシェアする
はてなブックマークに追加

関連記事