最稳方案是用 max-height:初始设 max-height: 0 + overflow: hidden,展开设足够大的固定值如 500px,并 transition max-height;interpolate-size 虽可实现 height: 0 → auto 动画但仅 Chrome 129+ 支持且需父容器设置、兼容性差;grid 方案精确但依赖布局约束且 Safari 支持不稳定。

不能直接实现——height: 0 → height: auto 永远不会产生平滑过渡,浏览器不支持对 auto 插值,无论加多少 transition 都会跳变。
为什么 Chrome 129+ 的 interpolate-size: allow-keywords 仍不推荐直接用
它确实能让 height: 0 → height: auto 在 Chrome 中动起来,但有硬性前提和兼容陷阱:
-
interpolate-size: allow-keywords必须写在父容器上,不是目标元素本身;写错位置(比如直接加在要展开的<div> 上)就完全无效 <li>若父级是 <code>flex或grid容器,继承链可能被截断,得手动设到最近的非 flex/grid 父级 - Safari 和 Firefox 截至 2026 年 10 月仍完全不支持该属性,无 fallback 就等于功能残缺
- 即使启用,也必须同时满足:
height: 0显式声明、transition: height明确写出、展开状态保留height: auto兜底——漏任一环动画就失效 - 初始状态:
max-height: 0+overflow: hidden(注意不是height: 0,因为 padding/border 会让视觉高度不为 0) - 展开状态:
max-height设为一个「足够大且安全」的固定值,比如max-height: 500px;不能设太小(内容被截),也不宜过大(动画时间拉长、影响性能) -
transition必须作用于max-height,例如transition: max-height 0.3s ease-in-out;不要混用height或opacity过渡,否则行为不可控 - 如果菜单含 padding/border,它们不会随
max-height动画缩放,需单独用padding或transform补动画,否则收起时边缘会“抽搐” - 父容器必须是
display: grid,且显式声明grid-template-rows: 0fr(收起)→minmax(0, max-content)(展开) - 目标内容区需设
overflow: hidden,否则内容会撑开布局破坏动画 - 父容器必须有确定的高度上下文(比如设置了
height、或在 flex/grid 子项中受约束),否则max-content无法计算基准 - 注意:0fr 不等于 height: 0,它是轨道尺寸为 0,依赖
overflow: hidden才能视觉隐藏;且该方案在旧版 Safari 中支持度仍不稳定
用 max-height 是最稳的通用方案
它绕过 auto 插值限制,兼容所有现代浏览器,实操要点很具体:
真正内容自适应的方案:用 grid-template-rows
当需要精确匹配内容高度、又不想 JS 测量时,grid 的 fr 单位是目前唯一能兼顾平滑与准确的纯 CSS 方案:
立即学习“前端免费学习笔记(深入)”;
真正难的不是选哪个方案,而是意识到:只要涉及 height: auto,就必须接受「要么妥协精度(max-height)、要么放弃兼容(interpolate-size)、要么引入新约束(grid 布局强依赖)」。没有银弹,只有取舍点在哪更可接受。


















