直接 transition: border 无效,因 border 是复合属性且初始为 none 会触发重排;应改用 box-shadow 实现光晕,并配合 :focus-visible 和 focus-within 确保可访问性与动效稳定。

为什么直接 transition: border 不会出光晕
因为 border 是复合属性,浏览器无法对 border-style、border-width、border-color 同时插值;尤其当初始值是 border: none,聚焦时突然变成 2px solid #007bff,会触发重排(reflow),动画卡顿甚至跳帧。Safari 和旧版 Chrome 更容易直接忽略这类过渡。
- 别写
transition: border 0.3s—— 这行基本无效 - 初始态建议统一用
border: 1px solid transparent,避免重排 - 真正要动的不是边框本身,而是视觉上“包裹”它的光感层
box-shadow 是实现渐变光晕最稳的方案
用两层 box-shadow 模拟「内收→扩散→柔化」的渐变光晕,比 outline 或 border 更可控、性能更好,且 iOS/Android 兼容性扎实。
- 基础态:
box-shadow: 0 0 0 0 rgba(0, 120, 255, 0) - 聚焦态:
box-shadow: 0 0 6px 2px rgba(0, 120, 255, 0.25), 0 0 12px rgba(0, 120, 255, 0.1) - 必须配
transition: box-shadow 0.25s ease,写在非伪类规则里(如input { ... }) - 深色背景慎用低透明度,推荐
rgba(100, 180, 255, 0.25)替代rgba(0, 120, 255, 0.1)
:focus-visible 才是移动端光晕生效的关键
iOS Safari 在触屏点击后常不触发 :focus,但 :focus-visible 能准确识别键盘导航和辅助技术场景,同时兼容现代触控逻辑——这是真机测试不亮光晕时最该检查的一环。
- 写法必须回退兼容:
input:focus, input:focus-visible - 不能只写
input:focus-visible,否则旧版 Safari 完全失效 - 真机验证技巧:加一句
input:focus-visible { outline: 2px solid red; },红框出现才说明状态被识别 - 别依赖
-webkit-focus-ring-color,它只影响 outline,对box-shadow无作用
伪元素流光需要父容器 + focus-within
如果要实现「边框流光」这种动态效果(比如光条循环滑动),input 自身不支持 ::before/::after,必须靠外层容器承载伪元素,并用 :focus-within 触发动画。
立即学习“前端免费学习笔记(深入)”;
- HTML 结构必须带包裹层:
<div class="input-wrapper"><input></div> - 容器需设
position: relative,伪元素才能定位 - CSS 写法:
.input-wrapper:focus-within::before { animation: flow 3s linear infinite; } - 注意
display: contents会让:focus-within失效,别用在包裹层
tab 切入时 :focus-visible 才是语义正确的触发点,而 outline: none 后没补 box-shadow 就等于砍掉无障碍路径。


















