呼吸灯效果应优先用 opacity 实现明暗循环,配 ease-in-out 缓动和 infinite 循环;避免 background-color 插值、brightness(0) 及漏写 infinite;需兼顾 prefers-reduced-motion 和动效协调。

用 @keyframes 定义明暗循环动画
呼吸灯效果本质是亮度(或透明度)在两个值之间平滑往复变化,CSS 里最直接的方式就是用 @keyframes 控制 opacity 或 filter: brightness()。别用 background-color 插值——颜色空间非线性,明暗过渡会发灰或突兀。
推荐优先用 opacity:兼容性好、性能高、行为确定。如果需要更精细的明暗控制(比如保持色相不变只调亮度),再考虑 brightness(),但注意 Safari 对 brightness(0) 渲染异常,别设到 0。
示例关键帧:
@keyframes breathe {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
这里用 0%, 100% 和 50% 构成对称缓动,避免停顿感。
animation 属性必须配 infinite 和缓动函数
只写 animation: breathe 3s; 会导致动画播完就停,失去“呼吸”连续性。必须加 infinite;同时默认 ease 缓动会让亮起/变暗过程不自然——呼吸感来自缓慢启停、中间加速,ease-in-out 更贴切。
完整声明建议这样写:
.breathing {
animation: breathe 3s ease-in-out infinite;
}
常见错误:
- 漏掉
infinite,动画只执行一次 - 用
linear,导致节奏像机械闪烁,不是呼吸 - 周期设太短(如
1s),人眼感知为频闪,易疲劳;2.5s–4s 较稳妥
避免布局抖动:给元素预留空间或用 transform 替代尺寸变化
如果用 scale() 模拟呼吸(比如放大缩小),元素尺寸变化可能触发重排,尤其在 Flex/Grid 容器中会扰动其他子项。而 opacity 和 brightness() 是合成属性,GPU 可加速,不影响布局。
若必须用尺寸变化(比如灯泡图标需轻微胀缩),务必提前固定容器宽高,或改用 transform: scale()(它不触发重排):
@keyframes breathe-scale {
0%, 100% { transform: scale(0.95); }
50% { transform: scale(1.05); }
}
注意:不要同时 animating width/height 和 transform,浏览器可能降级到 CPU 渲染。
移动端要注意 prefers-reduced-motion
不少用户开启了系统“减少动画”偏好,硬上呼吸灯可能引发眩晕。用媒体查询关掉动画是最小成本的可访问性处理:
@media (prefers-reduced-motion: reduce) {
.breathing {
animation: none;
opacity: 1; /* 回退为常亮 */
}
}
别指望 JS 检测后再加 class——CSS 媒体查询是原生、即时、可靠的。忽略这点,上线后可能被无障碍审计打低分。
真正难的是让呼吸节奏和 UI 其他动效(比如 loading 转圈、下拉展开)在时长和缓动上协调,否则页面像在不同节拍上乱跳。这得靠设计系统统一定义动效 token,不是单个 CSS 能解决的。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











