波纹效果必须用::after伪元素配合transform:scale()实现,核心是创建绝对定位圆形伪元素,初始scale(0),点击时scale(3)并opacity从1减至0;需javascript动态计算点击坐标设置left/top,减去半径确保圆心居中;务必添加pointer-events:none防拦截点击。

波纹效果必须用 ::after 伪元素 + transform: scale()
直接在按钮上加 background 动画或用 border-radius 模拟扩散,根本做不到中心发散、边缘渐隐的真实波纹。核心是:用 ::after 创建一个绝对定位的圆形伪元素,初始 scale(0),点击时通过 transform: scale(3)(或更大)撑开,并配合 opacity 从 1 降到 0 实现淡出。
关键点:
- 伪元素必须设
content: ""、position: absolute、border-radius: 50%,且父容器(按钮)需为position: relative - 不能靠
width/height动画控制大小——响应式下会失真;transform: scale()才能保持圆心居中、适配任意尺寸 -
transition必须写在伪元素上,且只过渡transform和opacity,否则触发重排影响性能
如何让波纹始终从点击位置中心扩散?
靠纯 CSS 无法获取点击坐标,必须用 JavaScript 动态计算并设置 left 和 top。监听 click 事件,用 event.clientX - button.getBoundingClientRect().left 算出相对按钮左上角的 X 坐标,同理算 Y。
实操要点:
- 每次点击前先清除已存在的波纹伪元素(避免多个叠加),可用
element.querySelectorAll('.ripple')或统一用一个::after并重置left/top - 设置
left和top时要减去半径(即width/2),否则圆心会偏右下 - 推荐给伪元素加 class 如
ripple,方便用 JS 控制生命周期,而不是全靠 CSS::after静态定义
pointer-events: none 必须加在波纹元素上
否则波纹层会挡住后续点击——尤其快速连点时,第二个点击可能被上一个还没消失的波纹截获,导致按钮无响应。
常见错误:
- 忘记设
pointer-events: none,点一次后按钮“变迟钝” - 把
pointer-events: none错加在按钮上,结果整个按钮不可点 - 用
z-index乱调层级,其实只要波纹在按钮上方、且pointer-events: none就够了
移动端点击延迟和 :active 伪类不生效怎么办?
CSS 的 :active 在 iOS Safari 上默认有 300ms 延迟,且部分安卓浏览器对伪类支持不稳定,所以不能依赖它触发波纹。必须用 touchstart + mousedown 双事件监听,且在 touchstart 中立刻触发波纹创建。
兼容处理建议:
- 同时监听
mousedown和touchstart,但注意touchstart会触发mousedown,加event.preventDefault()防止重复 - 移动端需加
meta viewport:<meta name="viewport" content="width=device-width, initial-scale=1">,否则getBoundingClientRect()返回值不准 - 不要用
:focus-within或:hover模拟点击态——它们不是用户真实交互信号
波纹效果真正难的不是动画本身,而是坐标计算精度、事件时机控制、以及移动端 touch/mouse 事件的交织处理。漏掉任何一个,都会出现偏移、卡顿或点不动。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











