:focus-within更可靠,解决图标消失失效问题;需统一box-sizing、用opacity+visibility过渡;ie11等旧环境需js回退;图标缩放时应避免pointer-events:none导致失焦异常。

focus 时图标消失:用 :focus-within 更可靠
直接对 input 用 :focus 控制父容器里的图标,常因结构嵌套深或事件冒泡不一致而失效。比如图标在 div.search-box 内部,但 input:focus 无法向上影响兄弟节点的图标显示。
更稳的做法是把过渡逻辑放在父容器上,用 :focus-within:
div.search-box {
transition: padding 0.2s ease;
}
div.search-box:focus-within .search-icon {
opacity: 0;
transform: scale(0.8);
}
div.search-box:focus-within input {
width: 100%;
}
-
:focus-within兼容 Chrome 60+、Firefox 52+、Safari 15.4+,旧版 Safari 需降级为 JS 监听focus/blur - 图标必须和
input在同一可聚焦容器内(不能跨shadow DOM或 iframe) - 避免对
.search-icon同时设display: none和过渡——display不触发重绘,得用opacity+visibility组合
输入框伸展卡顿:width 不是唯一变量
只改 width 容易出现“先拉伸再对齐”或边缘抖动,尤其在有边框、padding、box-sizing 混用时。
真正要同步过渡的是整个盒模型参与布局的部分:
立即学习“前端免费学习笔记(深入)”;
input {
box-sizing: border-box;
padding: 8px 12px;
border: 1px solid #ccc;
width: 160px;
transition: width 0.25s ease, padding 0.25s ease, border-color 0.25s ease;
}
div.search-box:focus-within input {
width: 240px;
padding: 8px 20px;
border-color: #007bff;
}
- 务必统一设
box-sizing: border-box,否则width+padding叠加会超预期尺寸 - 如果父容器宽度受限(如 flex item),优先过渡
flex-grow而非width,避免响应式断裂 - 动画时间超过 0.3s 易被感知卡顿,低于 0.15s 则像没动;0.2–0.25s 是较稳妥区间
IE11 或老安卓 WebView 中图标不消失
:focus-within 在 IE11 完全不支持,部分 Android 4.x WebView 也忽略该伪类,此时图标残留是常态,不是代码写错。
最小代价的兼容方案是加一层轻量 JS 回退:
const searchBox = document.querySelector('.search-box');
const input = searchBox.querySelector('input');
input.addEventListener('focus', () => searchBox.classList.add('focused'));
input.addEventListener('blur', () => searchBox.classList.remove('focused'));
对应 CSS 补一句:
.search-box.focused .search-icon { opacity: 0; transform: scale(0.8); }
- 不用监听整个 document 的 focus/blur,只绑当前 input,避免干扰其他表单
- 不要用
classList.toggle配合autofocus,页面加载时可能误触发 - 如果项目已用 jQuery,别为了这点逻辑引入整包——原生
addEventListener足够
图标消失后焦点管理异常
图标缩小时若用了 transform: scale(0),部分浏览器(如 Safari 16.4)会把该元素视作“不可交互”,导致点击空白处失焦后无法再点图标区域重新聚焦 input。
根本解法是保持图标可点击区域存在,只是视觉隐藏:
- 用
opacity: 0+pointer-events: none替代transform: scale(0)或visibility: hidden - 确保图标父容器没有
overflow: hidden,否则缩放动画裁切会导致视觉残留 - 如果图标是 SVG,检查是否设置了
focusable="false"—— 这会让它抢不到焦点,但也不会影响 input 的聚焦逻辑
过渡动效本身不难,难的是边界情况下的行为一致性。特别是图标作为交互入口又承担视觉提示时,它的显隐逻辑得和焦点状态严格对齐,差一帧或一个 CSS 层叠顺序,用户就会觉得“点了没反应”。











