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/filters/goo-menu.html7 Desc : Gooey action menu — dots merge and separate like liquid8 ============================================================9-->10<!--svgarden11title: Goo menu12slug: goo-menu13category: filters14tags: [filter, goo, liquid, blob]15difficulty: advanced16techniques: [feGaussianBlur, "feColorMatrix (alpha threshold)", feBlend, filter-pipeline]17how_it_works: >18 The gooey look is a two-step filter pipeline. feGaussianBlur first smears every19 dot into a soft cloud, so where two dots come near, their alpha halos overlap20 and add up. feColorMatrix then multiplies alpha by 19 and subtracts 9, a hard21 threshold that crushes the blur back to a crisp edge — but the overlapping22 halos survive the cut, becoming the liquid bridge between shapes. A final23 feBlend redraws the original sharp circles on top so the dots stay clean while24 the goo happens between them.25customizable:26 - { var: "--sg-color", label: "Color", type: color, default: "#7F77DD" }27 - { var: "--sg-size", label: "Size", type: range, min: 80, max: 240, default: 140, unit: px }28 - { var: "--sg-duration", label: "Cycle", type: range, min: 1.5, max: 6, step: 0.1, default: 2.8, unit: s }29created: 2026-08-1030-->31<div class="sg-goo-menu" style="--sg-color:#7F77DD; --sg-size:140px; --sg-duration:2.8s;">32 <svg viewBox="0 0 120 120" aria-hidden="true" focusable="false">33 <defs>34 <filter id="sg-goo-menu-goo" x="-30%" y="-30%" width="160%" height="160%">35 <feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />36 <feColorMatrix in="blur" mode="matrix"37 values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />38 <feBlend in="SourceGraphic" in2="goo" />39 </filter>40 </defs>41 <g filter="url(#sg-goo-menu-goo)">42 <circle class="sg-goo-menu-dot" cx="60" cy="60" r="15" />43 <circle class="sg-goo-menu-sat sg-goo-menu-sat1" cx="60" cy="60" r="11" />44 <circle class="sg-goo-menu-sat sg-goo-menu-sat2" cx="60" cy="60" r="11" />45 <circle class="sg-goo-menu-sat sg-goo-menu-sat3" cx="60" cy="60" r="11" />46 </g>47 </svg>48</div>49<style>50 .sg-goo-menu {51 width: var(--sg-size);52 height: var(--sg-size);53 }54 .sg-goo-menu svg {55 display: block;56 width: 100%;57 height: 100%;58 }59 .sg-goo-menu circle {60 fill: var(--sg-color);61 }62 .sg-goo-menu-sat {63 animation-duration: var(--sg-duration);64 animation-timing-function: ease-in-out;65 animation-iteration-count: infinite;66 }67 .sg-goo-menu-sat1 { animation-name: sg-goo-menu-up; }68 .sg-goo-menu-sat2 { animation-name: sg-goo-menu-right; }69 .sg-goo-menu-sat3 { animation-name: sg-goo-menu-left; }70 @keyframes sg-goo-menu-up {71 0%, 12% { transform: translate(0, 0); }72 45%, 65% { transform: translate(0, -35px); }73 100% { transform: translate(0, 0); }74 }75 @keyframes sg-goo-menu-right {76 0%, 12% { transform: translate(0, 0); }77 45%, 65% { transform: translate(31px, 18px); }78 100% { transform: translate(0, 0); }79 }80 @keyframes sg-goo-menu-left {81 0%, 12% { transform: translate(0, 0); }82 45%, 65% { transform: translate(-31px, 18px); }83 100% { transform: translate(0, 0); }84 }85</style>86