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/backgrounds/dots-drift.html7 Desc : Subtle drifting dot-grid pattern background8 ============================================================9-->10<!--svgarden11title: Drifting dots12slug: dots-drift13category: backgrounds14tags: [background, pattern, dots, ambient]15difficulty: intermediate16techniques: [svg-pattern, translate-property, seamless-tiling, layered-opacity]17how_it_works: >18 A <pattern> tile of one dot fills two oversized rects. Because a pattern is19 periodic, translating a rect by exactly one tile (28 units) returns it to a20 pixel-identical state, so the infinite drift never shows a seam — the rects21 are drawn larger than the viewport to hide the moving edges. The two layers22 drift in opposite diagonals at different speeds, which adds quiet depth23 without ever pulling focus from the content above.24customizable:25 - { var: "--sg-color", label: "Dot color", type: color, default: "#7F77DD" }26 - { var: "--sg-size", label: "Height", type: range, min: 80, max: 260, default: 150, unit: px }27 - { var: "--sg-duration", label: "Speed", type: range, min: 2, max: 20, step: 0.5, default: 8, unit: s }28created: 2026-08-1029-->30<div class="sg-dots-drift" style="--sg-color:#7F77DD; --sg-size:150px; --sg-duration:8s;">31 <svg viewBox="0 0 280 140" preserveAspectRatio="xMidYMid slice" aria-hidden="true" focusable="false">32 <defs>33 <pattern id="sg-dots-drift-tile" width="28" height="28" patternUnits="userSpaceOnUse">34 <circle cx="4" cy="4" r="2.2" />35 </pattern>36 </defs>37 <rect class="sg-dots-drift-a" x="-28" y="-28" width="340" height="200" fill="url(#sg-dots-drift-tile)" />38 <rect class="sg-dots-drift-b" x="-28" y="-28" width="340" height="200" fill="url(#sg-dots-drift-tile)" />39 </svg>40</div>41<style>42 .sg-dots-drift {43 width: 100%;44 min-width: 240px;45 height: var(--sg-size);46 overflow: hidden;47 border-radius: 8px;48 }49 .sg-dots-drift svg {50 display: block;51 width: 100%;52 height: 100%;53 }54 .sg-dots-drift circle {55 fill: var(--sg-color);56 }57 .sg-dots-drift-a {58 opacity: 0.35;59 animation: sg-dots-drift-se var(--sg-duration) linear infinite;60 }61 .sg-dots-drift-b {62 opacity: 0.18;63 animation: sg-dots-drift-nw calc(var(--sg-duration) * 1.7) linear infinite;64 }65 @keyframes sg-dots-drift-se {66 from { translate: 0 0; }67 to { translate: 28px 28px; }68 }69 @keyframes sg-dots-drift-nw {70 from { translate: 14px 14px; }71 to { translate: -14px -14px; }72 }73</style>74