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+ | ⭐⭐ | 仅需视觉动画、不改变文档流时 |
七、项目实践建议
- 当前项目:使用
grid-template-rows。代码最少、效果最好、现代浏览器全覆盖。 - 降级处理:如果需要支持老浏览器,可使用
CSS.supports('grid-template-rows', '0fr')检测,不支持则降级为无动画方案。 - 未来演进:随着 Chrome 133+ 普及,可直接替换为
height: auto+interpolate-size。