添加向固有尺寸过渡的动画效果

过去,要将元素动画化为动态大小(例如 block-size: auto 或 inline-size: max-content),需要使用 JavaScript 或脆弱的“max-height”技巧。interpolate-size 属性和 calc-size() 函数允许浏览器在固定长度和固有尺寸关键字之间进行原生插值。

实现步骤

  1. 选择启用关键字插值:将 interpolate-size: allow-keywords 应用于父元素(通常为 :root),以便为使用固有关键字的属性启用过渡效果。
  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);
}

示例:从 Intrinsic 过渡到 Fixed

您也可以反向添加动画,即从自然大小开始,然后收起至特定长度。这对于“可关闭”组件非常有用。

.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);
});

主要限制

  • 关键字到关键字限制:您无法直接在两个不同的关键字之间添加动画效果(例如,从 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;
}