按钮点击时涟漪不居中是因为::after伪元素定位基准未对齐点击位置,需用JavaScript计算相对坐标并设置left/top减去半径,配合transform-origin:center、px单位、animationend清理及Safari兼容处理。
根本原因是 ::after 伪元素的定位基准没对齐点击位置,而是默认以按钮左上角为原点。浏览器不会自动把涟漪中心“锚定”到鼠标点,得手动算。
e.clientX 和 e.clientY,再减去按钮 getBoundingClientRect() 的 left/top,得到相对坐标::after 要设 position: absolute,且父按钮必须是 position: relative
left 和 top 时,要减去半径(width/2),否则涟漪圆心会偏右下% 或 vw 定位,必须用 px 动态赋值,否则响应式下错位常见于直接写 transform: scale(0) → scale(1) 却没扩散效果——因为没设 transform-origin,缩放中心默认是元素左上角。
::after 必须显式加 transform-origin: center,否则涟漪从一角炸开transform: scale(0) 而不是 scaleX(0) scaleY(0),后者可能触发硬件加速异常border-radius,涟漪圆角需保持一致,否则边缘穿帮;建议伪元素也设相同 border-radius
will-change: transform,低端安卓 WebView 下可能导致闪屏或卡顿本质是事件未节流 + 伪元素未及时清理。每个点击都新建一个 ::after 实例(实际是 JS 动态加 class 触发),旧动画没结束,新动画又覆盖上去。
timeoutID,触发前先 clearTimeout
animationend 事件,然后移除涟漪 class,不能只靠 CSS animation-fill-mode: forwards
opacity: 0 隐藏残留元素,要真正 remove() 或重置 display: none
touchstart 替代 click,否则有 300ms 延迟,连点更易堆叠Safari 对动态插入的伪元素动画支持不稳定,尤其在 content: '' + animation 组合下,容易跳帧或首次不播。
立即学习“前端免费学习笔记(深入)”;
pointer-events: none,否则可能拦截后续点击animation-timing-function,不能只靠浏览器默认,推荐用 cubic-bezier(0.4, 0, 0.2, 1)
background: radial-gradient 模拟涟漪,Safari 渲染慢且易糊;老老实实用纯色 + opacity 渐变prefers-reduced-motion 的用户,涟漪应被 CSS 媒体查询禁用,否则违反可访问性