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:
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 supportsmix-blend-mode
. If it does, the script sets the SVG to display and converts each of the<span>
tags into<button>
elements, with thedata-value
attributes being converted into the value of each button. (If you wanted to be less conservative, as not all browsers yet support@supports
, you could skip this condition and create another option for IE users, who do not yet havemix-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.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/XJppvR