Skip to content

Displacement & Masking

1 / 14

Displace

Coordinate Refraction & Mask Stencils
Glass refraction
Masked offset
⇌

Displacement & Masking

Most image effects on the web are baked in. Someone opens the photo in an editor, applies the look and exports a new file. That works until the client uploads their own photos, and suddenly half the site looks designed and the other half looks like it was screenshotted out of a PowerPoint deck.

This is about doing it the other way round: effects that live in the browser and apply to whatever image, video or element ends up on the page. No editing, no preprocessing, no special exports. For designers that means a look you can count on, whoever supplies the images. For developers it means a filter and a few lines of CSS (and in one case a small script).

There are two techniques here, and they work in opposite ways. Displacement bends the image: every pixel gets pushed a little, the way textured glass bends what's behind it. Masked offset doesn't bend anything. It lays a slightly moved copy of the image on top and cuts it into lines, so the picture seems to break along a pattern.

Contents

  1. Introduction
  2. Glass refraction
  3. Masked offset
  4. Which one, and where it falls apart

Glass refraction

Think of a ribbed glass door or a glass block wall. The image behind it is all there, it's just pushed around. The browser can do the same with an SVG filter, and that filter can be put on any element: a photo, a video, even text.

The filter needs a second image to work from, called a displacement map. It's never shown. Its colours are instructions: the amount of red says how far a pixel moves sideways, and in which direction, and green does the same up and down. Plain grey means stay put. Fill the map with vertical waves and you get ribbed glass. Fill it with a grid of little ramps and every square becomes its own tiny lens.

Pick a tile to see each kind of glass. Adjust (or D) opens the settings, where you can change the photo, the rib width and how hard the glass bends.

Putting it on your own site

The useful part is that nothing here touches the images themselves. Assuming you can add CSS and a snippet to every page (most sites and CMSes let you, even when the templates are off limits):

  1. Make the map once. Either draw it as an image, or let a script draw it at the right size. Ribs are just a repeating gradient (like the first map above), so this is the easy bit.
  2. Add the filter to the page once. It's a small, invisible SVG that holds the map and the displacement step.
  3. Point it at your images with one CSS rule. Every image that matches gets the glass, including the ones uploaded next week.
<!-- once, anywhere on the page -->
<svg width="0" height="0">
  <filter id="glass">
    <feImage href="ribs.png" result="map" preserveAspectRatio="none" />
    <feDisplacementMap in="SourceGraphic" in2="map" scale="40"
      xChannelSelector="R" yChannelSelector="G" />
  </filter>
</svg>

/* and one rule */
.article img { filter: url(#glass); }

scale is the strength in pixels: 40 means pushing up to 20px either way. A map image gets stretched to fit each element, so a wide photo gets wider ribs. If that matters, a script can draw the map at each image's real size, which is what this page does.


Masked offset

This one looks like the image has been sliced and nudged out of place. It's simpler than it looks. There are two copies of the same image. The bottom one stays put. The top one is moved a few pixels (or zoomed in slightly) and then cut with a mask, so you only see it through a pattern of lines.

Wherever a line crosses an edge in the photo, the two copies don't match, and that's what you see. On a flat wall or a clear sky there's nothing to mismatch, so the pattern disappears. Zooming the copy from a chosen point works nicely on portraits: the face stays lined up while everything around it breaks.

Same as above: pick a tile, and open Adjust to change the pattern, how far the copy moves and where it zooms from.

Putting it on your own site

This is the harder one to bolt on, because it needs the image twice. If you can't change how images are output, a small site-wide script can do the copying:

  1. Make the pattern once. An image (or a script drawing) where the lines are solid and everything else is transparent.
  2. The script finds your images and puts a copy on top of each one. The original markup stays as it is.
  3. CSS does the rest: it moves the copy and cuts it with the pattern.
for each image in .article:
  wrap it in a container
  add a copy of it on top (decorative: hidden from screen readers)

.copy {
  transform: translate(6px, 6px);   /* or scale(1.03) from a point */
  mask-image: url(lines.png);
}

There's also a way without the copy: the whole trick fits in an SVG filter, set up exactly like the glass. It loads the pattern, shifts the element, keeps only the parts inside the pattern and lays them over the original. One filter, one CSS rule, nothing duplicated. The catch is that it can only shift, not zoom, and it inherits the glass filter's costs and Safari problems. I didn't use it here, but it's worth knowing about:

<filter id="offset">
  <feImage href="lines.png" result="pattern" />
  <feOffset in="SourceGraphic" dx="6" dy="6" result="moved" />
  <feComposite in="moved" in2="pattern" operator="in" result="cut" />
  <feMerge>
    <feMergeNode in="SourceGraphic" />
    <feMergeNode in="cut" />
  </feMerge>
</filter>

Which one, and where it falls apart

Both do the same job well: they give every image on a site a shared character without anyone opening an image editor. They just get there with different trade-offs.

GlassMasked offset
Adding it to a siteOne filter and one CSS ruleA copy of each image (small script), or the filter version
Cost to runEvery pixel, again whenever the content changesCheap: moving and masking
Animating itGets heavy fastSmooth
VideoFine in ChromeTwo players kept in sync
SafariSlow, partly supportedWorks fine

Safari is the weak spot for the glass (surprise, surprise). Its SVG filters are a lot slower, and filters applied from CSS only partly work there (the map has to be referenced in one particular way). That could change with any future update. So perhaps one day the notice at the top might be wrong in a good way.

Both also need something to work with. Clear edges and shapes look great. A flat sky or a plain wall looks like nothing happened, because bending or shifting a flat colour changes nothing. And both are decoration: great for hero images, galleries and backgrounds, not for product photos or anything people need to read closely. If you make them move, respect reduced motion.

So it comes down to what you're allowed to touch. If you can add CSS and a snippet, start with the glass. If you can also run a small script, the offset is the cheaper one to live with. Either way, nobody has to open Photoshop.

All demos
Next[REDACTED]