点击涟漪本质是用 radial-gradient 实现的径向渐变动态扩展效果,核心是将点击坐标转为百分比css变量(--x/--y),配合 background-size 控制半径(--r)缩放,并仅对可动画属性如 background-size 和 opacity 做 transition。

点击涟漪的本质是径向渐变的动态扩展
涟漪效果不是靠动画位移或遮罩实现的,而是用 radial-gradient 在元素背景上画一个从点击点出发、半径不断增大的圆,并通过 background-size 控制其缩放范围。关键在于:必须把点击坐标转为百分比值(x%/y%),否则渐变中心无法精准落在鼠标位置。
- 使用
getBoundingClientRect()获取元素相对视口的位置,再减去元素自身offsetLeft/offsetTop得到相对于目标元素的偏移 - 将像素偏移除以元素宽高,乘以 100 得到
--x和--y的 CSS 变量值(注意单位是无单位数字,CSS 中需拼接%) - 渐变色停靠点建议设为
rgba(255,255,255,0.3) 0%, transparent 70%,太长的透明过渡会让扩散显得“虚”
如何用 CSS 变量驱动渐变中心与大小
CSS 本身不能读取鼠标坐标,所以必须由 JS 注入变量;但后续动画和颜色控制可以完全交给 CSS。重点是定义好三组变量:--x、--y 控制中心,--r 控制半径,--c 控制颜色(可选)。
- JS 设置变量时,推荐用
element.style.setProperty('--x', xPercent),避免污染全局:root - CSS 中写渐变要显式拼接单位:
background: radial-gradient(circle at var(--x) var(--y), var(--c, rgba(0,0,0,0.1)) 0%, transparent var(--r, 200px)) -
--r初始设为0,动画中过渡到足够覆盖元素对角线的值(例如calc(1.5 * sqrt((100vw * 100vw) + (100vh * 100vh)))不实用,直接用300px或max(300px, 150%)更稳)
为什么 transition 会失效?检查这三点
最常见的“点了没反应”,90% 是因为 transition 没生效——它只响应可动画的 CSS 属性,而 background-image 本身不可过渡。必须靠间接方式触发。
- 不要对
background整体加transition,而是只过渡background-size和opacity(如果用了透明度) - 确保 JS 中每次点击都重置
--r为0,再在下一轮 microtask 中设为终值,否则 CSS 动画不会重新触发 - 如果用了
will-change: background,反而可能禁用硬件加速,去掉它;真正需要的是transform: translateZ(0)或backface-visibility: hidden强制图层提升
兼容性与性能陷阱:Safari 和高频点击
Safari 对 radial-gradient 中变量拼接的支持较弱,尤其在 at var(--x) var(--y) 这种写法上容易渲染错位;同时快速连续点击会导致多个涟漪叠加、内存泄漏或卡顿。
- 绕过 Safari bug:改用
background-position: calc(var(--x) * 1px) calc(var(--y) * 1px)+ 固定大渐变图(background-size: 400px 400px),靠位移模拟中心变化 - 防重复点击:用
pointer-events: none在涟漪动画期间临时禁用元素,动画结束再恢复;或者用setTimeout+ 标志位控制 - 不用
requestAnimationFrame手动控制帧率——CSStransition自带优化,强行接管反而增加 JS 负担
最易被忽略的一点:涟漪颜色若依赖主题色,别在 JS 里硬编码 rgb() 字符串,而是让组件提前定义好 --ripple-color,CSS 直接读取,换肤时无需改逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











