最近业余时间在探索 claude code 的使用,用了一个一键转换液态水滴效果的 promot,感觉还不错,距离 iOS 的差远了,但是能用。分享一波,大家需要自取。
任务:实现简约清新风格的液态水滴效果
目标
为我的 Web 项目添加液态水滴交互效果,采用简约清新的视觉风格,使用轻量级 CSS 动画和最小化 JavaScript 实现。要求完美融入现有设计,保持高性能。
效果需求清单
请实现以下 4 个核心效果:
1. 列表项/卡片的液态扩散效果
应用元素:
- 列表项(
li、.list-item、.card等) - 可交互的卡片组件
效果描述:
- 鼠标悬停时,从元素中心产生双层液态波纹向外扩散
- 第一层(快速波纹):科技蓝色,1.2 秒扩散到元素的 300% 大小
- 第二层(慢速波纹):淡绿色,1.5 秒扩散到元素的 250% 大小,延迟 0.2 秒启动
- 活跃/选中状态的元素:持续液态脉冲效果(3 秒循环)
技术要求:
- 使用
::before和::after伪元素实现双层波纹 - 使用
radial-gradient径向渐变模拟液态扩散 - 波纹从透明度 0 → 1 → 0 变化,同时缩放从 0.8 → 1.2
- 父元素需要
position: relative和overflow: hidden - 确保内容在伪元素之上(
z-index: 1)
色彩参考:
/* 快速波纹 - 科技蓝 */
background: radial-gradient(circle, rgba(0, 234, 255, 0.4) 0%, transparent 70%);
/* 慢速波纹 - 淡绿 */
background: radial-gradient(circle, rgba(168, 239, 133, 0.3) 0%, transparent 70%);
2. 按钮的液态波纹效果
应用元素:
- 所有按钮元素(
button、.btn、.button等)
效果描述:
- 点击效果: 从精确的点击位置产生白色波纹向外扩散(0.5 秒)
- 悬停效果: 产生持续的液态光晕效果(2 秒循环)
技术要求:
CSS 部分:
- 使用
::before伪元素实现点击波纹 - 使用
::after伪元素实现悬停光晕 - 波纹起点通过 CSS 自定义属性控制:
--ripple-x和--ripple-y - 添加
.ripple-active类时触发波纹动画
JavaScript 部分:
// 为按钮添加波纹效果
function addLiquidRippleEffect() {
const buttons = document.querySelectorAll('button, .btn, .button');
buttons.forEach(button => {
button.addEventListener('click', function(e) {
// 计算点击位置
const rect = this.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// 设置波纹起点
this.style.setProperty('--ripple-x', `${x}px`);
this.style.setProperty('--ripple-y', `${y}px`);
// 触发波纹动画
this.classList.remove('ripple-active');
requestAnimationFrame(() => {
this.classList.add('ripple-active');
setTimeout(() => this.classList.remove('ripple-active'), 500);
});
});
});
}
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', addLiquidRippleEffect);
色彩参考:
/* 点击波纹 - 白色 */
background: radial-gradient(circle, rgba(255, 255, 255, 0.6) 0%, transparent 70%);
/* 悬停光晕 - 科技蓝 */
background: radial-gradient(circle, rgba(0, 234, 255, 0.3) 0%, transparent 60%);
3. 背景装饰液态水滴
应用元素:
- 主容器(
.container、.wrapper、main等) - 侧边栏、导航栏等大面积区域
效果描述:
- 在容器背景中添加 2 个装饰性水滴,缓慢浮动
- 大水滴:科技蓝色,120px × 120px,15 秒循环
- 中水滴:淡绿色,80px × 80px,18 秒循环
- 水滴形状动态变化(border-radius 动画)+ 位移 + 旋转
技术要求:
- 使用容器的
::before和::after伪元素 - 父元素需要
position: relative - 水滴设置
z-index: -1确保在内容后方 - 使用
filter: blur()增强液态感(6-8px) - 透明度设置为 0.6-0.7,避免遮挡内容
动画路径示例:
@keyframes liquid-float {
0%, 100% {
transform: translate(0, 0) rotate(0deg);
border-radius: 45% 55% 50% 50% / 55% 45% 55% 45%;
}
25% {
transform: translate(15px, -20px) rotate(5deg);
border-radius: 50% 50% 45% 55% / 50% 50% 50% 50%;
}
50% {
transform: translate(0, -35px) rotate(0deg);
border-radius: 55% 45% 50% 50% / 45% 55% 45% 55%;
}
75% {
transform: translate(-15px, -20px) rotate(-5deg);
border-radius: 50% 50% 55% 45% / 55% 45% 50% 50%;
}
}
色彩参考:
/* 大水滴 - 科技蓝 */
background: radial-gradient(ellipse at 30% 30%,
rgba(0, 234, 255, 0.15) 0%,
rgba(0, 234, 255, 0.08) 50%,
transparent 80%);
/* 中水滴 - 淡绿 */
background: radial-gradient(ellipse at 40% 40%,
rgba(168, 239, 133, 0.12) 0%,
rgba(168, 239, 133, 0.06) 50%,
transparent 80%);
4. 元素形状改造(水滴形状)
应用元素:
- 所有需要液态效果的元素(列表项、按钮、卡片等)
效果描述:
- 将标准圆角改为水滴形状(上部较圆润,下部略尖)
- 悬停时形状轻微变化
- 选中/活跃状态持续形状脉冲动画
技术要求:
- 使用复杂的
border-radius语法实现水滴形状 - 语法格式:
border-radius: 水平半径 / 垂直半径 - 每个方向 4 个值:
上左 上右 下右 下左
形状参数参考:
/* 小元素(按钮) */
border-radius: 15px 15px 18px 18px / 15px 15px 20px 20px;
/* 中等元素(列表项) */
border-radius: 20px 20px 25px 25px / 20px 20px 30px 30px;
/* 悬停时 */
border-radius: 25px 25px 30px 30px / 25px 25px 35px 35px;
形变动画示例:
@keyframes droplet-morph {
0%, 100% {
border-radius: 22px 22px 26px 26px / 22px 22px 30px 30px;
}
25% {
border-radius: 24px 20px 28px 24px / 24px 20px 32px 28px;
}
50% {
border-radius: 20px 24px 24px 28px / 20px 24px 28px 32px;
}
75% {
border-radius: 24px 22px 26px 26px / 24px 22px 30px 30px;
}
}
/* 应用到悬停状态 */
.element:hover {
animation: droplet-morph 1.5s ease-in-out infinite;
}
性能优化要求
请确保实现以下性能优化措施:
1. GPU 硬件加速
/* 对所有动画伪元素应用 */
.element::before,
.element::after {
transform: translateZ(0);
backface-visibility: hidden;
will-change: transform, opacity;
}
2. 渲染范围限制
/* 对有液态效果的元素应用 */
.element {
contain: layout style paint;
}
3. 低性能设备降级
/* 响应用户系统偏好 */
@media (prefers-reduced-motion: reduce) {
.element::before,
.element::after {
animation: none !important;
transition: none !important;
}
}
动画时序规范
请使用以下标准时序:
| 效果类型 | 持续时间 | 缓动函数 | 循环 |
| ------------ | ----------- | -------- |
| 快速波纹扩散 | 1.2s | ease-out | infinite |
| 慢速波纹扩散 | 1.5s | ease-out | infinite |
| 点击波纹 | 0.5s | ease-out | once |
| 悬停光晕 | 2s | ease-in-out | infinite |
| 液态脉冲 | 3s | ease-in-out | infinite |
| 水滴浮动 | 15-18s | ease-in-out | infinite |
| 形状形变 | 1.5s | ease-in-out | infinite |
推荐缓动函数:
/* 自然流动感 */
transition: all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
/* 柔和渐入渐出 */
animation: xxx ease-in-out infinite;
色彩方案建议
如果我的项目有现有配色,请根据以下规则调整:
主液态色(快速波纹)
-
默认:
rgba(0, 234, 255, 0.4)- 科技蓝 - 替换规则: 使用项目主色,透明度 0.3-0.5
辅助液态色(慢速波纹)
-
默认:
rgba(168, 239, 133, 0.3)- 淡绿 - 替换规则: 使用项目辅助色或主色的邻近色,透明度 0.2-0.4
装饰水滴
- 默认: 主色和辅助色,透明度 0.1-0.15
- 替换规则: 使用更低透明度的项目配色
点击波纹
-
默认:
rgba(255, 255, 255, 0.6)- 白色 - 替换规则: 深色主题用白色,浅色主题用深色或主色
实现步骤
请按照以下步骤实施:
第一步:准备工作
- 识别项目中需要添加液态效果的元素(列表项、按钮、容器等)
- 确认项目的主色调和辅助色
- 检查现有 CSS 是否有冲突的
::before/::after使用
第二步:实现核心效果
- 先实现列表项/卡片的液态扩散效果(最重要)
- 然后实现按钮的液态波纹效果(需要 JS 配合)
- 添加背景装饰水滴(可选,但建议添加)
- 最后改造元素形状为水滴形状
第三步:优化和测试
- 添加性能优化代码(GPU 加速、Containment)
- 添加低性能设备降级方案
- 在不同浏览器测试效果
- 检查帧率是否保持 60fps
第四步:细节调整
- 根据实际效果调整动画时长
- 微调色彩透明度以匹配项目风格
- 调整水滴形状参数以适应元素尺寸
- 确保所有交互反馈流畅自然
代码组织建议
CSS 文件结构
/* ==================== 液态水滴效果 ==================== */
/* 1. 列表项液态扩散效果 */
.list-item { /* 基础样式 */ }
.list-item::before { /* 快速波纹 */ }
.list-item::after { /* 慢速波纹 */ }
.list-item:hover::before { /* 悬停触发 */ }
.list-item:hover::after { /* 悬停触发 */ }
@keyframes liquid-ripple { /* 波纹动画 */ }
/* 2. 按钮液态波纹效果 */
button { /* 基础样式 */ }
button::before { /* 点击波纹 */ }
button::after { /* 悬停光晕 */ }
button.ripple-active::before { /* 波纹激活 */ }
@keyframes liquid-glow { /* 光晕动画 */ }
/* 3. 背景装饰水滴 */
.container::before { /* 大水滴 */ }
.container::after { /* 中水滴 */ }
@keyframes liquid-float-1 { /* 浮动动画1 */ }
@keyframes liquid-float-2 { /* 浮动动画2 */ }
/* 4. 水滴形状 */
.liquid-element { /* 水滴形状定义 */ }
.liquid-element:hover { /* 悬停形状变化 */ }
@keyframes droplet-morph { /* 形变动画 */ }
/* 5. 性能优化 */
.liquid-element::before,
.liquid-element::after { /* GPU 加速 */ }
@media (prefers-reduced-motion: reduce) { /* 降级 */ }
JavaScript 文件结构
// ==================== 液态波纹效果 ====================
/**
* 为按钮添加液态波纹效果
*/
function addLiquidRippleEffect() {
// 实现代码
}
/**
* 触发按钮波纹动画
* @param {HTMLElement} button - 按钮元素
* @param {MouseEvent} event - 点击事件
*/
function triggerButtonRipple(button, event) {
// 实现代码
}
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', addLiquidRippleEffect);
验收标准
实现完成后,请确保满足以下标准:
视觉效果
- ✅ 悬停列表项/卡片时看到双层液态波纹扩散
- ✅ 点击按钮时看到从点击位置扩散的波纹
- ✅ 悬停按钮时看到持续的液态光晕
- ✅ 背景中有缓慢浮动的装饰水滴
- ✅ 所有元素采用水滴形状
- ✅ 活跃/选中元素有持续脉冲效果
性能指标
- ✅ 浏览器帧率保持 60fps
- ✅ CPU 占用 < 5%
- ✅ 无明显卡顿或延迟
- ✅ 在低性能设备上能正常降级
交互体验
- ✅ 悬停和点击反馈即时响应
- ✅ 动画流畅自然,无突兀感
- ✅ 波纹起点准确(按钮点击位置)
- ✅ 所有状态反馈清晰明确
代码质量
- ✅ CSS 代码结构清晰,有注释
- ✅ JavaScript 代码简洁,无冗余
- ✅ 选择器性能优化(避免深层嵌套)
- ✅ 兼容主流浏览器(Chrome 88+, Firefox 78+, Safari 14+)
特殊场景处理
动态内容
如果列表项或按钮是动态创建的:
// 方案1:事件委托(推荐)
document.addEventListener('click', function(e) {
const button = e.target.closest('button, .btn');
if (button) {
triggerButtonRipple(button, e);
}
});
// 方案2:MutationObserver 监听 DOM 变化
const observer = new MutationObserver(() => {
addLiquidRippleEffect();
});
observer.observe(document.body, { childList: true, subtree: true });
框架集成
React:
import { useEffect, useRef } from 'react';
function ButtonWithRipple({ children, onClick }) {
const buttonRef = useRef(null);
const handleClick = (e) => {
triggerButtonRipple(buttonRef.current, e);
onClick?.(e);
};
return (
<button ref={buttonRef} onClick={handleClick}>
{children}
</button>
);
}
Vue:
// 自定义指令
app.directive('liquid-ripple', {
mounted(el) {
el.addEventListener('click', (e) => {
triggerButtonRipple(el, e);
});
}
});
// 使用
<button v-liquid-ripple>点击我</button>
Angular:
// 自定义指令
@Directive({ selector: '[liquidRipple]' })
export class LiquidRippleDirective {
@HostListener('click', ['$event'])
onClick(event: MouseEvent) {
triggerButtonRipple(this.el.nativeElement, event);
}
}
常见问题
Q1: 波纹效果与现有样式冲突怎么办?
A: 检查元素是否已经使用了 ::before/::after 伪元素。如果冲突,可以:
- 改用额外的包装
<div>元素 - 调整现有伪元素的用途
- 使用 JavaScript 动态创建波纹元素
Q2: 如何适配深色主题?
A: 使用 CSS 变量或主题类:
:root {
--liquid-primary: rgba(0, 234, 255, 0.4);
--liquid-secondary: rgba(168, 239, 133, 0.3);
}
[data-theme="dark"] {
--liquid-primary: rgba(100, 200, 255, 0.5);
--liquid-secondary: rgba(200, 255, 150, 0.4);
}
Q3: 动画在移动设备上卡顿怎么办?
A:
- 确保已添加 GPU 加速
- 降低装饰水滴数量(移动端只保留 1 个)
- 缩短动画时长
- 使用
@media (hover: none)禁用悬停效果
Q4: 如何禁用某些元素的液态效果?
A:
.no-liquid::before,
.no-liquid::after {
display: none !important;
animation: none !important;
}
注意事项
- 不要过度使用: 只在重要交互元素上应用液态效果
- 保持一致性: 同类元素应使用相同的动画参数
-
考虑可访问性: 添加
prefers-reduced-motion支持 - 测试多场景: 包括空状态、加载状态、错误状态等
- 监控性能: 使用 Chrome DevTools Performance 面板检查
- 渐进增强: 确保在不支持的浏览器中基础功能仍可用