直接用css变量控制width会失效,因为浏览器无法对var()的值变化做插值动画;正确做法是用var()控制max-width并配合width:100%和transition:max-width。

为什么直接用 CSS 变量控制 width 会失效
很多人写 --search-width: 120px,再在 input 上设 width: var(--search-width),配上 transition: width 0.3s,结果点击后宽度“啪”一下跳变,没有动画。问题不在变量本身,而在于:浏览器无法对 var(--search-width) 的变化做插值——它只是个符号替换,transition 看不到中间值。除非你手动改多个离散值(比如从 120px → 240px),否则 CSS 引擎不会生成过渡帧。
width + var() 要配合固定起始值才可动画
想让变量驱动平滑拉伸,必须确保起始态和结束态都是确定的、可插值的像素值,且变量只用于切换状态,不参与计算过程。正确做法是:
- 初始态写死
width: 32px(别用var()),加transition: width 0.3s ease - 激活态用
:focus或.expanded类,里面写width: var(--search-expanded-width, 240px) -
--search-expanded-width只在根或父级定义,比如:root { --search-expanded-width: min(240px, 80vw); } - 避免在变量里混用
auto或百分比,min()函数可以,但需确认浏览器支持(Chrome/Firefox/Edge 全支持,Safari 15.4+)
移动端 Safari 对 var() + width 的渲染延迟
iOS Safari 在解析含 var() 的 width 时,偶尔会延迟一帧才应用新值,导致动画开头卡顿。缓解方法有二:
- 聚焦前一刻动态加
will-change: width(别常驻,否则持续消耗 GPU) - 改用
max-width替代:width: 100%+max-width: var(--search-max-width, 120px),过渡max-width更稳,IE10+ 都认 - 务必在
加<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">,否则 Safari 可能因缩放重排打断变量生效
真正省心的方案:用 var() 控制 max-width 而非 width
比起折腾 width + var(),更推荐把变量用在 max-width 上。它天然兼容响应式,且不破坏布局流:
:root {
--search-collapsed: 120px;
--search-expanded: 320px;
}
.search-input {
width: 100%;
max-width: var(--search-collapsed);
transition: max-width 0.3s ease;
box-sizing: border-box;
}
.search-input:focus {
max-width: var(--search-expanded);
}
注意:max-width 动画只在「扩张方向」有效;如果内容很短,它不会强行撑满 --search-expanded,这是优点而非 bug。需要强制撑开时,得配合 flex-grow: 1 或 JS 测 scrollWidth ——但那就不是纯 CSS 变量能解决的事了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











