直接设 width: 0 会导致浏览器坍缩元素,offsetWidth 为 0 使 transition 失去插值依据而跳变;应使用非零明确值如 width: 32px 或更稳妥的 max-width 方案,并确保 transition 声明在默认状态中且不被覆盖。

为什么直接写 width: 0 会跳变
浏览器把 width: 0 当作彻底坍缩状态,内部文字、padding、border 全部被压掉,offsetWidth 读出来是 0,transition 插值失去依据。结果就是动画不执行,“啪”一下弹开。
真正可用的收起态必须是非零且明确:比如 width: 32px(刚好放一个放大镜图标),再配 overflow: hidden 和 white-space: nowrap 防文字换行打断节奏。
width: 0、display: none、visibility: hidden 都不能参与 transition;起始值必须是可计算单位,如 32px、2rem,auto 或 100% 不行。
用 max-width 替代 width 避开 flex 干扰
在 flex 容器里给 <input> 设 flex-grow: 1 再加 transition: width,动画大概率失效——因为 flex-grow 分配的是动态剩余空间,不是可插值的数值类型。
立即学习“前端免费学习笔记(深入)”;
更稳的路径是放弃 width,改用 max-width 控制伸展上限:
- 初始:
max-width: 40px+overflow: hidden - 展开:
max-width: min(320px, 80vw)(兼顾小屏和留白) - 必须配合
width: 100%,否则max-width不生效
这个方案 IE10+ 兼容,且不会被 flex 布局逻辑干扰。
移动端点击不到输入框?热区没扩够
收起态 width: 32px 只够放图标,用户点不到 <input> 本体,iOS Safari 尤其容易 focus 失败,键盘根本打不开。
别用 opacity: 0 + pointer-events: none 隐藏 <input>——这会切断焦点链。
可行做法:
- 给
<input>加padding-left: 32px,再用::before绝对定位图标,左侧空白区域也能触发聚焦 - 搜索按钮必须设
flex-shrink: 0,否则小屏下被压缩消失 - 移动端建议把按钮抽成
position: absolute叠在<input>右侧,释放水平空间
务必加 box-sizing: border-box,否则 padding 和 border 让视觉宽度超出预期。
transition 声明必须写在默认状态规则里
很多人只在 :focus 或展开类中写 transition,结果首次聚焦没动画。声明必须放在默认状态规则里,例如:
input {
width: 32px;
transition: width 0.3s ease, border-radius 0.3s ease;
overflow: hidden;
white-space: nowrap;
}
input:focus {
width: 280px;
border-radius: 24px;
}
常见错误是全局重置样式(如 Normalize.css)或框架(如 Tailwind)设置了 transition: all 0.2s,把你写的 transition: width 0.3s 覆盖了。用 DevTools 检查 computed 样式里的 transition,确认实际生效的是你写的那条。
显式写出所有要过渡的属性,避免用 all;如果用了 transform 或 opacity 等辅助动效,务必单独声明,不要混进同一个 transition。


















