一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

怎样通过CSS变量实现带交互感的按钮波纹效果?

时间:2026-06-19 09:47:46 编辑:袖梨 来源:一聚教程网

直接用 :active 无法实现真实波纹,因其仅表示布尔状态且不携带点击坐标,导致波纹总从中心触发、iOS Safari 默认禁用、移动端动画易中断;须通过 getBoundingClientRect() 计算相对坐标,用 CSS 变量 --x/--y 配合伪元素 transform: translate(-50%,-50%) 锚定圆心,并加 position: relative、border-radius: 50%、pointer-events: none,再以 JS 控制临时类与 animationend 清理。

为什么直接用 :active 无法实现真实波纹

因为 :active 只是一个布尔状态,不携带坐标信息。你写 button:active { background: radial-gradient(circle at 50% 50%, ...); },所有点击都从按钮正中心开始——用户点左下角,波纹却从正中炸开,交互失真。更麻烦的是,iOS Safari 默认禁用 :active,必须加 * { cursor: pointer; }touch-action: manipulation 才勉强触发,且移动端手指抬起快,动画常被截断。

必须用 getBoundingClientRect() 算坐标,不能用 e.offsetX

e.offsetX 在 IE 完全不支持,在有 transformscale 或 iframe 嵌套的容器里返回值不可靠。真实项目中 90% 的波纹偏移错误都源于没做坐标归一化。

  • 调用 button.getBoundingClientRect() 获取按钮左上角相对于视口的位置
  • 计算相对偏移:const x = e.clientX - rect.leftconst y = e.clientY - rect.top
  • 写入带单位的 CSS 变量:button.style.setProperty('--x', x + 'px'),单位 px 必须显式带上,否则 var(--x)left 中无法解析
  • 每次点击前重置:button.style.setProperty('--x', '0px'),否则连续点击时新波纹从旧位置起始

伪元素怎么读取 --x/--y 并精准锚定

伪元素不能用 attr(data-ripple-x)——Safari 不支持,且不支持单位运算;唯一可靠方式是 CSS 变量 + transform: translate(-50%, -50%) 把圆心拉到点击点。

  • 按钮必须加 relative 类(即 position: relative),否则 ::after 会相对于 body 定位
  • ::afterposition: absolute; top: 0; left: 0;,再写 left: var(--x); top: var(--y); transform: translate(-50%, -50%) scale(0);
  • 漏掉 border-radius: 50% 就是方块扩散,不是波纹
  • 务必加 pointer-events: none,否则波纹层会拦截后续点击

动画触发和清理的关键时机

仅靠 :active 触发不可靠:移动端可能不触发,鼠标抬起过快会导致动画中断,也无法控制多点点击。

立即学习“前端免费学习笔记(深入)”;

  • JS 中添加临时类如 is-rippling,CSS 写 .btn.is-rippling::after { transform: scale(1); opacity: 0; }
  • 监听 animationend 事件移除类,而不是用 setTimeout——浏览器动画帧可能延迟,setTimeout 容易误判
  • 快速连点需节流:if (button.rippling) return; button.rippling = true;,动画结束再置 false
  • 伪元素插入后,第一帧渲染需要等待浏览器合成层就绪,这点常被忽略

热门栏目