Image diffing using CSS

Since the last post on CSS was popular here is another simple CSS trick that I found useful in the past.

Let’s say we want to find the difference between these two images:

You can do this by simply inverting the colors and then stacking them together at 50% opacity. This can be achieved with a single CSS filter:
-webkit-filter: invert(100%) opacity(50%);

What you should get back is a gray image except for places where the two images differ. This works because inverting will flip the color (255 - c) and opacity will blend the two colors equally (c1 + c2 / 2). So the resulting color is ((255 - c1) + c2) / 2 which is just rgb(127.5, 127.5, 127.5) whenever the overlapping pixel colors c1 and c2 are the same.

Firefox 34 and older doesn’t support this but you can fallback to an equivalent SVG filter:
filter: url("data:image/svg+xml;utf8,<svg xmlns=''><filter id='invert' color-interpolation-filters='srgb'><feColorMatrix color-interpolation-filters='srgb' in='SourceGraphic' type='matrix' values='-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 0 0.5'/></filter></svg>#invert");
Or use mix-blend-mode: difference which actually produces prettier diffs but isn’t supported on Chrome. EDIT(10-2015): Ed in the comments below verified that mix-blend-mode now works on Chrome too! Check out his example.

Doing the visual diff using pure CSS is nice because it is possible even if you don’t have access to the raw pixel data (which is usually only available by loading the image into a canvas or using Chrome extension’s captureVisibleTab). But with CSS you can do a visual diff of any element as long as you can overlap things on top of it.

In particular, let’s say your designer mocked up something in Photoshop and gave it to you as a png to build. To layout elements matching the design, the usual workflow might involve manually measuring dimensions or overlaying a semitransparent mockup as a template. This process is usually pretty tedious since humans are surprisingly bad at detecting changes so you might miss subtle differences between the design and what you built.

So you can use this CSS trick to get a quick visual diff instead. For example, let’s say someone gave you a screenshot of and asked you to replicate it. To help position things you can overlay the inverted mock (see first section of the js tab) and then tweak the dimensions/margin/padding in inspector until everything is aligned:

See the Pen vEGmKR by Franklin Ta (@fta) on CodePen.

When everything is solid gray, you know you got everything pixel perfect!