outline 不支持动画,应改用 box-shadow 模拟可过渡焦点环;需配合 outline: none、正确声明 :focus/:focus-visible 顺序,并在键盘、鼠标、真机触摸三场景验证。

focus-visible 本身不支持 outline 动画
浏览器对 outline 属性的实现是“绘制即生效”,它不参与 CSS transition 或 animation 的属性插值。直接写 outline: 2px solid #0066cc; + transition: outline 0.3s 不会动,只会突变。这是所有主流浏览器(包括 Safari 16+、Chrome 110+)的统一行为,不是 bug,是规范限制。
用 box-shadow 模拟可动画的焦点环
真正能平滑过渡的是 box-shadow——它支持颜色、大小、模糊度的逐帧插值,视觉上和轮廓环几乎无差别,且兼容性更好(IE11 都支持,只要不用 inset)。
- 把原本想加在
outline上的效果,改到box-shadow:比如box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.5); - 必须显式声明
outline: none或outline: 0,否则原生 outline 会和 shadow 叠在一起,显得粗重 - 若需 offset 效果(比如轮廓离边框 2px),用
box-shadow: 0 0 0 2px #0066cc, 0 0 0 4px rgba(0, 102, 204, 0.3);模拟双层 - 过渡要锁定属性:
transition: box-shadow 0.25s ease-in-out;,别写成transition: all,避免意外触发其他动画
:focus-visible 和 :focus 的声明顺序不能错
动画效果只在键盘导航时出现,但鼠标点击后也得有基础反馈,否则用户会怀疑按钮没响应。所以样式链必须是:
input:focus { outline: none; transition: box-shadow 0.25s ease-in-out; }input:focus:not(:focus-visible) { box-shadow: none; }input:focus-visible { box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.6); }
注意三点:
-
:focus必须在最前,提供兜底过渡能力;旧版 Safari 忽略:focus-visible时,仍能靠:focus触发 box-shadow -
:focus:not(:focus-visible)要紧接其后,确保鼠标点击时不显示任何焦点环 -
:focus-visible最后定义,且必须带具体box-shadow值——空规则或box-shadow: 0不会清除前面的过渡起始态
真机测试时容易漏掉的两个细节
iOS Safari 在触控点击后通常不触发 :focus-visible,但会触发 :focus;而键盘 Tab 导航才真正走 :focus-visible 路径。这意味着:
- 别只在桌面 Chrome 测——用真机连 Safari 开发者工具,检查
input:focus-visible是否被实际匹配(可在 DevTools 的 Styles 面板里手动勾选伪类) - 如果动画在键盘下不动,大概率是
transition没写在:focus规则里,而是只写在:focus-visible中——后者不支持 transition 声明,浏览器直接忽略
真正难调的不是动画本身,而是让 :focus-visible 在正确时机被识别,又不让鼠标用户失去反馈。这需要三重验证:键盘 Tab、鼠标点击、真机触摸,缺一不可。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











