点击波纹效果的核心原理是用:after伪元素配合transform:scale()动画模拟扩散效果,需JS获取点击坐标并写入CSS变量,容器设position:relative且overflow:hidden,伪元素设transform-origin:center center。

点击波纹效果的核心原理是什么
波纹不是靠 JS 画圆,而是用 :after 伪元素 + transform: scale() 动画模拟「从点击点向外扩散」的视觉错觉。关键在于:波纹必须以点击位置为圆心、动态设置 left 和 top,且容器需设 position: relative,否则伪元素会脱标乱飘。
如何用纯 CSS 定位到鼠标点击坐标
CSS 本身不能读取点击坐标,所以必须靠 JS 获取并写入自定义属性。这是最容易卡住的地方——很多人想纯 CSS 实现,结果发现波纹总在左上角炸开。
- 给目标元素绑定
click事件,用event.clientX和event.clientY减去元素getBoundingClientRect()的偏移,算出相对于容器的x/y - 把结果写进
style.setProperty('--x', x + 'px')和--y,CSS 里用left: var(--x)、top: var(--y) - 务必在每次点击前重置伪元素的
scale,否则第二次点击会从上次结束状态继续动画
示例关键片段:
button {
position: relative;
overflow: hidden;
}
button::after {
content: '';
position: absolute;
width: 10px; height: 10px;
background: rgba(0,0,0,0.2);
border-radius: 100%;
transform: scale(0);
transform-origin: center center;
left: var(--x, 50%);
top: var(--y, 50%);
transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}
button:focus::after { animation: ripple 0.4s ease-out; }
为什么波纹经常“只闪一下”或“不居中”
两个高频原因:一是没设 overflow: hidden,波纹撑大容器后被截断;二是伪元素 transform-origin 没锁定在中心,导致缩放时偏移。
-
transform-origin必须显式写成center center,不能依赖默认值(不同浏览器可能不同) - 如果按钮有圆角(
border-radius),波纹圆角要同步,否则边缘露白,可加border-radius: inherit - 移动端要注意
click事件延迟,建议用pointerdown替代,且加touch-action: none防止滚动冲突
兼容性与性能怎么平衡
transform 和 opacity 动画是 GPU 加速的,但 left/top 是 layout 触发属性,频繁写入会掉帧。所以必须避免每帧都 JS 更新坐标。
- 只在
pointerdown时计算一次坐标并写入--x/--y,动画全程由 CSS 控制 - IE 不支持 CSS 自定义属性,如需兼容,得回退到 JS 创建真实
元素(但已非常规需求) - 波纹颜色建议用
rgba()而非hsla(),部分旧版 Safari 对后者渲染异常
真正难的不是写出来,是让波纹在各种尺寸按钮、不同缩放比例、高 DPR 屏幕下都不偏、不糊、不卡——这些细节全靠反复测点击位置和 getBoundingClientRect() 的精度。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











