Distortion✨ Premium

Wave Distortion

The letters of a text rise, lean, sink and lean the other way one after another: a slow swell, 3 seconds per wave, that rolls through the word from left to right.

CSSJSWave

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Distortion has 31 effects, including 5 free. Explore the category →

3 usage examples

Sailing school — the name rippling over the sea at the top of the page — Wave Distortion example 1

① Sailing school — the name rippling over the sea at the top of the page

WhenOn Ondivelle's home page, the school's name, large against an evening sky, keeps rippling above the tagline; the menu (Courses, Prices, Weather) and the booking button stay put.
WhyThe swell of the letters echoes the water: the heading becomes the scenery. Because the wave is slow (3 s) and limited to the heading, it sets the mood without getting in the way of the rest.
Settings--wvd-size: 60px, --wvd-color: #f4f9ff, --wvd-bg: transparent, --wvd-height: auto, root aligned left; Georgia font, wvd-text class on the <h1>, 4 px of padding so the swell is not clipped.
Harbour office — the current water height in the tide widget — Wave Distortion example 2

② Harbour office — the current water height in the tide widget

WhenIn Kerbrivel's "Tides today" widget, high and low tide times, the coefficient and the curve stay still; only the "rising tide · now" value, 4.2 m, ripples.
WhyThe only live figure in the table is the one that moves: it is spotted at first glance, and the swell hints that it keeps changing. The screen reader says "4.2 m", not a string of characters.
Settings--wvd-size: 34px, --wvd-color: #0f5c86, background and height released, 3 px of padding. Two roots (FR "4,2 m", EN "4.2 m"): the scene shows the one matching the page language.
Web messaging — the button that reads "Reconnecting…" after a click — Wave Distortion example 3

③ Web messaging — the button that reads "Reconnecting…" after a click

WhenA "Connection lost" bar appears in Parlivo. When "Try again" is clicked, the button label becomes "Reconnecting…" and ripples during the attempt, then the bar turns green. The scene replays that click on its own, in a loop.
WhyWaiting is often shown with a spinner; here the word itself moves, with no extra icon and within the button's own space. The text changes, so screen reader users get the information.
Settings--wvd-size: 12px, --wvd-color: #fff, --wvd-rise: .2em (visible swell at small size), root set to width: auto inside the <button>. The label swap and the reconnection are wired in the scene.

How it works

You write the text in .wvd-text. On load, the script copies it into a .wvd-sr reserved for screen readers, then replaces what is shown with .wvd-letter elements grouped by word in .wvd-word, all under aria-hidden="true". Each letter carries its position in the --wvd-i variable. Every .fx-0255-root on the page is handled, each with its own text.

The wvdWave animation lasts 3 s: at a quarter, the letter has risen 0.125 em and leans −5°; at three quarters, it has sunk by the same amount and leans +5°; it ends upright, in place. Each letter starts 0.15 s after the previous one: with the 10 letters of DISTORTION, the last starts 1.35 s after the first and the wave sweeps the word from left to right.

Everything is set with variables on the root: size (--wvd-size, 2.5rem), colour (--wvd-color, white), swell height (--wvd-rise, in em so it follows the size), slant (--wvd-skew), duration and stagger. The block keeps overflow: hidden: a swell too tall for the line height gets clipped, so raise line-height or add a little padding.

The root spans the full width, at least 300 px tall on a #0a0a0f background. With --wvd-height: auto, --wvd-bg: transparent and width: auto, it slips into a heading, a widget or a button.

Accessibility

  • Screen readers: the text in .wvd-sr is announced normally, the split letters are ignored. Measured in Chromium, Firefox and WebKit: "D I S T O R T I O N" spelled out before the repair, "DISTORTION" after.
  • Reduced motion: with prefers-reduced-motion: reduce, the letters stop moving and stay upright; the text is whole and readable.
  • Readability: the ±5° slant and the 0.125 em swell keep the word readable at every size tested (12 to 80 px). On a 12 px button label, raise --wvd-rise to 0.2em so the motion shows.
  • Flashing: none; the colour never changes, only the position moves (frame-by-frame measurement: 0 cells above the threshold).
  • Role: the effect makes nothing clickable. Placed in a <button> or an <h1>, it keeps the meaning of the element that hosts it.

Browser compatibility

CSS (1.9 KB) and 1 KB of dependency-free JavaScript: CSS variables, calc() in keyframes and delay, skewX(), Array.from. Measured in Chromium 151, Firefox 153 and WebKit 26.5: pixel-identical to the previous version at 0, 40, 75 and 500 ms; two copies with two different texts each split correctly; 0 errors.

Chrome 49+✓ Full (measured)
Firefox 32+✓ Full (measured)
Safari 9.1+✓ Full (WebKit engine measured)
Edge 79+✓ Full (Chromium engine)
Mobile iOS 9.3+✓ Full (WebKit engine measured)
Android Chrome 49+✓ Full (Chromium engine)

If the script does not run, the text stays in one piece, in the chosen colour, with no swell. Without CSS variables, the text shows with inherited styles, still.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0255-root">
  <div class="wvd-text">Your text</div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Text (HTML — content of .wvd-text) DISTORTION The text shown and read; it may contain spaces, accents and digits.
--wvd-size · --wvd-color 2.5rem · #fff Size and colour of the letters.
--wvd-rise .125em Height of the swell, up then down (5 px at 2.5rem). 0.2em on a small label.
--wvd-skew 5deg Slant of the letters at the top and bottom of the wave. 0deg for a swell with no tilt.
--wvd-speed · --wvd-delay 3s · .15s Length of one wave and gap between two letters. A shorter gap (0.08s) makes a tighter wave on long text.
--wvd-bg · --wvd-height #0a0a0f · 300px Root background and minimum height; transparent and auto to blend it in.

FAQ

Yes for indexing and reading: the full text stays in the page, in .wvd-sr. When copying with the mouse, the selection takes the visible letters; the copy kept for screen readers has user-select: none and is not pasted twice. Measured in all three engines: the pasted text is exact, spaces included.
The .wvd-text block has overflow: hidden, as in the original code. If the swell goes beyond the line height (large --wvd-rise, tight line-height), add a few pixels of vertical padding to .wvd-text, as in the examples.
Put the root in the page from the start, hidden (hidden), next to the normal label: the script splits it on load. When the action starts, swap the two with hidden, then switch back at the end, like the messaging button.