<feDisplacementMap> in SVG: warping one image with another

Shifts every pixel of an image using the colour values of a second image, a distortion effect no CSS property alone can produce.
4 min read
Believemy logo

A logo that seems to float underwater, text that looks carved into an uneven surface, a banner that ripples like fabric: these distortions never move a single path by hand, they use a second image as a displacement map.

<feDisplacementMap> reads the colour values of a reference image and uses them to shift, pixel by pixel, another image or shape, creating a controlled relief or distortion effect.


Definition

<feDisplacementMap> is an SVG filter primitive that takes two inputs: a source image to warp (in) and a displacement map (in2). For every pixel of the map, it reads two colour channels picked by xChannelSelector and yChannelSelector, and uses them to shift the matching source pixel, horizontally and vertically.

The scale attribute controls the strength of the shift: at zero the image stays untouched; the higher the value, the more pronounced the distortion. The map texture often comes from a noise generator such as <feTurbulence>, but any image will do.


Main attributes

AttributeRoleTypical values
inImage to warpSourceGraphic or the output of an earlier step
in2Displacement mapOften the output of a noise generator
scaleShift strength in pixelsFrom 0 (no effect) to 40 or more
xChannelSelectorChannel used on the horizontal axisR, G, B or A
yChannelSelectorChannel used on the vertical axisR, G, B or A


Concrete rendering example

The example below generates a displacement map from a noise texture, then applies it to a plain rectangle, which breaks its clean edges and makes it look like crumpled fabric.

HTML
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="fabric" x="-20%" y="-20%" width="140%" height="140%">
      <feTurbulence
        type="fractalNoise"
        baseFrequency="0.02"
        numOctaves="2"
        result="noise"
      />
      <feDisplacementMap
        in="SourceGraphic"
        in2="noise"
        scale="25"
        xChannelSelector="R"
        yChannelSelector="G"
      />
    </filter>
  </defs>
  <rect
    x="20"
    y="20"
    width="160"
    height="160"
    rx="12"
    fill="#22c55e"
    filter="url(#fabric)"
  />
</svg>

The result: the square's edges are no longer straight, as if the shape had been printed on crumpled fabric instead of a flat surface.


Difference from a similar element

<feDisplacementMap> differs from <feColorMatrix> in what it targets: the latter recolours pixels without moving them, while <feDisplacementMap> moves pixels without touching their original colour. Both can be combined in the same filter to warp and tint an image in a single pass.


Common pitfall

Good to know

A filter's calculation box is, by default, only slightly bigger than the shape, with just a 10% margin on each side. With a high scale value, the shift can exceed that margin and end up cut off flat on one edge, an artefact easy to mistake for a bug. The fix is to explicitly enlarge the filter region, for example with x="-20%" y="-20%" width="140%" height="140%" on the <filter> element.


Real-world use case

<feDisplacementMap> shows up in frosted-glass effects, logos that seem to float underwater, titles carved into a stone or wood texture, and more generally anywhere a design wants to break the perfect regularity of a vector shape without redrawing its outline by hand.

  • Crumpled-fabric effect on a banner or a card
  • Text that seems to ripple on a landing page
  • An "underwater" logo for a product section
  • An irregular border in a torn-paper style


FAQ

QuestionDoes the displacement map always have to come from feTurbulence?

No, any image can act as a map, including a gradient, a photo or the output of another filter; feTurbulence is simply the most common source because it produces organic noise without loading an external image.

QuestionWhat happens if the displacement map is smaller than the source image?

SVG neither stretches nor tiles the map: outside the area it covers, it is treated as transparent, which amounts to zero-value colour channels there and often produces an unpredictable result in that spot; it is best for the map to cover the same area as the source to keep a consistent effect across the whole shape.

QuestionCan the scale value be animated for a continuous wave effect?

Yes, <animate> can vary the scale attribute over time, producing a distortion that pulses or ripples without ever reloading an image, an effect that is light on performance and smooth to the eye.

Related terms

Discover our hTML and CSS glossary

Browse the terms and definitions most commonly used in HTML and CSS development.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.