用 :active 配合 ::after 伪元素实现波纹效果最轻量,通过 width/height + transform: translate(-50%,-50%) 锚定点击中心,transition 控制展开,兼顾兼容性与性能,移动端需 JS 补齐坐标。

点击时颜色从中心扩散的波纹效果怎么写
用 :active 配合 radial-gradient + animation 是最轻量、兼容性最好的方案,不需要 JS,也不依赖伪元素叠加。关键不是“做动画”,而是让渐变色的 radius 和 opacity 同步变化,否则会看到生硬的色块跳变。
- 必须用
background-image而非background-color,因为只有渐变支持background-size动画控制半径 -
radial-gradient(circle, #007bff 0%, transparent 70%)中的70%是初始透明位置,它要和background-size的终点值匹配,否则动画拉伸失真 - Chrome/Firefox 支持
background-size: 0 0→background-size: 200% 200%动画,但 Safari 15.4+ 才稳定支持,旧版需 fallback 到transform: scale()
button {
position: relative;
overflow: hidden;
}
button::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: radial-gradient(circle, rgba(0,123,255,0.2) 0%, transparent 70%);
transform: translate(-50%, -50%);
transition: width 0.3s, height 0.3s;
}
button:active::after {
width: 200px;
height: 200px;
}
为什么用 ::after 而不用 ::before 或直接改 background
因为 ::before 默认在内容层之下,而按钮文字常带 z-index 或 position,容易被遮住;直接改元素自身 background 会覆盖原有背景(比如图片、渐变),破坏设计。用 ::after 可精准叠在最上层,且不影响原样式结构。
-
::after必须设position: absolute+top/left: 50%+transform: translate(-50%, -50%),否则中心点不随点击位置变化 - 如果按钮宽高不固定(如文字长度不定),
width/height改用max-width/max-height并配合animation更稳妥 - IE11 不支持
radial-gradient动画,若需兼容,得用filter: blur()模拟,但性能差、边缘发虚
animation 里写 background-size 还是控制 width/height
优先用 width/height。虽然 background-size 看似更“语义化”,但它的动画在部分安卓 WebView(如 UC 13.x)中会卡顿,且无法响应点击坐标(只能居中)。而 width/height 配合 transform: translate 能精准锚定点击点,且硬件加速更稳。
- 别写
animation: ripple 0.4s ease-out然后在@keyframes里动background-size—— Safari iOS 15.6 有渲染撕裂 - 真实项目中,建议用
transition替代animation:触发快、取消及时(比如按住不放再移开,波纹能自然中断) - 如果真要用
animation,必须加animation-fill-mode: forwards,否则动画结束瞬间波纹消失太突兀
移动端点击偏移、多点触控失效怎么办
纯 CSS 波纹在移动端有两个硬伤:一是 :active 在 iOS 上延迟约 300ms,二是不响应 touchstart 坐标。这时候必须用 JS 补齐点击位置,但 CSS 层仍只负责渲染。
立即学习“前端免费学习笔记(深入)”;
- 监听
touchstart,拿到touches[0].clientX/Y,动态设置::after的left/top值(注意减去父容器 offset) - 别用
pointer-events: none给::after,否则 iOS 会忽略后续 touch 事件 - 双指点击时,只取第一个触点,避免多个波纹重叠;手指抬起后,用
setTimeout清除::after样式,防止残留
真正难的不是写出来,是让波纹在各种屏幕缩放、滚动中始终对准手指落点 —— 这需要把 clientX/Y 换算成相对于按钮左上角的相对坐标,而且得在 touchstart 瞬间完成,不能等 layout 回流。










