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.1 KB · 74 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/filters/heat-shimmer.html7  Desc   : Heat-haze shimmer rising over a flame8  ============================================================9-->10<!--svgarden11title: Heat shimmer12slug: heat-shimmer13category: filters14tags: [filter, heat, shimmer, flame]15difficulty: intermediate16techniques: [feTurbulence, feOffset-scrolling-noise, feDisplacementMap, gradient-mask]17how_it_works: >18  Heat haze is displacement that travels: feTurbulence generates a stretched19  noise field (stitchTiles keeps it seamless), a SMIL-animated feOffset scrolls20  that field upward, and feDisplacementMap warps the flame with whatever noise21  is currently passing through — so the wobble visibly rises like hot air.22  The trick that sells it is the second, unfiltered flame on top, masked by a23  vertical gradient: opaque at the base and transparent at the tip, it keeps24  the bottom rock-solid so the shimmer appears to grow with height, the way25  real convection does.26customizable:27  - { var: "--sg-color", label: "Flame", type: color, default: "#E8853C" }28  - { var: "--sg-size",  label: "Size",  type: range, min: 60, max: 220, default: 110, unit: px }29created: 2026-08-1030-->31<div class="sg-heat-shimmer" style="--sg-color:#E8853C; --sg-size:110px;">32  <svg viewBox="0 0 120 140" aria-hidden="true" focusable="false">33    <defs>34      <path id="sg-heat-shimmer-flame"35        d="M60 16 C 72 38, 92 52, 92 84 A32 32 0 0 1 28 84 C 28 52, 48 38, 60 16 Z" />36      <filter id="sg-heat-shimmer-f" x="-30%" y="-40%" width="160%" height="180%">37        <feTurbulence type="fractalNoise" baseFrequency="0.03 0.12" numOctaves="2"38          seed="3" stitchTiles="stitch" result="n" />39        <feOffset in="n" dx="0" dy="0" result="sn">40          <animate attributeName="dy" from="0" to="-50" dur="2.4s" repeatCount="indefinite" />41        </feOffset>42        <feDisplacementMap in="SourceGraphic" in2="sn" scale="9"43          xChannelSelector="R" yChannelSelector="G" />44      </filter>45      <linearGradient id="sg-heat-shimmer-grad" x1="0" y1="1" x2="0" y2="0">46        <stop offset="0.25" stop-color="white" />47        <stop offset="0.85" stop-color="black" />48      </linearGradient>49      <mask id="sg-heat-shimmer-solid">50        <rect x="0" y="0" width="120" height="140" fill="url(#sg-heat-shimmer-grad)" />51      </mask>52    </defs>53    <use class="sg-heat-shimmer-hazy" href="#sg-heat-shimmer-flame" filter="url(#sg-heat-shimmer-f)" />54    <use class="sg-heat-shimmer-base" href="#sg-heat-shimmer-flame" mask="url(#sg-heat-shimmer-solid)" />55    <path class="sg-heat-shimmer-core" d="M60 62 C 66 76, 76 82, 76 96 A16 16 0 0 1 44 96 C 44 82, 54 76, 60 62 Z" />56  </svg>57</div>58<style>59  .sg-heat-shimmer {60    width: var(--sg-size);61  }62  .sg-heat-shimmer svg {63    display: block;64    width: 100%;65  }66  .sg-heat-shimmer-hazy,67  .sg-heat-shimmer-base {68    fill: var(--sg-color);69  }70  .sg-heat-shimmer-core {71    fill: rgba(255, 255, 255, 0.5);72  }73</style>74