:focus触发width动画常失效,因auto/100%不可插值;须用确定尺寸、transition写在默认态、配合overflow:hidden和box-sizing:border-box,并注意移动端需JS补位及避免布局重排。

单纯用 :focus 触发 width 动画,90% 的情况下会失效——不是写法错,而是浏览器根本没法插值。
为什么 :focus + width 常常没动画
浏览器对 width 做过渡,要求起始值和结束值都必须是可计算、可插值的确定尺寸。但很多开发者直接写:
input { width: auto; transition: width 0.3s; }
input:focus { width: 240px; }
问题就出在 auto:它不是数值,浏览器跳过过渡直接渲染。即使你用 100% 开头,父容器宽度一变,起始值就浮动,插值失败。
- 起始
width必须是明确单位:比如48px、3rem,不能是auto或100% -
transition必须写在默认状态(非:focus),否则首次聚焦不触发 - 别在 flex 容器里混用
width和flex,容易被min-width或flex-shrink截断动画
怎么写才真正能动:初始宽度 + overflow: hidden
收起态不是“消失”,而是“只露图标”。关键不是压窄,而是控制可见范围:
立即学习“前端免费学习笔记(深入)”;
- 给
input设初始width: 48px(刚好容下搜索图标 + 一点 padding) - 加
overflow: hidden,确保文字和光标不溢出 - 聚焦时设
width: 220px,同时调小padding-left让文字左移,视觉更连贯 - 务必写
box-sizing: border-box,否则边框和内边距会额外撑宽
示例 CSS:
input.search-input {
width: 48px;
padding: 8px 12px 8px 36px;
overflow: hidden;
box-sizing: border-box;
transition: width 0.25s ease, padding-left 0.25s ease;
}
input.search-input:focus {
width: 220px;
padding-left: 12px;
}
移动端 :focus 失效?得靠 JS 补位
iOS Safari 在软键盘弹出后常不触发 :focus,Android Chrome 对快速失焦响应滞后。纯 CSS 方案在这里不可靠。
- HTML 中给
input加 classsearch-input,外层包个div.search-wrapper - JS 监听
focus和blur,切换is-expanded类:element.classList.add('is-expanded') -
blur时不立即收起,加setTimeout(() => ..., 150),避免点清空按钮时误收 - CSS 写
.search-wrapper.is-expanded .search-input覆盖展开样式,比伪类更可控
width 动画卡顿或跳变的真正原因
不是过渡时间设短了,而是触发了非合成层渲染或布局重排。
- 父容器若设了
overflow: hidden且高度固定,max-width动画会连带引发重排——width同理 - 别同时过渡
padding和border,它们和width渲染节奏不同步,造成视觉撕裂 - 真要提性能,可在聚焦瞬间动态加
style="will-change: width",收起后立刻移除;常驻会拖慢页面 - 确保输入框字体大小 ≥ 16px,iOS Safari 对小字号有强制缩放逻辑,会导致伸缩错位
最易被忽略的是:动画是否平滑,往往取决于父容器的 display 类型和 flex 行为,而不是 input 自身的 transition 写得多漂亮。



















