直接修改:focus中的width常失效,因CSS transition无法对auto或100%等非确定值做插值;应改用CSS变量控制宽度,并在基础样式中声明transition,确保变量有初始值且width始终绑定var(--search-w)。

为什么直接改 :focus 里的 width 常常失效
因为浏览器无法对 auto 或 100% 这类非确定值做插值过渡。你写 width: 100%; → width: 300px;,它不渐变,直接跳。很多开发者卡在这一步,反复检查选择器却忽略根本限制:CSS transition 只能动画「可计算的数值」。
用 CSS 变量不是为了炫技,而是绕过这个限制——把宽度逻辑从属性值里抽出来,交给变量控制,再让 :focus 去改变量值,过渡就自然生效了。
- 必须给变量设初始数值(不能是
unset或空字符串),比如--search-w: 140px; -
width属性本身要始终绑定变量,如width: var(--search-w);,否则改变量没用 - 过渡声明得写在变量变更前的元素上,即
transition: width 0.25s ease;要放在基础样式里,不能只写在:focus中
:focus 如何安全修改 CSS 变量值
变量本身不能被伪类“拥有”,但你可以用 :focus 触发父级或自身上变量的重定义。最稳妥的方式是直接在 input 元素上覆盖变量:
.search-input {
--search-w: 140px;
width: var(--search-w);
transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.search-input:focus {
--search-w: 280px;
}
注意点:
立即学习“前端免费学习笔记(深入)”;
- 别在
:focus里写width: var(--search-w);—— 它不会重新触发计算,变量值变了但 width 没刷新 - 如果父容器用了
flex,优先用flex-basis绑定变量,比如flex-basis: var(--search-w);,比width更兼容 flex 布局 - IE11 不支持 CSS 变量,若需兼容,得 fallback 到
max-width+:focus方案
移动端 :focus 不触发变量更新?检查这三点
iOS Safari 和部分安卓 WebView 对 :focus 的触发时机很敏感,尤其套了 label 或加了 JS 干预后,变量可能根本不更新。
- 确认
<input>没被pointer-events: none、tabindex="-1"或disabled阻断 - 如果用了
<label for="xxx">,确保for值和 input 的id完全一致(大小写敏感) - 某些情况下需显式加
cursor: text或user-select: text,否则软键盘弹出延迟导致:focus样式滞后一帧
变量方案比 max-width 过渡难在哪
它更灵活,但也更易出错。真正麻烦的不是写法,而是变量作用域和继承链:
- 变量名冲突风险高:
--w这种短名容易被其他组件覆盖,建议带命名空间,如--search-input-width - 变量不会自动响应父容器尺寸变化,比如窗口缩放时,你得配合
@media手动重设变量值,不能指望它像100%那样自适应 - 调试困难:浏览器开发者工具里看不到变量实时值是否生效,得靠 computed styles 看最终
width是否已更新
真要用变量驱动宽度,就得接受它是个「静态快照」——聚焦时切一个值,失焦时切回去,别指望它动态跟随内容或容器伸缩。


















