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%
2.8 KB · 70 lines html
Raw Blame History
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