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.6 KB · 69 lines html
Raw Blame History
1<!--2  ============================================================3  SVGarden — https://www.svgarden.dev4  Author : Simon-Pierre Boucher5  Contact: contact@spboucher.ai6  File   : snippets/text-fx/text-variable-weight-wave.html7  Desc   : A wave of font-weight rolling across letters via @property8  ============================================================9-->10<!--svgarden11title: Variable-weight wave12slug: text-variable-weight-wave13category: text-fx14tags: [text, variable-font, property, stagger]15difficulty: advanced16techniques: ["@property", font-variation-settings, --sg-i-index-stagger, "@supports"]17how_it_works: >18  Custom properties normally interpolate as raw strings, so animating one just19  snaps between keyframes. Registering it with @property and syntax:'<number>'20  tells the engine it is a real number, making it tween smoothly — and here that21  animated number is piped straight into font-variation-settings "wght", so the22  glyph skeleton itself thickens and relaxes. Each letter carries its position23  in a --sg-i variable, and a negative animation-delay computed from it phases24  the shared keyframe into a traveling wave. Inside @supports the effect is25  gated: browsers without @property (or without a variable system font) simply26  show the text at a steady weight.27support: >28  Needs @property and font-variation-settings (Chrome 85+, Safari 16.4+,29  Firefox 128+) plus a variable system font such as SF Pro or Segoe UI30  Variable; elsewhere the text renders at a static weight.31customizable:32  - { var: "--sg-color",    label: "Color",     type: color, default: "#7F77DD" }33  - { var: "--sg-size",     label: "Font size", type: range, min: 20, max: 72, default: 42, unit: px }34  - { var: "--sg-duration", label: "Speed",     type: range, min: 0.8, max: 5, step: 0.1, default: 2, unit: s }35created: 2026-08-1036-->37<div class="sg-text-variable-weight-wave" aria-label="flexible" style="--sg-color:#7F77DD; --sg-size:42px; --sg-duration:2s;">38  <span class="sg-text-variable-weight-wave-ch" style="--sg-i:0" aria-hidden="true">f</span><span class="sg-text-variable-weight-wave-ch" style="--sg-i:1" aria-hidden="true">l</span><span class="sg-text-variable-weight-wave-ch" style="--sg-i:2" aria-hidden="true">e</span><span class="sg-text-variable-weight-wave-ch" style="--sg-i:3" aria-hidden="true">x</span><span class="sg-text-variable-weight-wave-ch" style="--sg-i:4" aria-hidden="true">i</span><span class="sg-text-variable-weight-wave-ch" style="--sg-i:5" aria-hidden="true">b</span><span class="sg-text-variable-weight-wave-ch" style="--sg-i:6" aria-hidden="true">l</span><span class="sg-text-variable-weight-wave-ch" style="--sg-i:7" aria-hidden="true">e</span>39</div>40<style>41  @property --sg-tvww-wgt {42    syntax: '<number>';43    inherits: false;44    initial-value: 400;45  }46  .sg-text-variable-weight-wave {47    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI Variable Text', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;48    font-size: var(--sg-size);49    color: var(--sg-color);50    letter-spacing: 0.02em;51    display: inline-flex;52  }53  .sg-text-variable-weight-wave-ch {54    font-weight: 550;55  }56  @supports (font-variation-settings: "wght" 500) {57    .sg-text-variable-weight-wave-ch {58      animation: sg-text-variable-weight-wave-roll var(--sg-duration) ease-in-out infinite;59      animation-delay: calc(var(--sg-i) * var(--sg-duration) / -8);60      font-variation-settings: "wght" var(--sg-tvww-wgt);61      font-weight: normal;62    }63  }64  @keyframes sg-text-variable-weight-wave-roll {65    0%, 100% { --sg-tvww-wgt: 260; }66    50%      { --sg-tvww-wgt: 840; }67  }68</style>69