transition 无法直接监听 height 百分比变化,因其依赖父容器高度且无明确像素值供插值;应优先用 transform: scaley() 配合 transform-origin: bottom 实现平滑上升,或通过 calc() 与 css 变量将百分比转为像素,js 动态计算为兜底方案。

transition 不能直接监听 height 百分比变化
因为 height: 50% 这类相对值在 CSS 中无法被浏览器计算出具体的像素起点和终点,transition 没法插值——它只认明确的数值(比如 height: 0px → height: 200px)。你写 transition: height 0.3s + height: 0% → height: 80%,动画根本不会动,或者只在首次渲染时“跳”一下。
常见错误现象:height 从 0% 变到 100%,进度条突然弹出来,没有过渡;DevTools 里看到 height 值变了,但视觉上没动画。
- 必须把目标高度转成具体像素值(
px)或使用支持插值的替代属性 - 百分比高度依赖父容器,而父容器本身可能没固定高,进一步加剧不可预测性
- 如果父容器高度是
auto或由内容撑开,%高度会失效或归零
用 transform: scaleY() 替代 height 动画
transform 的 scaleY() 是最稳妥的平滑上升方案:它不触发重排,性能好,且能基于任意初始状态插值。关键在于把进度条做成固定高度的容器,再用缩放模拟“填满”效果。
使用场景:垂直进度条高度需随数据动态增长(如加载完成度、任务进度),且要兼容 Flex/Grid 布局、响应式容器。
立即学习“前端免费学习笔记(深入)”;
- 给进度条元素设固定
height(比如height: 200px),内部子元素用transform: scaleY(0)→scaleY(1) - 起始态用
transform: scaleY(0),终点用transform: scaleY(0.75)表示 75% 高度 - 务必加
transform-origin: bottom,否则缩放中心在顶部,看起来是“向下拉长”,不是“从底向上长” - 不要同时写
height和transform动画,避免冲突
`.progress-bar {
height: 200px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: #4a90e2;
transform-origin: bottom;
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.progress-fill.active {
transform: scaleY(0.8);
}`用 CSS 自定义属性 + calc() 实现百分比驱动的 height 动画
如果你坚持用 height,唯一可行的方式是让父容器有确定高度,并通过 CSS 变量传入数值,再用 calc() 转成像素。这绕过了百分比不可插值的问题,但代价是父容器必须可测量。
参数差异:--progress: 65 表示 65%,配合 height: calc(var(--progress) * 1px) 就能生成像素值——前提是父容器高度已知且单位统一(比如父高是 300px,那 1% = 3px)。
- 父容器需设
height: 300px(不能是min-height或auto) - 子进度条写
height: calc(var(--progress) * 3px),其中3是每 1% 对应的像素 - 修改
--progress值时,height才会真正产生可过渡的数值变化 - 注意 Safari 对
calc()在transition中的支持较晚,iOS 15.4+ 才稳定
JavaScript 配合 getBoundingClientRect() 动态补全高度
当父容器高度不确定(比如响应式布局、字体加载影响行高),纯 CSS 方案容易失准。这时得靠 JS 读取真实像素高度,再注入 CSS 变量或内联样式。
容易踩的坑:在 DOM 渲染前就读高度,拿到 0;或 resize 后没重新计算,导致动画错位。
- 用
offsetHeight或getBoundingClientRect().height获取父容器当前像素高 - 算出 1% 对应多少 px:
const unit = parentHeight / 100,再设element.style.setProperty('--unit', unit + 'px') - 监听
resize或字体加载完成事件(document.fonts.ready),重新计算 - 避免高频触发:用
requestAnimationFrame节流
CSS 垂直进度条的“平滑上升”本质是规避百分比 height 的插值缺陷。真正落地时,transform: scaleY() 最省心,calc() + CSS 变量次之,JS 补全是兜底手段——但三者都绕不开一个事实:浏览器不会帮你猜“100% 到底是多少像素”。










