Noise Displacement
Text distorted by a fractal SVG noise field — feTurbulence generates the displacement map, feDisplacementMap warps the pixels; intensity doubles on hover via pure CSS, zero JavaScript.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Backgrounds has 50 effects, including 6 free. Explore the category →
3 usage examples



How it works
The effect relies entirely on an SVG filter pipeline declared inside a hidden <defs> block. feTurbulence type="fractalNoise" generates a synthetic noise image — a procedural texture in which each pixel encodes a displacement value in its R and G channels. feDisplacementMap reads those channels and shifts each source pixel by (value - 0.5) × scale along both axes, producing text whose letters are warped according to the local topology of the noise field.
Two filters are defined with the same feTurbulence but a different scale on the feDisplacementMap: the first applies moderate distortion (rest state), the second amplifies it. The CSS selector .ng-displace-scene:hover .ng-displace-text switches the element from filter: url(#ng-displace-filter) to filter: url(#ng-displace-filter-strong) on hover — no JS involved.
The transition: filter .3s property produces a cross-fade between the two filter states. Chrome and Edge actually interpolate intermediate feDisplacementMap values; Firefox and Safari perform a discrete cross-fade without jarring jumps. In both cases the progression is visually smooth. The feTurbulence noise is static (no animate attribute): zero GPU computation runs outside of the hover interaction.
The noise field is controlled by baseFrequency (spatial frequency: low = coarse organic noise, high = fine digital grain), numOctaves (fractal detail richness), and seed (random seed — varies the noise pattern between instances without changing its character). The effect works on any HTML element, not just text.
Accessibility
- prefers-reduced-motion not implemented: no
@media (prefers-reduced-motion: reduce)is present. The rest-state distortion is static (no looping animation), which is acceptable; however thefiltertransition on hover (.3s) is not suppressed for motion-sensitive users. - Text contrast: white
#fffon#0a0a0fbackground — ratio ≈ 19.8:1, well above WCAG AAA (7:1). The distortion reduces perceived legibility but does not change the measured contrast ratio. - Keyboard interaction: the hover intensity is triggered by
:hoveronly — no:focus-withinor:focus-visibleequivalent is provided. Keyboard-only users see the rest state exclusively. - Semantics: screen readers access the raw text of
.ng-displace-textdirectly — the distortion is purely visual and does not affect the accessibility tree. No additionalaria-labelis required.
Browser compatibility
Requires inline SVG and the CSS filter: url(#id) property on HTML elements — supported in all modern browsers. Zero external dependencies.
If SVG filters are unsupported, the text renders without distortion — no JS errors (there is no JS), no layout degradation.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<svg width="0" height="0" aria-hidden="true" style="position:absolute">
<defs>
<filter id="ng-displace-filter">
<feTurbulence type="fractalNoise" baseFrequency="0.04" numOctaves="4" seed="2" result="noise"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="12" xChannelSelector="R" yChannelSelector="G"/>
</filter>
<filter id="ng-displace-filter-strong">
<feTurbulence type="fractalNoise" baseFrequency="0.04" numOctaves="4" seed="2" result="noise"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="28" xChannelSelector="R" yChannelSelector="G"/>
</filter>
</defs>
</svg>
<div class="ng-displace-scene">
<div>
<div class="ng-displace-text">VOTRE TEXTE</div>
<p class="ng-displace-sub">Survolez pour amplifier</p>
</div>
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| scale (rest filter) | ~12 | The scale attribute on the feDisplacementMap inside #ng-displace-filter — distortion amplitude in CSS pixels at rest. Suggested range: 6–18. |
| scale (strong filter) | ~28 | The scale attribute on the feDisplacementMap inside #ng-displace-filter-strong — amplitude on hover. A rest-to-strong ratio of 1:2.3 gives a natural progression. |
| baseFrequency | 0.04 | Spatial frequency of the feTurbulence (same value in both filters). Lower = coarse organic noise; higher = fine digital grain. Typical range: 0.025–0.08. |
| numOctaves | 4 | Number of octaves in the feTurbulence — higher = richer fractal detail but more GPU cost. 2–3 for a smooth real-time effect, 5–6 for a highly detailed texture on static content. |
| seed | 2 | Random seed of the feTurbulence (integer 0–9999). Changes the noise shape without modifying its density. Essential to differentiate two instances on the same page and avoid identical patterns. |
| transition: filter .3s | .3s | Duration of the CSS transition on .ng-displace-text. Extend to .5–.8s for a dramatic reveal, reduce to .1s for a sharp snap. Remove entirely for an instant switch. |
| font-size (.ng-displace-text) | 2.5rem | Perceived distortion scales with font size — increasing the size makes the displacement more dramatic at a constant scale. No need to raise scale if you are already enlarging the text. |
FAQ
scale directly via CSS is not standardised. Declaring two filters with different scale values and toggling between them via :hover + transition: filter is the most compatible technique: Chrome and Edge interpolate intermediate values, Firefox and Safari cross-fade, but in both cases the result is visually smooth and requires zero JS.#ng-displace-filter blocks on the same page would collide (only the first would be used). Rename the filters in the second instance with a suffix: #ng-displace-filter-2 and #ng-displace-filter-strong-2, and update the matching CSS rules. Also change seed to get distinct noise patterns.filter: url(#ng-displace-filter) applies to any HTML element: image, video, <div> with a background, inline SVG. On images the distortion produces a refraction or warped-glass effect; on shapes with sharp edges, contours fragment into organic patterns. Lower scale for large surfaces — a high value creates transparent artefacts at element edges.