interpolate-size
プロパティまたは calc-size()
関数を使用して、長さから組み込みサイズ設定キーワードへのスムーズな遷移とアニメーションを有効にします。
公開日: 2024 年 9 月 17 日
はじめに
よくリクエストされる CSS 機能として、height: auto
にアニメーション化する機能があります。リクエストの若干のバリエーションとして、height
ではなく width
プロパティを移行するか、min-content
、max-content
、fit-content
などのキーワードで表される他の固有のサイズのいずれかに移行することがあります。
たとえば、次のデモでは、アイコンにカーソルを合わせたときにラベルが自然な幅にスムーズにアニメーション化されるといいでしょう。
使用される CSS は次のとおりです。
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease; /* 👈 Transition the width */
&:hover,
&:focus-visible {
width: max-content; /* 👈 Doesn't work with transitions */
}
}
width
プロパティを移行するように transition
を宣言し、:hover
で width: auto
を宣言しても、スムーズな移行は行われません。代わりに、急激な変化が起こります。
interpolate-size
を使用して、組み込みサイズ設定キーワードとの間でアニメーション化する
CSS の interpolate-size
プロパティを使用すると、CSS 組み込みサイズ設定キーワードのアニメーションと遷移を許可するかどうかを制御できます。
デフォルト値は numeric-only
で、補間は有効になりません。このプロパティを allow-keywords
に設定すると、ブラウザがそれらのキーワードをアニメーション化できる場合に、長さから CSS 固有のサイズ設定キーワードへの補間が有効になります。
numeric-only
:<intrinsic-size-keyword>
は補間できません。allow-keywords
: 2 つの値を補間できます。一方が<intrinsic-size-keyword>
で、もう一方が<length-percentage>
の場合です。[…]
interpolate-size
プロパティは継承されるため、:root
で宣言して、ドキュメント全体で組み込みサイズ設定キーワードとの間で遷移を有効にできます。これはおすすめの方法です。
/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
次のデモでは、このルールがコードに追加されています。その結果、width: auto
との間のアニメーションは正常に動作します(サポートされているブラウザの場合)。
セレクタを絞り込んでオプトインのリーチを制限する
allow-keywords
オプトインをドキュメントのサブツリーに限定する場合は、セレクタを :root
からターゲットとする要素のみに調整します。たとえば、ページの <header>
がこのようなタイプの遷移に対応していない場合は、次のように <main>
要素とその子孫のみにオプトインを制限できます。
main { /* 👈 Scope the opt-in to only <main> and its descendants */
interpolate-size: allow-keywords;
}
キーワードのサイズ設定との間でアニメーションをデフォルトで許可しないのはなぜですか?
このオプトイン メカニズムに関してよく寄せられるフィードバックとして、ブラウザでは本来備わっているサイズ設定キーワードから長さへの遷移やアニメーションをデフォルトで許可するべきである、というものがあります。
この動作を有効にするオプションは、この機能の開発中に検討されました。ワーキング グループは、多くのスタイルシートが、組み込みサイズ設定キーワード(auto
や min-content
など)をアニメーション化できないことを前提としているため、これをデフォルトで有効にすると下位互換性が失われることを発見しました。詳しくは、関連する CSS ワーキング グループの問題に関するこちらのコメントをご覧ください。
そのため、このプロパティはオプトインです。継承特性により、ドキュメント全体を有効にするには、前述のように :root
で interpolate-size: allow-sizes
を宣言するだけです。
calc-size()
を使用して、組み込みサイズ設定キーワードとの間でアニメーション化する
固有のサイズ設定キーワードとの間で補間を有効にするもう一つの方法は、calc-size()
関数を使用することです。これにより、安全で明確に定義された方法で、組み込みサイズに対して数学演算を実行できます。
この関数は、次の 2 つの引数を順番に受け取ります。
- calc-size ベース。
<intrinsic-size-keyword>
でもネストされたcalc-size()
でもかまいません。 - calc-size 計算: calc-size ベースを使用して計算を行うことができます。計算サイズベースを参照するには、
size
キーワードを使用します。
次に例を示します。
width: calc-size(auto, size); // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered
元のデモに calc-size()
を追加すると、コードは次のようになります。
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease;
&:hover,
&:focus-visible {
width: calc-size(max-content, size); /* 👈 */
}
}
視覚的には、interpolate-size
を使用した場合とまったく同じ結果が得られます。したがって、この場合は interpolate-size
を使用する必要があります。
calc-size()
の強みは、計算を実行できることです。これは interpolate-size
ではできないことです。
width: calc-size(auto, size - 10px); // = The auto width minus 10 pixels
width: calc-size(min-content, size + 1rem); // = The min-content width plus 1rem
width: calc-size(max-content, size * .5); // = Half the max-content width
たとえば、ページ上のすべての段落のサイズを 50px
の最も近い倍数にするには、次のようにします。
p {
width: calc-size(fit-content, round(up, size, 50px));
height: calc-size(auto, round(up, size, 50px));
}
calc-size()
では、2 つの calc-size()
の計算サイズのベースが同じである場合に、2 つの calc-size()
の間で補間することもできます。これも interpolate-size
では実現できません。
#element {
width: min-content; /* 👈 */
transition: width 0.35s ease;
&:hover {
width: calc-size(min-content, size + 10px); /* 👈 */
}
}
calc()
で <intrinsic-size-keyword>
を許可しない理由
calc-size()
についてよく聞かれる質問は、CSS ワーキング グループが、組み込みサイズ設定キーワードをサポートするように calc()
関数を調整しなかった理由です。
その理由の一つは、計算時に組み込みサイズ設定キーワードを組み合わせて使用できないことです。たとえば、calc(max-content - min-content)
と記述すると有効なように見えますが、実際には有効ではありません。calc-size()
は、calc()
とは異なり、最初の引数として 1 つの <intrinsic-size-keyword>
のみを受け取るため、正確性を強制します。
コンテキスト認識もその理由の一つです。一部のレイアウト アルゴリズムには、特定の組み込みサイズ設定キーワードに対する特別な動作があります。calc-size()
は、<length>
ではなく、固有のサイズを表すように明示的に定義されています。これにより、これらのアルゴリズムは calc-size(<intrinsic-size-keyword>, …)
を <intrinsic-size-keyword>
として扱い、そのキーワードに対する特別な動作を維持できます。
どの方法を使用すればよいですか。
ほとんどの場合、:root
で interpolate-size: allow-keywords
を宣言します。基本的に 1 行で記述できるため、組み込みサイズ設定キーワードとの間でアニメーションを有効にする最も簡単な方法です。
/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
このコードは、サポートしていないブラウザでは遷移なしにフォールバックするため、プログレッシブ エンハンスメントに適しています。
計算など、よりきめ細かい制御が必要な場合や、calc-size()
でしか実行できない動作を使用する場合は、calc-size()
を使用できます。
#specific-element {
width: 50px;
&:hover {
width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
}
}
ただし、コード内で calc-size()
を使用する場合、calc-size()
をサポートしていないブラウザ用のフォールバックを組み込む必要があります。たとえば、追加のサイズ宣言を追加したり、@supports
を使用して機能検出にフォールバックしたりします。
width: fit-content;
width: calc-size(fit-content, size + 1em);
/* 👆 Browsers with no calc-size() support will ignore this second declaration,
and therefore fall back to the one on the line before it. */
その他のデモ
interpolate-size: allow-keywords
を活用したデモをいくつかご紹介します。
通知
次のデモは、こちらの @starting-style
デモのフォークです。高さが異なるアイテムを追加できるようにコードを調整しました。
これを実現するには、ページ全体でサイズ キーワードの補間が有効になり、各 .item
要素の height
が auto
に設定されます。それ以外の場合、コードはフォーク前とまったく同じです。
:root {
interpolate-size: allow-keywords; /* 👈 */
}
.item {
height: auto; /* 👈 */
@starting-style {
height: 0px;
}
}
<details>
要素をアニメーション化する
このタイプの補間を使用する一般的なユースケースは、開くときに開示ウィジェットや排他的アコーディオンをアニメーション化することです。HTML では、<details>
要素を使用します。
interpolate-size: allow-keywords
を使用すると、かなりのことができます。
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
details {
transition: height 0.5s ease;
height: 2.5rem;
&[open] {
height: auto;
overflow: clip; /* Clip off contents while animating */
}
}
}
ご覧のとおり、アニメーションは開示ウィジェットが開いているときにのみ実行されます。この問題に対処するため、Chrome では ::details-content
疑似要素の開発を進めており、今年後半に Chrome に搭載される予定です(今後の投稿で詳しく説明します)。interpolate-size: allow-keywords
と ::details-content
を組み合わせると、両方向のアニメーションを作成できます。