spb/svgarden Public
SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)
HTML 79.2%
Astro 10.3%
JavaScript 6%
CSS 3.7%
Shell 0.8%
1<!--2 ============================================================3 SVGarden — https://www.svgarden.dev4 Author : Simon-Pierre Boucher5 Contact: contact@spboucher.ai6 File : snippets/buttons/btn-liquid-swipe.html7 Desc : Wavy liquid front sweeping across the button on hover8 ============================================================9-->10<!--svgarden11title: Liquid swipe button12slug: btn-liquid-swipe13category: buttons14tags: [button, liquid, clip-path, hover]15difficulty: advanced16techniques: [clipPath, animated-path-front, transition, preserveAspectRatio-none]17how_it_works: >18 The "liquid" is one filled path shaped like a rectangle whose right edge19 undulates — that wavy edge is the liquid's front. A clipPath pins everything20 inside the button's rounded pill so the wave can slosh past the edges without21 spilling. At rest the path sits translated a full button-width left, in22 viewBox pixels because percentage translates are unreliable on SVG children;23 hovering transitions it to 0, and a low-amplitude keyframe animation bobs it vertically the24 whole time, which is what makes the front feel fluid instead of like a sliding25 card. The bob lives on a wrapper group rather than the path itself, because an26 animated transform on an SVG element replaces its static transform instead of27 composing with it — nesting sidesteps that.28customizable:29 - { var: "--sg-color", label: "Liquid", type: color, default: "#4B9FE8" }30 - { var: "--sg-size", label: "Font size", type: range, min: 12, max: 26, default: 16, unit: px }31 - { var: "--sg-duration", label: "Speed", type: range, min: 0.3, max: 1.6, step: 0.05, default: 0.7, unit: s }32created: 2026-08-1033-->34<button class="sg-btn-liquid-swipe" type="button" style="--sg-color:#4B9FE8; --sg-size:16px; --sg-duration:0.7s;">35 <svg viewBox="0 0 140 44" preserveAspectRatio="none" aria-hidden="true" focusable="false">36 <defs>37 <clipPath id="sg-btn-liquid-swipe-pill">38 <rect x="0" y="0" width="140" height="44" rx="22" />39 </clipPath>40 </defs>41 <rect class="sg-btn-liquid-swipe-rim" x="1" y="1" width="138" height="42" rx="21" />42 <g clip-path="url(#sg-btn-liquid-swipe-pill)">43 <g class="sg-btn-liquid-swipe-bob">44 <path class="sg-btn-liquid-swipe-wave"45 d="M-6 -8 H132 C 140 0, 128 8, 136 16 C 144 24, 128 32, 136 40 C 140 46, 134 50, 132 52 H-6 Z" />46 </g>47 </g>48 </svg>49 <span class="sg-btn-liquid-swipe-label">Dive in</span>50</button>51<style>52 .sg-btn-liquid-swipe {53 position: relative;54 appearance: none;55 border: 0;56 background: transparent;57 font: inherit;58 font-size: var(--sg-size);59 font-weight: 600;60 color: inherit;61 padding: 0.8em 2em;62 cursor: pointer;63 }64 .sg-btn-liquid-swipe svg {65 position: absolute;66 inset: 0;67 width: 100%;68 height: 100%;69 }70 .sg-btn-liquid-swipe-rim {71 fill: none;72 stroke: var(--sg-color);73 stroke-width: 2;74 vector-effect: non-scaling-stroke;75 }76 .sg-btn-liquid-swipe-wave {77 fill: var(--sg-color);78 /* viewBox units — percentage translate is unreliable on SVG children */79 transform: translateX(-152px);80 transition: transform var(--sg-duration) cubic-bezier(0.5, 0.1, 0.3, 1);81 }82 .sg-btn-liquid-swipe-bob {83 animation: sg-btn-liquid-swipe-bob 1.6s ease-in-out infinite;84 }85 .sg-btn-liquid-swipe-label {86 position: relative;87 transition: color calc(var(--sg-duration) * 0.7) ease;88 }89 .sg-btn-liquid-swipe:hover .sg-btn-liquid-swipe-wave,90 .sg-btn-liquid-swipe:focus-visible .sg-btn-liquid-swipe-wave {91 transform: translateX(0);92 }93 .sg-btn-liquid-swipe:hover .sg-btn-liquid-swipe-label,94 .sg-btn-liquid-swipe:focus-visible .sg-btn-liquid-swipe-label {95 color: #ffffff;96 }97 @keyframes sg-btn-liquid-swipe-bob {98 0%, 100% { transform: translateY(0); }99 50% { transform: translateY(-3px); }100 }101</style>102