纯CSS3无法实现“点哪从哪炸开”的水波纹效果,必须用JS获取点击坐标并动态设置伪元素位置;:active+transition因状态瞬时、无法读取坐标、Safari兼容性差等原因不可行。

纯 CSS3 无法做出“点哪、从哪炸开”的水波纹点击扩散效果——必须用 JavaScript 获取坐标并动态设置伪元素位置,否则所有波纹都从左上角或中心固定起始,交互反馈完全失真。
为什么 :active + transition 不行
因为 :active 是瞬时状态,松手就消失,撑不起「出现→扩散→淡出」三阶段动画;transition 只能做两态切换(比如 scale(0) → scale(1)),且无法读取 e.clientX。浏览器不提供点击坐标的 CSS 变量,写死 left: 50% 就只能从中心炸开。
- iOS Safari 默认禁用
:active,需加touch-action: manipulation或cursor: pointer才勉强触发 - 快速连点时,多个
:active状态重叠,JS 无法清理旧动画,DOM 和渲染层都会堆积残留 - 即使强制启用,
transition也无法在:active中动态设置left/top,坐标还是写死的
必须用 ::after + getBoundingClientRect() 算相对坐标
按钮要设 position: relative,否则 ::after 的 absolute 定位会相对于 body 偏移;伪元素本身要设 content: ""、border-radius: 50%、z-index: -1(压在文字下方)、pointer-events: none(避免拦截后续点击)。
- 用
const rect = button.getBoundingClientRect()拿到按钮在视口中的位置 - 计算相对偏移:
const x = e.clientX - rect.left,const y = e.clientY - rect.top(移动端用e.touches[0].clientX) - 注入方式推荐:
ripple.style.left = x + "px"+ripple.style.top = y + "px"+transform: translate(-50%, -50%),别用attr()(Safari 不支持) - 每次点击前清空旧值:
button.style.removeProperty('--x'),否则新波纹从上一次位置起始
iOS Safari 渲染异常的三个硬性修复点
Safari(尤其 15.4 以下)对 ::after + scale() 有合成 bug:波纹卡顿、闪烁、甚至不触发。这不是加 -webkit- 能解决的。
- 给
::after加will-change: transform,强制开启 GPU 加速 - 圆心定位必须用
transform: translate(x, y),别混用top/left—— Safari 对混合定位的合成逻辑不稳定 - 按钮本身有
border-radius,父级必须加overflow: hidden,否则 Safari 会裁切动画轨迹 - 动画结束必须监听
animationend并移除伪元素或重置opacity和transform,否则残留 DOM 会拖慢后续点击响应
最易被忽略的是坐标换算这一步:漏掉 getBoundingClientRect() 直接用 clientX,波纹就会飞出屏幕;其次是 pointer-events: none 忘加,点几次后按钮就“变迟钝”,用户根本不知道问题出在哪。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











