SPB Git

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%
3.8 KB · 102 lines html
Raw Blame History
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