I'm Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with HTML, CSS and SVG. To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

my books

Pro CSS3 Animation book coverPro CSS3 Animation, Apress, 2013

my other blogs

Massive Head CanonMassive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

The New DefaultsThe New Defaults — A Sass color keyword system for designers.

CSSslidyCSSslidy — an auto-generated #RWD image slider. 3.8K of JS, no JQuery.

Using CSS mix-blend-mode for Better Product Photos

Making product customisation and visualisation as easy as adding a link

Visualizing products with multiple options is always challenging: customers expect to view every variation of their purchase, but making those options available usually involves a lot of PhotoShop work, multiple images, and custom JavaScript.

mix-blend-mode is the equivalent of background-blend-mode for arbitrary HTML elements: it controls how a layer affects the appearance of elements underneath it, using the principles of Adobe’s Blend modes. I’ll share much more information about mix-blend-mode in future articles, but I thought a practical demonstration using progressive enhancement principles would be a good place to start.

Let’s use a fashion photograph as an example. The pinstripe suit shown might have three color options: ivory (the default), blue and charcoal.  The basic markup would look something like this:

<div id="suit">
<section>
      <h1>The Modern Pinstripe</h1>
</section>
<p id="coloroptions">Available in: 
<span data-value="#00f">Blue</span>
<span data-value="#fff">Ivory</span>
<span data-value="#333">Charcoal</span>
</div>

We’ll come to the <span> elements and data attributes in a moment. For right now, it’s worthwhile to note that a good rule of thumb for progressive enhancement is that the DOM will validate both before and after we apply any JavaScript.

I’m placing the image in a <section> background for slightly easier layering and scaling, although it could readily be a real image:

#suit { 
position: relative;
padding-top: 70%; 
background-image: url(modern-pinstripe.jpg);
background-size: contain;
}

background-size: contain ensures that the background image always fills the available space without being stretched; padding-top is used to make sure that the <section> is the correct aspect ratio to contain the image and the SVG we’re about to add.

Painting By Numbers

The first step to making the color overlay is the same process that we would use to retouch the photograph: create a selection. I used the magnetic lasso in PhotoShop and touched up the result using Quick Mask, but there are many possible methods.

Once the selection is complete, I saved it as a path in PhotoShop and copied it into Illustrator as a Compound Path, using an Artboard with the same dimensions as the original image.  Exporting the result as SVG will give me a result that looks something like this:

SVG overlay

The SVG code is placed directly inside the <section>:

<section>
      <h1>The Modern Pinstripe</h1>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 838" id="suit-overlay">
<path d="M988.2,603.8c-1-0.4-0.3-0.4-0…. />
</svg>
</section>

…and then styled using CSS so that the SVG is responsive, but does not display by default:

#suit svg { 
      position: absolute; 
      width: 100%;
height: 100%;
      top: 0;
display: none;
}
#suit svg path {
      fill: transparent;
}

This creates our initial conditions: a product image with a description of available colors.

Mixing It Up

The SVG overlay matches the area of the suit in the product image, but to recolor the image successfully, we must make the SVG a blending layer:

#suit svg { 
      mix-blend-mode: multiply;
}

The image won’t change, as the SVG is still invisible. Let’s change that with some JavaScript at the end of the document:

function changecolor() {
      suitpath.style.fill = this.value;
}
function suitstyles(element) {
 element.addEventListener('click', changecolor, false);
}
var suit = document.querySelector("#suit-overlay"),
suitpath = suit.getElementsByTagName("path")[0],
coloroptions = document.querySelectorAll("#coloroptions span");
supportsBlend = CSS.supports("mix-blend-mode", "multiply");
if (supportsBlend == true) {
      suit.style.display = "block";
      for (var i=0;i<coloroptions.length;i++) {
            var buttonconvert = document.createElement("button");
            buttonconvert.innerHTML = coloroptions[i].innerHTML;
            buttonconvert.value = coloroptions[i].getAttribute("data-value")
            coloroptions[i].parentNode.replaceChild(buttonconvert, coloroptions[i]);
      }
      var buttons = [].slice.call(document.getElementsByTagName("button"));
buttons.forEach(suitstyles);
}

A quick breakdown of the script, starting with the variables:

  • suit and suitpath reference the SVG elements on the page.
  • coloroptions collects together all the <span> elements in the product description paragraph.
  • CSS.supports is the JavaScript equivalent to the CSS @supports rule: it detects if the browser supports mix-blend-mode. If it does, the script sets the SVG to display and converts each of the <span> tags into <button> elements, with the data-value attributes being converted into the value of each button. (If you wanted to be less conservative, as not all browsers support @supports yet, you could skip this condition and create another option for IE users, who do not yet have mix-blend-mode
  • The new buttons are then collected together, converted into a true JavaScript array, and a click event applied to each, so that when the user clicks on a button the SVG path is color-flooded with the appropriate hexadecimal color.

Using mix-blend-mode allows us to create easy customization of products: if a new color is made available, we just add a <span> with the appropriate data-value to the paragraph. To provide the ultimate in customization, we could provide an HTML5 color input, allowing the customer to select any shade they want.

Photograph by  Shinji Watanabe, licensed under Creative Commons. Explore the code for the fashion visualization on CodePen

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.