直接写 width: 0 会导致跳变,因其被浏览器视为彻底坍缩,offsetWidth 为 0,transition 失去插值依据;应改用非零收起态(如 width: 32px)并配 overflow: hidden 和 white-space: nowrap。

为什么直接写 width: 0 会跳变
浏览器把 width: 0 当作彻底坍缩状态,内部文字、padding、border 全被压掉,offsetWidth 读出来是 0,transition 插值失去依据。结果就是动画不执行,“啪”一下弹开。
真正可用的收起态必须是非零且明确:
-
width: 32px(刚好放一个放大镜图标) - 必须配
overflow: hidden和white-space: nowrap,防文字换行打断节奏 -
width: 0、display: none、visibility: hidden都不能参与transition
用 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让视觉宽度超出预期
JS 切换类名时动画卡顿的真实原因
点击后立刻 el.classList.add('expanded'),又马上读 el.offsetWidth,会强制同步重排,动画直接中断。这不是 CSS 写错了,而是 JS 测量时机不对。
正确做法:
- 用
getComputedStyle(el).width读值前,包一层requestAnimationFrame延迟一帧 - 更推荐放弃 JS 测量,改用 CSS 原生状态驱动,比如
:focus-within或:has(input:focus)(Chrome/Firefox/Edge 已稳定支持) - 若需兼容老浏览器,可在 JS 中先读一次
el.offsetWidth强制触发布局,再改 class —— 但仅限一次,禁止连读连写
最易被忽略的是:所有 transition 声明必须写在默认状态规则里,不能只写在 :focus 或展开类中;起始值必须是可计算单位(如 32px、2rem),auto 或 100% 不行。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











