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/text/wave-text.html7 Desc : Letters bouncing in a wave via staggered delays8 ============================================================9-->10<!--svgarden11title: Wave text12slug: wave-text13category: text14tags: [text, wave, stagger, bounce]15difficulty: beginner16techniques: [animation-delay, nth-of-type, translateY, svg-text]17how_it_works: >18 Each letter is its own <text> element running the same small translateY19 bounce; the traveling wave is nothing but arithmetic — every letter's20 animation-delay is one-tenth of the duration later than its neighbor's,21 computed with calc() from the same variable that sets the speed. Change the22 fraction and the wave tightens or stretches; make it negative and the wave23 rolls the other way.24customizable:25 - { var: "--sg-color", label: "Color", type: color, default: "#7F77DD" }26 - { var: "--sg-size", label: "Width", type: range, min: 120, max: 400, default: 220, unit: px }27 - { var: "--sg-duration", label: "Speed", type: range, min: 0.6, max: 4, step: 0.1, default: 1.6, unit: s }28created: 2026-08-1029-->30<div class="sg-wave-text" style="--sg-color:#7F77DD; --sg-size:220px; --sg-duration:1.6s;">31 <svg viewBox="0 0 220 60" aria-hidden="true" focusable="false">32 <text x="14" y="40">s</text>33 <text x="39" y="40">v</text>34 <text x="64" y="40">g</text>35 <text x="89" y="40">a</text>36 <text x="114" y="40">r</text>37 <text x="136" y="40">d</text>38 <text x="162" y="40">e</text>39 <text x="187" y="40">n</text>40 </svg>41</div>42<style>43 .sg-wave-text {44 width: var(--sg-size);45 }46 .sg-wave-text svg {47 display: block;48 width: 100%;49 }50 .sg-wave-text text {51 font-family: inherit;52 font-size: 34px;53 font-weight: 700;54 fill: var(--sg-color);55 animation: sg-wave-text-bounce var(--sg-duration) ease-in-out infinite;56 }57 .sg-wave-text text:nth-of-type(2) { animation-delay: calc(var(--sg-duration) * -0.9); }58 .sg-wave-text text:nth-of-type(3) { animation-delay: calc(var(--sg-duration) * -0.8); }59 .sg-wave-text text:nth-of-type(4) { animation-delay: calc(var(--sg-duration) * -0.7); }60 .sg-wave-text text:nth-of-type(5) { animation-delay: calc(var(--sg-duration) * -0.6); }61 .sg-wave-text text:nth-of-type(6) { animation-delay: calc(var(--sg-duration) * -0.5); }62 .sg-wave-text text:nth-of-type(7) { animation-delay: calc(var(--sg-duration) * -0.4); }63 .sg-wave-text text:nth-of-type(8) { animation-delay: calc(var(--sg-duration) * -0.3); }64 @keyframes sg-wave-text-bounce {65 0%, 100% { transform: translateY(0); }66 30% { transform: translateY(-9px); }67 60% { transform: translateY(2px); }68 }69</style>70