css ripple效果最小可行实现是用:active状态+radial-gradient背景遮罩+transform缩放,配合overflow:hidden裁剪;需用button标签并设cursor:pointer或onclick以解决ios safari的:active失效问题,渐变须为circle、0%起始、70%透明终止,并配transition动画。

什么是CSS Ripple效果的最小可行实现
移动端要模拟Android原生Ripple,核心不是“画一个波纹动画”,而是用:active状态 + background渐变遮罩 + transform缩放控制,配合overflow: hidden裁剪。纯CSS方案无需JS监听touch事件,但必须处理iOS Safari的:active失效问题。
为什么直接用:active在iOS上不生效
iOS Safari默认禁用非可点击元素(如div、span)的:active伪类,除非满足以下任一条件:
- 元素有
onclick属性(哪怕内容是void(0)) - 元素设了
cursor: pointer - 元素是原生可交互标签(
button、a、input) - 页面加了
meta name="viewport" content="width=device-width, user-scalable=no"(不推荐,影响体验)
最稳妥的做法是:用button标签替代div,并重置默认样式。例如:
<button class="ripple">点我</button>再通过
appearance: none和border: none去掉原生样式。
如何用radial-gradient做出水波扩散感
关键在于背景渐变的起始半径和结束透明度——不能写死50%,而要用0起始、100%结束,并让颜色从不透明渐变到完全透明:
.ripple:active {
background: radial-gradient(circle, rgba(0,0,0,0.1) 0%, transparent 70%);
transform: scale(0.98);
}
注意三点:
-
circle比ellipse更接近原生Ripple的圆形扩散 - 结束位置用
70%而非100%,避免边缘出现硬边 - 必须搭配
transition: background 0.3s, transform 0.1s,否则动画卡顿
真机测试时容易忽略的兼容性细节
安卓Chrome和iOS Safari对radial-gradient解析略有差异,尤其在高DPR屏幕下:
- iOS 15+需加
-webkit-radial-gradient前缀(尽管现代版本已支持,但老设备仍可能 fallback) - 某些安卓定制ROM(如MIUI)会强制禁用
:active过渡动画,此时需用touchstart/touchend事件手动切换class - 如果父容器有
transform: translateZ(0)或will-change: transform,可能截断Ripple溢出区域,要确保父级overflow: visible
最保险的兜底方案:用button + radial-gradient + pointer-events: auto,不依赖任何JS,但得接受部分低端安卓机动画帧率偏低。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











