Web 端展开/收起面板方案总结

梳理纯 CSS(grid-template-rows、max-height、transform、interpolate-size)、JS(Web Animations API)与语义化(details)等展开收起方案,给出推荐实现与降级策略。

一、核心挑战

在 CSS 中,height 和 width 属性如果设置为 auto,默认是无法做过渡动画(transition)的。因此展开/收起效果通常需要借助 Hack 或现代 CSS 新特性来实现。


二、纯 CSS 方案

1. grid-template-rows(当前推荐方案)

利用 CSS Grid 布局的特性,在 0fr 和 1fr 之间进行过渡,浏览器会自动计算实际内容高度。

.ai-audit-content {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.3s ease;
}

.ai-audit-content.collapsed {
  grid-template-rows: 0fr;
}

.ai-audit-content-inner {
  overflow: hidden;
}
优点 缺点 兼容性
无需预设高度,动画精确流畅 低版本浏览器无动画(直接跳变) Chrome 84+ / Firefox 66+ / Safari 14+

2. max-height(传统 Hack)

设置一个足够大的 max-height,配合 overflow: hidden 和 transition。

.ai-audit-content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.ai-audit-content.expanded {
  max-height: 1000px; /* 需大于实际内容高度 */
}
优点 缺点 兼容性
兼容性极好(IE10+) 展开时动画延迟(空转),收起时提前结束;动画时序不精确 IE10+ / 全平台

3. transform: scaleY()

通过 2D 缩放实现视觉上的收起,不改变文档流中的高度。

.ai-audit-content {
  transform-origin: top;
  transform: scaleY(1);
  transition: transform 0.3s ease;
}

.ai-audit-content.collapsed {
  transform: scaleY(0);
  opacity: 0; /* 配合透明度防止子元素仍可交互 */
}
优点 缺点 兼容性
动画性能极佳(GPU 加速) 不改变布局高度,下方内容可能跳动或被遮挡 IE9+

4. interpolate-size + height: auto(未来官方标准)

CSS 工作组正式推出的解决方案,允许对 auto 高度进行插值过渡。

:root {
  interpolate-size: allow-keywords;
}

.ai-audit-content {
  height: 0;
  overflow: hidden;
  transition: height 0.3s ease;
}

.ai-audit-content.expanded {
  height: auto;
}
优点 缺点 兼容性
语法最直观,彻底告别 Hack 极新特性,旧浏览器不支持 Chrome 133+ / Safari 18.2+

5. calc-size(auto, size)(同上规范的配套)

不需要全局开启 interpolate-size,直接在声明处启用。

.ai-audit-content {
  height: 0;
  overflow: hidden;
  transition: height 0.3s ease;
}

.ai-audit-content.expanded {
  height: calc-size(auto, size);
}

兼容性同上。


三、JS 方案

1. Web Animations API

使用浏览器原生动画 API 精确驱动 height 过渡。

const toggleHeight = (el: HTMLElement, expand: boolean) => {
  const start = expand ? 0 : el.scrollHeight;
  const end = expand ? el.scrollHeight : 0;
  
  el.animate(
    [{ height: `${start}px` }, { height: `${end}px` }],
    { duration: 300, easing: 'ease', fill: 'forwards' }
  );
}
优点 缺点 兼容性
走 GPU 合成线程,不阻塞渲染 需要 JS 参与,代码量稍大 Chrome 50+ / Firefox 48+

四、语义化方案

<details> + <summary>

HTML5 原生提供的可折叠元素,自带交互逻辑。

<details class="ai-details">
  <summary>标题</summary>
  <div class="content">详细内容</div>
</details>

配合 CSS 动画:

.ai-details > .content {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.3s ease;
}

.ai-details:not([open]) > .content {
  grid-template-rows: 0fr;
}

/* 隐藏原生箭头 */
summary::-webkit-details-marker, summary::marker { display: none; }
优点 缺点 兼容性
语义化极佳,无障碍友好,无需 JS 控制状态 动画仍需 CSS 配合;Vue 中双向绑定不如自定义组件灵活 IE10+(无动画)/ 现代浏览器

五、进阶动画特性

@starting-style + display 动画

2024 年推出的新标准,允许在元素首次渲染(或 display 切换)时执行过渡动画,可完美替代 v-show。

.ai-audit-content {
  display: none;
  transition: height 0.3s ease, opacity 0.3s ease;
  
  &:is([data-visible]) {
    display: block;
    @starting-style {
      height: 0;
      opacity: 0;
    }
    height: auto;
    opacity: 1;
  }
}

状态:Chrome 124+ / Firefox 133+ / Safari 18.2+。


六、方案对比总结

方案 动画质量 代码量 兼容性 推荐度 适用场景
grid-template-rows ⭐⭐⭐⭐⭐ 5行 Chrome 84+ ⭐⭐⭐⭐⭐ 现代前端项目默认首选
interpolate-size ⭐⭐⭐⭐⭐ 4行 Chrome 133+ 🔮 未来终局方案
Web Animations API ⭐⭐⭐⭐⭐ 20行 全现代浏览器 ⭐⭐⭐⭐ 需要极精确动画且无 CSS 限制
<details> ⭐⭐⭐⭐⭐ 混合 全现代浏览器 ⭐⭐⭐⭐ 文档页、静态页、无需复杂交互
max-height ⭐⭐ 4行 IE10+ ⭐⭐ 兼容 IE 的老项目
transform: scaleY() ⭐⭐⭐ 6行 IE9+ ⭐⭐ 仅需视觉动画、不改变文档流时

七、项目实践建议

  1. 当前项目:使用 grid-template-rows。代码最少、效果最好、现代浏览器全覆盖。
  2. 降级处理:如果需要支持老浏览器,可使用 CSS.supports('grid-template-rows', '0fr') 检测,不支持则降级为无动画方案。
  3. 未来演进:随着 Chrome 133+ 普及,可直接替换为 height: auto + interpolate-size。