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%
5.2 KB · 113 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/backgrounds/rain-window.html7  Desc   : Rain streaks on a window with wet-glass refraction8  ============================================================9-->10<!--svgarden11title: Rain on a window12slug: rain-window13category: backgrounds14tags: [background, rain, turbulence, displacement]15difficulty: advanced16techniques: [feTurbulence, feDisplacementMap, animateMotion, staggered-delays]17how_it_works: >18  The refraction is the trick worth stealing: the backdrop gradient is drawn19  twice, and the top copy runs through feTurbulence noise feeding a20  feDisplacementMap, which shoves its pixels around like light bending through21  wet glass. A SMIL animate slowly mutates the noise's baseFrequency so the22  distortion crawls instead of freezing. In front, eight streak lines share23  one falling keyframe with scattered durations and negative delays, while24  two heavier droplets wander down a wobbly animateMotion path — the slow25  droplets against fast streaks give the scene its depth.26customizable:27  - { var: "--sg-color",    label: "Glass tint", type: color, default: "#31445A" }28  - { var: "--sg-size",     label: "Height",     type: range, min: 100, max: 300, default: 180, unit: px }29  - { var: "--sg-duration", label: "Rain speed", type: range, min: 0.8, max: 4, step: 0.1, default: 1.6, unit: s }30created: 2026-08-1031-->32<div class="sg-rain-window" style="--sg-color:#31445A; --sg-size:180px; --sg-duration:1.6s;">33  <svg viewBox="0 0 320 180" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">34    <defs>35      <linearGradient id="sg-rain-window-sky" x1="0" y1="0" x2="0" y2="1">36        <stop class="sg-rain-window-tint" offset="0" />37        <stop offset="1" stop-color="#0f1722" />38      </linearGradient>39      <filter id="sg-rain-window-warp" x="-10%" y="-10%" width="120%" height="120%">40        <feTurbulence type="fractalNoise" baseFrequency="0.012 0.05" numOctaves="2" result="sg-noise">41          <animate attributeName="baseFrequency" dur="9s" repeatCount="indefinite"42            values="0.012 0.05;0.016 0.06;0.012 0.05" />43        </feTurbulence>44        <feDisplacementMap in="SourceGraphic" in2="sg-noise" scale="16" />45      </filter>46    </defs>47    <rect x="0" y="0" width="320" height="180" fill="url(#sg-rain-window-sky)" />48    <rect class="sg-rain-window-wet" x="-20" y="-20" width="360" height="220" fill="url(#sg-rain-window-sky)" />49    <g class="sg-rain-window-streaks">50      <line x1="30"  y1="-30" x2="27"  y2="-6" />51      <line x1="74"  y1="-42" x2="71"  y2="-14" />52      <line x1="118" y1="-26" x2="115" y2="-4" />53      <line x1="162" y1="-38" x2="159" y2="-10" />54      <line x1="206" y1="-30" x2="203" y2="-8" />55      <line x1="248" y1="-44" x2="245" y2="-16" />56      <line x1="284" y1="-28" x2="281" y2="-6" />57      <line x1="308" y1="-40" x2="305" y2="-14" />58    </g>59    <circle class="sg-rain-window-drop1" cx="96" cy="0" r="2.6">60      <animateMotion dur="8s" begin="-2s" repeatCount="indefinite"61        path="M0 -10 q 4 30 -3 58 q -5 26 2 52 q 5 26 -2 50 q -4 20 1 44" />62    </circle>63    <circle class="sg-rain-window-drop2" cx="228" cy="0" r="2.1">64      <animateMotion dur="11s" begin="-6s" repeatCount="indefinite"65        path="M0 -10 q -4 34 3 62 q 5 28 -3 54 q -4 24 3 48 q 3 18 -2 40" />66    </circle>67  </svg>68</div>69<style>70  .sg-rain-window {71    width: 100%;72    min-width: 240px;73    height: var(--sg-size);74    overflow: hidden;75    border-radius: 8px;76  }77  .sg-rain-window svg {78    display: block;79    width: 100%;80    height: 100%;81  }82  .sg-rain-window-tint {83    stop-color: var(--sg-color);84  }85  .sg-rain-window-wet {86    filter: url(#sg-rain-window-warp);87    opacity: 0.75;88  }89  .sg-rain-window-streaks line {90    stroke: #dbe6f3;91    stroke-width: 1.4;92    stroke-linecap: round;93    opacity: 0.32;94    animation: sg-rain-window-fall var(--sg-duration) linear infinite;95  }96  .sg-rain-window-streaks line:nth-of-type(2) { animation-duration: calc(var(--sg-duration) * 0.8);  animation-delay: calc(var(--sg-duration) * -0.4); }97  .sg-rain-window-streaks line:nth-of-type(3) { animation-duration: calc(var(--sg-duration) * 1.25); animation-delay: calc(var(--sg-duration) * -0.9); }98  .sg-rain-window-streaks line:nth-of-type(4) { animation-duration: calc(var(--sg-duration) * 0.7);  animation-delay: calc(var(--sg-duration) * -0.2); }99  .sg-rain-window-streaks line:nth-of-type(5) { animation-duration: calc(var(--sg-duration) * 1.1);  animation-delay: calc(var(--sg-duration) * -0.7); }100  .sg-rain-window-streaks line:nth-of-type(6) { animation-duration: calc(var(--sg-duration) * 0.85); animation-delay: calc(var(--sg-duration) * -0.55); }101  .sg-rain-window-streaks line:nth-of-type(7) { animation-duration: calc(var(--sg-duration) * 1.3);  animation-delay: calc(var(--sg-duration) * -0.3); }102  .sg-rain-window-streaks line:nth-of-type(8) { animation-duration: calc(var(--sg-duration) * 0.75); animation-delay: calc(var(--sg-duration) * -0.65); }103  .sg-rain-window-drop1,104  .sg-rain-window-drop2 {105    fill: #e7eef8;106    opacity: 0.5;107  }108  @keyframes sg-rain-window-fall {109    from { transform: translateY(0); }110    to   { transform: translateY(230px); }111  }112</style>113