組み込みサイズへのアニメーション

ウェブ機能: calc-size() interpolate-size

これまで、block-size: auto や inline-size: max-content などの動的なサイズに要素をアニメーション化するには、JavaScript や不安定な「max-height」ハックが必要でした。interpolate-size プロパティと calc-size() 関数を使用すると、ブラウザは固定長と固有のサイズ設定キーワードの間をネイティブに補間できます。

実装の手順

  1. キーワード補間を有効にする: 親要素(通常は :root)に interpolate-size: allow-keywords を適用して、固有のキーワードを使用するプロパティの遷移を有効にします。
  2. 遷移を定義する: ターゲット要素のサイズ設定プロパティ(block-size、inline-size など)に transition を設定します。
  3. 組み込みキーワードを使用する: インタラクション(:hover や状態クラスなど)中に、サイズ設定プロパティをサポートされている組み込みキーワード(auto、min-content、max-content、fit-content、または(flex-basis の場合)content)に変更します。
  4. 計算を実行する(省略可): 固有サイズ(auto + 2rem など)に対して計算を実行する必要がある場合は、calc-size() を使用します。calc-size() は、ベースに依存しない計算用の any キーワードもサポートしています。

例: 一般的な拡張パターン

このパターンは、任意のコンテナ(「もっと見る」セクションやナビゲーション メニューなど)に適用して、制限された高さと要素の自然なサイズの間で遷移できます。

/* Opt-in globally for all children */
:root {
  /* MANDATORY: Transitions to intrinsic keywords are disabled by default for compatibility */
  interpolate-size: allow-keywords;
}

.expandable-container {
  /* 1. Define a fixed initial size (or 0) and hide overflow */
  block-size: 100px;
  overflow: hidden;
  
  /* 2. Transition the sizing property */
  transition: block-size 0.4s ease-out;
}

.expandable-container.is-expanded {
  /* 3. Smoothly animate to the intrinsic natural height */
  block-size: auto;
}

例: 計算された固有のインライン サイズ

.badge {
  inline-size: 40px;
  overflow: hidden;
  white-space: nowrap;
  transition: inline-size 0.3s ease;
}

.badge:hover {
  /* calc-size(basis, calculation) */
  /* 'size' refers to the evaluated basis (max-content in this case) */
  inline-size: calc-size(max-content, size + 20px);
}

例: 組み込みから固定への移行

逆方向のアニメーション(自然なサイズから特定の長さに縮小する)も可能です。これは、「閉じることができる」コンポーネントに役立ちます。

.collapsible-alert {
  /* 1. Start with the natural content height */
  block-size: auto;
  overflow: hidden;
  transition: block-size 0.5s ease-in-out, opacity 0.5s ease;
}

.collapsible-alert.is-dismissed {
  /* 2. Smoothly collapse to zero */
  block-size: 0;
  opacity: 0;
  pointer-events: none;
}

/* MANDATORY Copy-Paste Safety: Disable sizing animations for sensitive users */
@media (prefers-reduced-motion: reduce) {
  .expandable-container,
  .badge,
  .collapsible-alert {
    transition: none !important;
  }
}
// MANDATORY Accessibility Synchronization: Ensure elements collapsed to zero dimensions are removed from the assistive technology tree, and sync aria-expanded states on triggers.
const alertElement = document.querySelector('.collapsible-alert');
alertElement.addEventListener('transitionend', (e) => {
  if (e.propertyName === 'block-size' && alertElement.classList.contains('is-dismissed')) {
    alertElement.hidden = true;
  }
});

// Example trigger syncer
const triggerBtn = document.querySelector('.accordion-trigger');
triggerBtn?.addEventListener('click', () => {
  const isExpanded = triggerBtn.getAttribute('aria-expanded') === 'true';
  triggerBtn.setAttribute('aria-expanded', !isExpanded);
});

主な制約

  • キーワード間の制限: 2 つの異なるキーワード間で直接アニメーション化することはできません(例: min-content から max-content)。遷移の片端は、固定の長さまたは割合にする必要があります(例: 0 から auto)。
  • calc-size 構文: calc-size() 内で、同じ式に異なる固有キーワードを混在させることはできません。最初の引数(基底)は、size が表すものを定義します。
  • オプトイン要件: 下位互換性を維持するため、組み込みキーワードへの移行はデフォルトで無効(numeric-only)になっています。要素または祖先に interpolate-size: allow-keywords を適用する必要があります。calc-size() はプロパティごとのオーバーライドとして機能し、使用されるたびに補間を自動的に有効にします。

代替戦略

interpolate-size と calc-size() はプログレッシブ エンハンスメントです。サポートしていないブラウザでは、ターゲット サイズに瞬時にジャンプします。

  • グレースフル デグラデーション: 単純な block-size: auto 遷移の場合、標準のブラウザではサイズが瞬時に切り替わります。これは機能的ですが、洗練されていません。
  • 手動のキーワード フォールバック: calc-size() を使用する場合は、古いブラウザ用に標準のキーワード フォールバックを必ず指定してください。古いブラウザでは calc-size() 宣言全体が破棄されるためです。
.card {
  block-size: auto; /* Fallback for older browsers */
  block-size: calc-size(auto, size); /* Modern browsers use this */
  transition: block-size 0.3s ease;
}