// FREE TOOLSView all →
◈Keyword ResearchFreeReal Google + Bing suggestions, grouped by intent.
▣Meta & SERP PreviewsoonSee how your page looks in Google, fix title & description.
◐AI Visibility ChecksoonWhat AI assistants say about your brand.
❖Schema GeneratorsoonCopy-paste JSON-LD for FAQ, Article, Product & more.
← all components
#04
Liquid fill button
On hover, a liquid rises from the bottom of the button with a sloshing wave crest, and the label flips to dark as it's submerged. Pure CSS and an SVG wave, no JavaScript. Available in React + Tailwind or plain HTML and CSS.
ReactTailwindCSSSVG
// LIVE DEMO
// THE CODE
React + Tailwind
export default function LiquidFillButton() {
return (
<button className="liquid-btn relative px-9 py-4 rounded-2xl font-bold overflow-hidden border border-white/15">
<span className="liquid-label relative z-20 transition-colors duration-300">Fill me up</span>
<span className="liquid-fill absolute left-0 right-0 bottom-0 z-10">
<svg className="liquid-wave absolute -top-3 left-0 w-[200%] h-4" viewBox="0 0 120 12" preserveAspectRatio="none">
<path d="M0 6 Q 15 0 30 6 T 60 6 T 90 6 T 120 6 V12 H0 Z" fill="url(#lg)" />
<defs><linearGradient id="lg" x1="0" x2="1">
<stop offset="0" stopColor="#38bdf8" /><stop offset="1" stopColor="#818cf8" />
</linearGradient></defs>
</svg>
</span>
<style>{`
.liquid-btn { color:#e5e7eb; background:#0d1420; }
.liquid-btn .liquid-fill { height:0; background:linear-gradient(180deg,#38bdf8,#818cf8);
transition:height .5s cubic-bezier(.4,0,.2,1); }
.liquid-btn:hover .liquid-fill { height:130%; }
.liquid-btn:hover .liquid-label { color:#05070d; }
.liquid-wave { animation:liquid-slosh 1.6s linear infinite; }
@keyframes liquid-slosh { to { transform:translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .liquid-wave { animation:none; } }
`}</style>
</button>
);
}HTML + CSS
<!-- HTML -->
<button class="liquid-btn">
<span class="label">Fill me up</span>
<span class="fill">
<svg class="wave" viewBox="0 0 120 12" preserveAspectRatio="none">
<path d="M0 6 Q 15 0 30 6 T 60 6 T 90 6 T 120 6 V12 H0 Z" fill="url(#lg)"/>
<defs><linearGradient id="lg" x1="0" x2="1"><stop offset="0" stop-color="#38bdf8"/><stop offset="1" stop-color="#818cf8"/></linearGradient></defs>
</svg>
</span>
</button>
<style>
.liquid-btn { position:relative; padding:16px 36px; border:1px solid rgba(255,255,255,.15); border-radius:16px;
font:700 15px system-ui; color:#e5e7eb; background:#0d1420; overflow:hidden; cursor:pointer; }
.liquid-btn .label { position:relative; z-index:20; transition:color .3s; }
.liquid-btn .fill { position:absolute; left:0; right:0; bottom:0; z-index:10; height:0;
background:linear-gradient(180deg,#38bdf8,#818cf8); transition:height .5s cubic-bezier(.4,0,.2,1); }
.liquid-btn:hover .fill { height:130%; }
.liquid-btn:hover .label { color:#05070d; }
.wave { position:absolute; top:-12px; left:0; width:200%; height:16px; animation:slosh 1.6s linear infinite; }
@keyframes slosh { to { transform:translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .wave { animation:none; } }
</style>// HOW IT WORKS
- 01A gradient fill element sits at the bottom of the button; on hover its height transitions from 0 to over 100%.
- 02An SVG wave path rides the top of the fill and scrolls sideways on a loop, giving the liquid a sloshing crest.
- 03The label's color flips as the liquid covers it. All CSS, and it stops animating under prefers-reduced-motion.
Want a custom component for your product?
Let's build it →