水波纹效果需javascript驱动获取点击坐标并动态设置伪元素圆心位置,核心步骤包括:目标元素设position: relative;::after需content、absolute、border-radius: 50%且opacity: 0;动画用transform+opacity避免重排。

点击时水波纹从中心向四周扩散的原理
核心是用 ::after 伪元素画一个透明圆,点击瞬间通过 JavaScript 记录坐标并设置为 transform-origin,再用 transform: scale() 放大它,配合 opacity 淡出实现扩散消散效果。纯 CSS 无法获取点击坐标,所以必须 JS 驱动 —— 这点常被教程忽略,导致“复制代码没反应”。
给按钮加水波纹前必须做的三件事
否则伪元素不显示、定位错乱或动画卡顿:
- 目标元素(如
button)需设position: relative,否则::after的绝对定位会脱离预期位置 -
::after必须设content: ""、position: absolute、border-radius: 50%,且初始opacity: 0 - 动画要用
transform+opacity,避免触发布局重排;scale(0)到scale(4)是常见安全范围,太大易出屏
JS 动态设置圆心坐标的正确写法
关键在把点击事件的 clientX/clientY 转换为相对于按钮左上角的偏移值,再传给 transform-origin:
element.addEventListener('click', (e) => {
const rect = element.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ripple = document.createElement('span');
ripple.className = 'ripple';
ripple.style.left = `${x}px`;
ripple.style.top = `${y}px`;
element.appendChild(ripple);
// 动画结束后移除节点
setTimeout(() => ripple.remove(), 600);
});
注意:不能直接用 e.offsetX/e.offsetY,它们在某些浏览器中对 button 不稳定;getBoundingClientRect() 更可靠。
兼容性与性能容易被忽视的点
水波纹在低配设备上可能掉帧,尤其同时触发多个按钮时:
- 给
::after加will-change: transform, opacity可提前启用 GPU 加速(但别滥用,每个都加反而拖慢) - 移动端需补
touchstart事件,仅监听click会有 300ms 延迟 - IE11 不支持
transform-origin接收百分比以外的值,所以必须用像素值(即上面 JS 中的x/y)
真正难的不是画个圆,而是让每个点击都精准落在用户手指落点上,又不卡、不出界、不残留 DOM 节点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











