Wavy Underline Thickness Control
Native CSS text-decoration-style: wavy with animated thickness + offset — no decorative SVG layer needed. Three motion programs: a thickness breathe, a thickness + offset peak pulse, and a hue-shift color sweep.
Native CSS text-decoration-style: wavy with animated thickness + offset — no decorative SVG layer needed. Three motion programs: a thickness breathe, a thickness + offset peak pulse, and a hue-shift color sweep.
Wavy underline · text-decoration breathing
Native wavy underline styling changes visual weight with text-decoration-thickness and underline-offset rather than drawing a separate SVG underline. Three variants demonstrate a thin inline link, a broader editorial mark, and a compact dense callout.
Thin wave · body copy
A thin squiggle breathes its thickness subtly so inline text stays readable while still signaling emphasis. The offset stays pinned — the underline never moves vertically. Em-based thickness scales with font size + browser zoom.
Broader wave · headline
A thicker underline pulses both its weight AND its offset together — the line gets bolder as it pushes farther below the baseline, then holds the peak briefly before settling back. Headline-scale emphasis without positioning a separate decoration layer.
Compact copy · fixed offset
A compact callout keeps thickness fixed and instead cycles the underline COLOR between accent and accent-2. Safer in dense UI where a thickness-changing squiggle would crowd neighboring text — only hue moves, geometry stays still.
A wavy underline thickness control uses native text-decoration, then animates text-decoration-thickness and underline-offset in em units so the line scales with the text.
1<a class="wavy-underline-recipe" href="#">Read the motion notes</a><style>.wavy-underline-recipe {color: #e0f2fe;font: 800 clamp(1.2rem, 6vw, 2rem)/1.2 ui-sans-serif, system-ui;9text-decoration-line: underline;text-decoration-style: wavy;text-decoration-color: #38bdf8;12text-decoration-thickness: .08em;13text-underline-offset: .24em;text-shadow: 0 0 18px rgba(56, 189, 248, .14);animation:wavy-underline-recipe-breathe 2.4s ease-in-out infinite alternate;}18.wavy-underline-recipe:focus-visible {outline: 2px solid #7dd3fc;outline-offset: .35rem;}22@keyframes wavy-underline-recipe-breathe {from {text-decoration-thickness: .06em;text-underline-offset: .22em;}to {text-decoration-thickness: .16em;text-underline-offset: .3em;}}32@media (prefers-reduced-motion: reduce) {.wavy-underline-recipe {animation: none;text-decoration-thickness: .1em;text-underline-offset: .24em;}}</style>
Native decoration follows text metrics, wraps with inline text, and scales naturally with font size. A pseudo-element can work for headings, but it is easier to misalign on wrapped inline copy.
Two stacked links — small caption (.85rem) and headline (2rem). before locks thickness to a fixed 3px so the same line looks chunky under small copy and pencil-thin under the headline. after uses .1em — at .85rem that is ~1.4 px, at 2rem it is ~3.2 px, the underline weight tracks the type scale.
Use em for text-relative weight. It responds to zoom and font size, which is especially important when the same underline style appears in body copy and headings.
Same word with three descenders (p, p, y), same heavy wavy decoration (thickness .18em on both), same color alpha breath (55% → 100%), text-decoration-skip-ink: none so the wave is drawn through everything it meets. Only text-underline-offset differs. 0 keeps the wave at the default position, where it crosses the descenders of p, p, y — the wave visibly cuts across the glyph strokes. .28em pushes the wave clear of the descenders so the same heavy crests stay on their own line. (Animating thickness redraws the wave shape on every frame and looks stepped; animating the alpha keeps the breathing smooth.)
Yes. Keep the range subtle for body text and reserve stronger pulses for short labels or editorial marks. Dense UI often works better with color changes than thickness changes.
Yes. Keep the range subtle for body text and reserve stronger pulses for short labels or editorial marks. Dense UI often works better with color changes than thickness changes.
Yes. Keep the range subtle for body text and reserve stronger pulses for short labels or editorial marks. Dense UI often works better with color changes than thickness changes.
Stop the breathing or color cycle and keep a static underline with enough contrast. Do not remove the underline if it communicates link affordance or emphasis.
Native CSS wavy underline via text-decoration-style: wavy with animated text-decoration-thickness and text-underline-offset. No decorative SVG layer and no per-letter spans — just CSS text-decoration properties on the actual text node. Three motion programs: thickness breathe, thickness + offset peak pulse, hue-shift color sweep.
Reach for wavy underlines on highlighted phrases, marketing callouts, and editorial emphasis — anywhere <em> needs visual amplification. Skip it on links (the wavy already means “spelling error” to most users) and on dense paragraph copy where the underline crowds adjacent lines.
Set text-decoration-line: underline + text-decoration-style: wavy on the element. Two animatable properties drive the motion: text-decoration-thickness (e.g. 1px to 3px) and text-underline-offset (e.g. 2px to 6px). A @keyframes rule animates either or both. For color sweeps animate text-decoration-color through a hue range. The wave geometry itself is fixed — you cannot animate the wave amplitude or frequency directly without falling back to an SVG underline overlay.
Animating thickness past ~4px crowds the line below in dense paragraph copy — clamp the maximum thickness based on line-height. Browsers differ on whether text-decoration-thickness is interpolated smoothly (Chromium yes, Firefox yes as of recent versions, Safari sometimes snaps); accept that the breathe may be slightly less smooth in older Safari. Watch text-underline-offset on emoji or mixed-font lines — the offset is calculated per-glyph metric and can produce uneven underlines under those characters.
Native text-decoration underlines respect user underline-style preferences and forced-colors mode for free — one of the strongest reasons to use this over an SVG fake. Under prefers-reduced-motion: reduce drop the animation so the underline is static at its rest thickness. Wavy underlines on links can confuse users with spelling-check muscle memory — use a different decoration-style (solid, double) for actual links.
Native text decoration is usually better than drawing an SVG underline for every link. text-decoration-style, text-decoration-thickness, and text-underline-offset keep the underline attached to real text metrics.
Tune thickness per font size. A decorative wave that works under a large heading can muddy small inline links, so keep body-copy underlines quieter and avoid animation when the underline is carrying accessibility meaning.