:focus 上直接设 transition 无效,因焦点是布尔突变;须在默认态声明属性初始值(如 border-color: #ccc),:focus 中仅修改该值,transition 才生效。

focus 状态本身不触发 transition
直接对 :focus 设置 transition 通常无效,因为焦点切换是布尔状态突变(有/无),没有中间过渡值。浏览器不会自动为 outline、border-color 等属性的“出现”或“消失”补帧——除非这些属性在非 focus 状态下已声明初始值。
- 必须为同一属性在
:not(:focus)或默认状态中定义起始值(如border-color: #ccc) - 只在
:focus中修改该属性(如border-color: #007bff),transition 才能生效 - 常见失效场景:仅在
:focus写outline: 2px solid blue,但默认态未设outline: none或同类型值
推荐用 border-color + outline-offset 实现平滑聚焦边框
视觉上最自然的过渡是边框颜色渐变 + 轮廓微移,避免生硬闪入。需同时控制 border 和 outline,并确保两者不冲突。
input, select, textarea {
border: 2px solid #ddd;
outline: none;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
input:focus, select:focus, textarea:focus {
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
-
outline: none是必需的,否则原生 outline 会覆盖 transition 效果 - 用
box-shadow模拟 focus ring,比outline更易控制圆角和透明度 - 不要对
outline本身加 transition —— 它不支持平滑动画
textarea 和 contenteditable 元素的 focus 过渡要额外处理 resize
当 textarea 启用 resize,拖拽改变尺寸时可能意外触发 focus 状态重置,导致过渡中断。需确保 transition 属性不包含 width 或 height。
- 避免写
transition: all 0.3s—— 这会让 resize 动画与 focus 动画耦合,行为不可控 - 显式列出需过渡的属性:
transition: border-color 0.2s, box-shadow 0.2s - 若需支持暗色模式,
border-color应使用color-scheme: light dark兼容的系统色或 CSS 变量
移动端 Safari 的 focus 触发延迟问题
iOS Safari 默认延迟约 300ms 才触发 :focus,导致 transition 看起来卡顿。这不是 CSS 问题,而是浏览器策略。
立即学习“前端免费学习笔记(深入)”;
- 可添加
inputmode属性提前唤起键盘(如inputmode="text"),有助于更快进入 focus 状态 - 更可靠的方式是监听
focusin事件,用 JS 添加临时 class 并触发 transition(绕过伪类限制) - 注意:Safari 对
:focus-within支持良好,但表单元素自身仍需手动管理 focus 流程










