最可靠方案是用 width + transition,避免 flex-basis 动画;因其非纯视觉属性且浏览器支持差,易导致跳帧、换行、图标溢出;width 方案需设初始 32px、禁用 0、配合 min(240px,80vw)、overflow:hidden、white-space:nowrap 及 box-sizing:border-box。

直接用 width + transition 最可靠,别碰 flex-basis 做伸缩动画。
为什么 flex-basis 动画大概率失效
浏览器对 flex-basis 的过渡支持极弱——它不是纯视觉属性,而是参与 Flex 布局分配阶段的计算值。一旦父容器是 display: flex,且子项没锁死 flex-grow: 0 和 flex-shrink: 0,中间帧就会被跳过,动画变成“啪”一下弹出来。
常见错误现象:flex-basis: 32px → flex-basis: 240px 动画卡顿、文字换行、右侧图标被挤出视口。
即使强行加 transition: flex-basis 0.3s,也只在 Chrome 110+ 等新版中勉强可用,Firefox/Safari 基本不认。
用 width 实现平滑伸缩的关键设置
只要搜索框不依赖 flex 自动伸缩逻辑,就改用 width。这是兼容性最好、行为最可预测的方案。
- 初始态设
width: 32px(刚好容下放大镜图标),**不要用width: 0** —— 否则元素坍缩会导致offsetWidth读取为 0,JS 测量失准 - 激活态推荐
width: min(240px, 80vw),兼顾小屏和大屏适配 - 必须加
overflow: hidden和white-space: nowrap,防止文字溢出打断动画节奏 - 父容器若有
padding或border,记得统一用box-sizing: border-box
JS 切换 class 时容易卡顿或跳变
典型错误:点击按钮后立刻 el.classList.add('expanded'),又马上读 el.offsetWidth,触发强制同步重排,动画直接中断。
正确做法:
- 用
getComputedStyle(el).width读目标值前,先包一层requestAnimationFrame延迟一帧 - 或者更干脆:放弃 JS 测量,用 CSS 原生状态驱动,比如
:focus-within或:has(input:focus)(截至 2026 年 4 月,Chrome/Firefox/Edge 已稳定支持) - 若需兼容老浏览器,可在 JS 中先
el.offsetWidth强制触发布局,再改 class —— 但仅限一次,别连读连写
真正难的不是写几行 transition,而是控制好宽度变化时内容不换行、图标不位移、焦点不丢失。这些细节全靠 white-space、overflow、box-sizing 和触发时机共同约束。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











