前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库CSS transition height auto 平滑展开收起
CSS动画与视觉

为什么 height 从 0 到 auto 不能做过渡?怎么实现平滑展开收起?

浏览器做过渡需要两个具体的数值来插值,auto 不是数值,所以 height: 0 到 height: auto 没法过渡。常用的替代方案是用 max-height 估一个上限值,或者用 Grid 的 grid-template-rows 从 0fr 到 1fr 过渡。

前端进阶之旅 · 一题精讲更新于 2026.09.29
CSS#动画与视觉#CSS Grid#动画
先看核心答案读代码示例
理解线索

三种展开收起方案对比

  1. max-height设一个比内容高的大值,收起时前半段动画是空跑
  2. grid-template-rows从 0fr 到 1fr 过渡,不需要知道具体高度
  3. interpolate-size告诉浏览器把 auto 当具体值来插值,新属性

max-height 的大值不能乱给。设 2000px 但内容只有 100px,收起时要等动画跑完 1900px 的空程才看到变化,体验很差。

核心回答

先记住这个答案

CSS 过渡需要一个起始值和一个结束值来做数值插值。auto 是一个关键字,不是具体数值,浏览器拿不到两个数来算中间帧,所以 height: 0 到 height: auto 不会有动画效果,而是直接跳变。解决思路有三种:用 max-height 估上限值、用 Grid 行高做 0fr 到 1fr 的过渡、或等浏览器支持 interpolate-size。

  • height: auto 不是数值,浏览器无法对它做插值
  • max-height 方案简单但收起时有明显停顿感
  • Grid 行轨道可实现部分展开动画
  • interpolate-size 可让尺寸关键字参与插值

max-height 技巧和它的缺陷

最常见的做法是不过渡 height,改成过渡 max-height。收起时设 max-height: 0,展开时设一个比内容实际高度大的值,比如 max-height: 500px。

用 max-height 模拟展开CSS
.panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}
.panel.open {
  max-height: 500px; /* 估一个比内容高的值 */
}

这个方案能用,但有明显缺点。展开时,动画从 0 到 500px 的过程中,实际内容可能只有 100px 高。当 max-height 超过内容高度后,内容已经完全显示了,剩余的动画时间在空跑。视觉上就是内容很快就出来了,然后停了一下才算结束。收起时更明显:从 500px 开始往下减,前 400px 的变化用户完全看不到,到了 100px 才开始有视觉变化,给人「顿了一下才动」的感觉。 所以 max-height 的大值不能随便给。设得太大,停顿感重;设得太小,内容会被截断。如果内容高度是动态的,就很难挑到合适的值。

Grid 行高方案:不需要知道具体高度

用 CSS Grid 可以绕开「不知道内容多高」的问题。思路是把要展开的内容放在一个 Grid 容器里,过渡容器的行高从 0fr 到 1fr。

grid-template-rows 过渡CSS
.wrapper {
  display: grid;
  grid-template-rows: 0fr; /* 收起:行高为 0 */
  transition: grid-template-rows 0.3s ease;
}
.wrapper.open {
  grid-template-rows: 1fr; /* 展开:行高自适应内容 */
}
.wrapper > .content {
  overflow: hidden; /* 收起时隐藏溢出内容 */
}

0fr 和 1fr 都是数值,浏览器可以在它们之间插值。1fr 的实际高度等于内容的高度,所以动画的节奏和内容高度完美匹配,不会有 max-height 那种空跑的问题。这是目前兼容性和效果最好的方案,主流浏览器都已支持。

未来的原生方案:interpolate-size

Chrome 129 开始支持 interpolate-size: allow-keywords。加了这个声明后,浏览器会在过渡时先计算出 auto 对应的具体像素值,然后正常插值。这意味着可以直接写 height: 0 到 height: auto 的过渡了。

这个属性可以设在容器上让子元素继承,也可以设在 :root 上全局生效。不过目前 Firefox 和 Safari 还没支持,生产环境建议先用 Grid 方案,把 interpolate-size 作为渐进增强。

回答前,多想一步

容易答错的地方

以为用 JS 先读高度再设上去就行
用 JS 读取 scrollHeight 然后设成 height 确实可以过渡,但这种做法在内容高度变化时要重新测量,而且读 scrollHeight 本身会触发强制布局。如果在动画帧里频繁读写,反而引起性能问题。
以为 max-height 设得够大就没问题
max-height 设得越大,空跑时间越长。比如内容 200px,max-height 设 2000px,收起动画 0.3 秒里前 90% 的时间用户完全看不到变化。
试着用自己的话回答

面试官还会怎么问?

展开收起时想顺便做 opacity 渐显怎么配合?

在同一个元素上加 transition: grid-template-rows 0.3s, opacity 0.3s,展开时 opacity 从 0 到 1,收起时反过来。opacity 不触发布局,两个过渡并行不影响性能。

为什么不用 scaleY 来模拟展开?

scaleY(0) 到 scaleY(1) 只是视觉上缩放,元素在布局中仍然占据原来的空间。展开面板下面的内容不会被推开,视觉效果和真正的高度变化差别很大。

收起的时候想要不同的缓动曲线怎么做?

在收起状态写 transition: grid-template-rows 0.3s ease-in,在展开状态写 transition: grid-template-rows 0.3s ease-out。浏览器用的是目标状态的 transition 声明,所以展开时读 .open 的缓动,收起时读默认状态的缓动。

从一道题,走向一组知识

把知识连起来

动画与视觉

cubic-bezier 四个参数分别控制什么?

展开收起的缓动曲线选择直接影响手感,搭配自定义贝塞尔曲线效果更自然。

动画与视觉

animation-direction 的 alternate 和 reverse 有什么区别?

用 @keyframes 做展开收起时,animation-direction 控制正放和倒放的切换逻辑。

动画与视觉

transition-property 写 all 和只列具体属性,性能上有区别吗?

展开收起如果过渡 height 会触发布局重排,了解属性类型对性能的影响能帮你选对方案。

参考资料

  • CSS transitions

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. max-height 技巧和它的缺陷
  3. Grid 行高方案:不需要知道具体高度
  4. 未来的原生方案:interpolate-size
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑