波纹效果需四要素齐备:触发元素必须设position: relative;伪元素须声明pointer-events: none;用transform: scale()替代width/height动画;js动态设置left/top并清理旧波纹。

点击区域必须有相对定位才能让波纹居中
波纹效果本质是用 ::after 伪元素画一个从点击点扩散的圆,而“点击点”需要通过 JavaScript 获取坐标并设为 left 和 top。但这些值是相对于**最近的定位上下文(positioned ancestor)**计算的。如果父容器是默认的 static,那坐标会回退到 body,导致波纹偏移。
所以必须给触发元素加 position: relative,否则无论 JS 算得多准,波纹都对不齐。
- 不要只在 CSS 里写动画,忘了加
position: relative - 如果按钮是
display: flex子项,父容器没定位,也要单独给按钮加relative - 避免用
position: absolute替代 —— 那会破坏文档流,影响布局
伪元素需设置 pointer-events: none
波纹是盖在按钮上的 ::after,如果不关掉它的鼠标事件,连续点击时可能拦截第二次点击,尤其在动画还没结束、新波纹还没生成时,用户会感觉“点不动”。
这个样式必须显式声明,不能依赖默认值,因为某些重置 CSS(如 normalize.css)或框架(如 Tailwind 的 pointer-events-auto)可能覆盖它。
- 在波纹伪元素规则里务必加上
pointer-events: none - 别写成
pointer-events: auto或漏掉这一行 - 如果用了
z-index控制层级,确保它不会意外挡住下层可点击区域
transform + scale 比 width/height 更流畅
用 width 和 height 动画波纹,浏览器要频繁重排(reflow),尤其在低端设备上容易卡顿;而 transform: scale() 只触发重绘(repaint),GPU 加速更稳。
实现时把伪元素初始设为 scale(0),动画终点设为 scale(3)(足够覆盖常见按钮尺寸),再配合 transform-origin 定义缩放中心。
- 动画关键帧里只改
transform,不要同时动width/height -
transform-origin: center是必须的,否则缩放中心会偏移到左上角 - 如果按钮是圆角矩形,
border-radius: 50%要加在伪元素上,而不是靠宽高比模拟
JavaScript 必须动态设置 left/top 并清理旧波纹
CSS 只负责动画,JS 才决定“从哪开始”。每次点击都要读取 clientX/clientY 相对于按钮左上角的偏移,并赋给伪元素的 left 和 top。但伪元素无法直接用 JS 设置样式,所以得用内联 style 写在元素本身,再由 CSS 变量或属性选择器承接 —— 最简方案是用 style.setProperty 更新自定义属性。
另外,多次快速点击会产生多个未完成的波纹,必须在动画结束时移除对应伪元素,否则 DOM 节点堆积,内存泄漏。
- 监听
click,用getBoundingClientRect()算相对坐标 - 用
element.style.setProperty('--x', x + 'px')传入 CSS 变量 - 在
animationend事件里移除已添加的波纹类,或清空 style 属性 - 别用
setTimeout模拟动画时长 —— 不同设备帧率不同,容易错位
position: relative 和 pointer-events: none,漏掉任一个,用户第一眼就会觉得“不对劲”。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











