Skip to main content
assetsforwordpress

Animated Variable Font

This is a text effect that continuously changes the shape of every letter, making them thinner, bolder, wider, either as a smooth wave flowing across the text in a loop, as an interactive hover effect that stretches and glows letters near the cursor, or both at once. It adds a subtle color-split effect for extra depth, and the animation automatically switches to a calm, static version for visitors who prefer reduced motion.

Instructions

ASSETS4WP

Hover your mouse over the heading

SUPA
STYLE

Hover your mouse over the heading

BREAKDANCE
FORFUN

Hover your mouse over the heading

Instructions

Open the JS script in the Supa Code Block element and edit the options at the end of the script. Each option is explained below:

First, one thing worth knowing before the individual options: the axis options (weight, width, optical size) all follow the same pattern, each comes in three parts, and the final value is always

base + (wave position × wave amount) + (pointer influence × hover amount)

The wave position is a 0–1 sine value, and pointer influence is a 0–1 value with a smooth falloff that's 1 right under the cursor and 0 at the edge of the radius. Everything is then clamped to the axis's real limits (wght 100–1000, wdth 25–151, opsz 8–144, slnt −10 to 0).

Content & font

  • text — The string to display. If omitted (or null), the script reads whatever text is already inside the element and uses that. When you change it later via headline.update({ text: "..." }), the DOM gets rebuilt with the new letters.
  • fontFamily — The CSS font stack applied to the element. It must point to a variable font that actually exposes the axes being animated (wght, wdth, opsz, slnt — e.g. Roboto Flex), otherwise the effect has nothing to flex. If null, whatever font the element already has is left untouched. The script also disables automatic optical sizing and font synthesis, so it — not the browser — controls all the axes.

The idle "breathing" wave

  • wave (boolean) — Master switch for the ambient animation that runs even without the mouse. If false, letters only move in response to the cursor.
  • speed — How fast the wave oscillates (roughly radians per second). Higher = more frantic pulsing. Your config uses 2.95, about twice the default 1.25.
  • phase — The wave's offset between neighboring letters, in radians. At 0 every letter pulses in perfect sync; around 0.7 you get the classic travelling-crest look; larger values stretch a single crest across the whole headline.

Weight (wght)

  • wghtBase — The resting weight — how thin the letters are when idle. Your 200 is a light skeleton.
  • wghtWave — How much the breathing wave fattens the letters on top of the base. With base 200 + wave 500, letters swell up to weight 700 at wave peaks.
  • wghtHover — Extra weight added at full pointer influence. This is why letters near the cursor visibly "bulk up".

Width (wdth)

  • wdthBase — Resting letter width. Your 36 is strongly condensed.
  • wdthWave — How far the wave stretches the letters wider as it passes (peaks around base + wave).
  • wdthHover — How much wider letters become under the cursor — the "stretch toward the pointer" effect.

Optical size (opsz)

  • opszBase — The baseline optical size, which controls stroke contrast, spacing, and letter details. Your 37 is a text/display middle ground.
  • opszWave — The wave's contribution to optical size. It's 0 in your config, so opsz only reacts to the cursor.
  • opszHover — Optical size added under the pointer. Your 120 pushes hovered letters to the extreme display setting: tighter spacing, higher contrast — the "spotlight detail boost".

Slant (slnt)

  • slntHover — The only axis without a base or wave part: it exists purely for hover. It's applied as a negative value, so hovered letters lean backwards by up to this many degrees. Your 9 gives up to ~9° of backslant right at the cursor.

Pointer physics

  • radius — The size of the cursor's area of influence, measured in letter-widths. Everything within ~2 letters of the cursor is affected (with your config), falling off smoothly to zero at the edge. Small values = a laser pointer; large values = a wide spotlight.
  • lift — How far hovered letters float upward, in pixels. Works together with lightnessHover — the letter rises and brightens as you approach. Set to 0 to disable the floating entirely.

Color

  • colorMode — Either "gradient" (interpolates from colorA on the left to colorB on the right across the headline) or "solid" (uses colorA everywhere and ignores colorB). Your config uses solid dark gray, because in chroma mode the R/G/B plates supply all the color.
  • colorA — The start color (or the only color in solid mode), as a hex string.
  • colorB — The end color for gradient mode, as a hex string.
  • lightnessHover — How strongly hovered letters shift in brightness, in percent. On dark backgrounds (screen mode) they brighten — up to roughly double brightness at full influence. On light backgrounds (multiply mode) the logic inverts and they darken like soaked ink, but gentler (scaled at 0.45×) so they don't instantly go black.

Chromatic aberration

  • chroma (boolean) — Master switch for the RGB/CMY split. When true, every letter is rendered three times as separable color plates that recombine via mix-blend-mode, with a small horizontal offset between them. When false, there's a single plain text layer and all the other chroma options are ignored.
  • chromaBlend — Which color model the split uses. "screen" is additive light (R/G/B plates) — correct for dark backgrounds. "multiply" is subtractive ink (C/M/Y plates) — correct for light backgrounds. "auto" (the default) climbs up the DOM tree, finds the first opaque background color, measures its luminance, and picks multiply for light backdrops, screen for dark ones. Important caveat: auto can't see through photos or video, so if the headline sits over media, force one explicitly and call headline.refresh() after moving it.
  • chromaAmount — The constant horizontal fringe, in pixels, between the color plates — the "3D glasses" / CRT misregistration look that's always present. Yours is 1.5px.
  • chromaHover — Extra fringe added by pointer influence, so the split "blows out" near the cursor. With amount 1.5 + hover 4, the fringe widens to about 5.5px at full influence.

Glow

  • glow (boolean) — Neon halo via text-shadow. It's applied only to the two offset plates, not the stationary middle one, so the halo appears to emanate from the split edges of the letter. It's deliberately subtler in light/multiply mode.
  • glowStrength — Scales how big and soft the halo gets as pointer influence rises. At 36, the blur radius can reach ~39px on a dark background at full hover.

Motion & accessibility

  • respectReducedMotion (default true) — Honors the user's prefers-reduced-motion: reduce setting. If it's on, the animation loop never starts; instead a single static frame is rendered (base values with the wave frozen at its midpoint, no pointer influence). The headline still looks designed — it just doesn't move.
  • forceReducedMotion (default false) — Overrides everything: renders the static frame always, regardless of the user's motion preference. Useful for screenshots, previews, or debugging, and it takes precedence over respectReducedMotion.

A few practical notes

Everything is reconfigurable at runtime: headline.update({ wghtBase: 300, chroma: false, ... }) merges new values, re-applies the font if you pass fontFamily, and rebuilds the DOM if you pass new text. Call headline.refresh() whenever the element moves to a different background so the auto blend mode re-samples it. And headline.destroy() removes all listeners and restores the original text.