ついにCSSだけでwidth: auto;やheight: auto;へのアニメーションができるようになります

CSSだけでwidth: auto;height: auto;にアニメーションできたらいいな、と思ったことはありませんか?
たとえば、下記のようにテキストの量によってサイズが異なるボタンです。

これまではCSSでアニメーションするときは、固定値(width: 100px;しかアニメーションが機能しませんでしたが、Chrome 129でサポートされたinterpolate-sizeプロパティやcalc-size()関数を使用すると、簡単にwidth: auto;へのアニメーションが実装できます。

CSSだけでwidth: auto;やheight: auto;へのアニメーションができるようになります

Animate to height: auto; in CSS
by Bramus!

下記は各ポイントを意訳したものです。
※元サイト様のライセンスに基づいて翻訳しています。基づいてというのは、貢献部分に関して同ライセンスも含みます。

はじめに

CSS Dayのカンファレンスで参加者からリクエストが多かったCSSの機能の一つが、height: auto;のアニメーション機能です。もちろん、バリエーションとしてwidth: auto;のアニメーション、そしてmin-content, max-content, fit-contentなどのキーワードで表される固有サイズのどれかにアニメーションさせることも挙げられます。

どういうことかというと、たとえば下記のデモで、アイコンをホバーしたときにラベルがスムーズに自然な幅(auto)にアニメーションできるようになると嬉しいというものです。
これまでだと、下記のデモのようにアニメーションが機能しません。

See the Pen
Growing buttons on hover (before)
by coliss (@coliss)
on CodePen.

上記のデモのCSSには、下記のようにアニメーションするように記述されています。

上記のデモではwidthプロパティをトランジションさせるようにtransitionを設定し、:hoverwidth: max-content;が設定されているにもかかわらず、スムーズなアニメーションは行われません。ホバーすると、急激に設定した幅に変化するだけです。

autoなどのキーワードをアニメーションさせる方法

CSSのinterpolate-sizeプロパティを使用すると、CSS固有のサイズ設定キーワードでアニメーションやトランジションを許可するかどうかを設定できます。使い方は簡単で、下記を使用するWebページに追加するだけです。

上記のデモにこのCSSを追加したデモが下記です。
これでwidth: auto;へのアニメーション、そしてwidth: auto;からのアニメーションが正常に動作します。
※2024年10月現在、Chrome 129+のみにサポートされています。

See the Pen
Growing buttons with interpolate-size: allow-keywords
by coliss (@coliss)
on CodePen.

interpolate-sizeプロパティのデフォルト値はnumeric-onlyで、数値のみです。値をallow-keywordsに設定すると、キーワードでアニメーションできるようになります。

interpolate-sizeプロパティのサポートブラウザは、下記の通りです。

interpolate-sizeプロパティのサポートブラウザ

interpolate-sizeプロパティのサポートブラウザ

Chrome 129でサポートされているキーワードは、auto, min-content, max-content, fit-contentです。将来サポートされる可能性があるキーワードには、stretch, containがあります。

セレクタで範囲を制限する

上記ではinterpolate-sizeプロパティを:rootにしてドキュメント全体に設定しましたが、一部だけに制限することもできます。たとえば、header要素がこのようなトランジションに対応していない場合、下記のようにmain要素とその子孫要素のみに制限できます。

デフォルトでキーワードのアニメーション化を許可しないのはなぜですか?

このメカニズムに関する一般的なフィードバックは、ブラウザはデフォルトで固有サイズのキーワードのトランジションやアニメーションを許可すべきだというものです。

この動作を有効にするオプションは、この機能の開発中に調査されました。ワーキンググループは、多くのスタイルシートが固有サイズのキーワード(autoなど)はアニメーションできないと想定しているため、デフォルトでこれを有効にすることは後方互換性がないことを突き止めました。詳細は、CSS Working Group issueをご覧ください。

したがって、このinterpolate-sizeプロパティはオプトインです。継承特性のおかげで、ドキュメント全体をオプトインするには前述のように:rootinterpolate-size: allow-sizes;を設定するだけです。

calc-size()でキーワードをアニメーションさせる方法

CSS固有のサイズ設定キーワードでアニメーションさせるもう一つの方法は、calc-size()関数を使用することです。この関数を使用することで、安全かつ明確に定義された方法で固有のサイズ設定キーワードに対して計算を実行できます。

上記のデモにこのCSSを追加したデモが下記です。
これでwidth: auto;へのアニメーション、そしてwidth: auto;からのアニメーションが正常に動作します。
※2024年10月現在、Chrome 129+のみにサポートされています。

See the Pen
Growing buttons with calc-size()
by coliss (@coliss)
on CodePen.

この関数は、次の2つの引数を順番に受け入れます。

  • calc-size basis: <intrinsic-size-keyword>にすることもネストされたcalc-size()にすることもできます。
  • calc-size calculation:calc-size basisを用いて計算を実行します。calc-size basisを参照するにはsizeキーワードを使用します。

calc-size()のサポートブラウザは、下記の通りです。

calc-size()のサポートブラウザ

calc-size()のサポートブラウザ

視覚的には、interpolate-sizeプロパティを使用した場合とまったく同じです。しかし、特定のケースではinterpolate-sizeプロパティを使用する必要があります。

calc-size()が優れているのは計算を実行できることです。これはinterpolate-sizeプロパティでは実行できません。

たとえば、ページ上のすべての段落のサイズを50pxの倍数にもっとも近い値にしたい場合は、次のようにします。

実際の動作は、デモページでご覧ください。

See the Pen
grid-size paragraphs thanks to calc-size()
by coliss (@coliss)
on CodePen.

calc-size()関数でできることは、2つのcalc-size()のcalc-size basisが同じ場合に、それらの間を補間することです。これもinterpolate-sizeプロパティでは実現できません。

どちらを使えばよいのか?

ほとんどの場合、:rootinterpolate-sizeプロパティを使用します。これは基本的に1行で済むため、キーワードでアニメーションさせるときにもっとも簡単な方法です。

このCSSはサポートしていないブラウザではトランジションしないようにフォールバックするので、優れたプログレッシブエンハンスメントにもなります。

計算の実行などより細かい制御が必要な場合は、calc-size()を使用します。また、calc-size()にしかできない動作をしようしたい場合も同様です。

ただし、コード内でcalc-size()を使用すると、calc-size()をサポートしてないブラウザのためにフォールバックを含める必要があります。たとえば、数値によるサイズ宣言を追加したり、@supportsで機能検出にフォールバックします。

キーワードをアニメーションさせるデモ

:rootinterpolate-size: allow-keywords;を設定したデモを見てましょう。

details要素を使用した開示ウィジェットや排他的アコーディオンを開くときにアニメーションさせます。これにinterpolate-size: allow-keywords;を使用すると、かなり多くのことが可能になります。

実際に動作は、デモページでご覧ください。

See the Pen
Styling <details>: Material UI Accordion (interpolate-size version, no ::details-content)
by coliss (@coliss)
on CodePen.

通常はウィジェットが開くときのアニメーションは、一方向にしか実行されませんが、interpolate-size: allow-keywords;::details-contentを組み合わせると、両方向にアニメーションさせることができます。
::details-contentは今年後半にChromeに実装予定です。

サイトのキャプチャ

sponsors

top of page

©2024 coliss