How to Dynamically Change the Colors of Product Images using CSS Blend Mode and SVG

Learn a simple technique for adding a color swap functionality to your product images by creating an SVG and applying a mix-blend-mode to the composition.

To better explain that title right off the bat, here’s what we’re about to learn, and it’s easier than you think. Give it a go, change the shirt from yellow to blue by using the color picker in the bottom right corner:

See the Pen
Dynamic Colour Picking – Part 4
by Kyle Wetton (@kylewetton)
on CodePen.

You can see another example of this in the demo Color this sofa! where you can change the color of a sofa and its background gradient.

Imagine this for a second: You’ve finally done it, over the summer, you and a buddy are about to launch your screen printing start up out of your shared house, it’s not much, but you have a working setup and a few local bands and non-profits have already shown interest. Your supplier for t-shirts, pants, hats and $2 sunglasses is exactly what you’ve been looking for, they supply 25 colors per item and you couldn’t be happier that your website has finally been signed off. Now all you need to do is upload some photos of your merchandise! Problem is, 25 colors per item? Thats 125 different options, how do you approach this?

You’ve seen this often happen online, and the solution is almost always a picture of one color, and little dots that represent the rest of the options.

Color options example

And for good reason too, nobody wants to spend the time or money photographing someone wearing over 125 items, so like the masses before you, you get your friend to model one color of each and let your potential customer use their imagination to determine what the others look like based on a dotted color.

The reason for the preamble is to be clear about why the solution you’re about to learn is so valuable. With just a small to moderate amount of setup, you can take one photo of your product and let your web page dynamically change the color of a t-shirt, hat, sunglasses and pants to any color you throw at it, in fact, if you wanted to you can change all of these items independently on the same image, on the same web page, without it reloading.

So what’s happening here? What magic is this?

It’s an SVG element with an image behind it, and a vector shape (path element) drawn over the part(s) you want the color to change. You simply change the fill color of your path element, and use the CSS property mix-blend-mode: multiply to stain that color onto the image.

Let’s Get Started

Download this photo if you’d like to follow along.

Photo by Alex Holyoake on Unsplash

This part is important: you want to know the dimensions of your photo, and it should ideally be something customized to your website’s needs (a square photo at 1000x1000px for instance). My example is 1920x1280px and it’s a dimension we should take note of when we set this up.

Second, the part of the photo you’re changing needs to be white. Our t-shirt is white, if we were changing a sofa material or the cladding on the side of house, the material and cladding needs to be white.

Part 1: Creating the Vector Shape / SVG Markup

The easiest way to do this is via Adobe Illustrator, and it’s the program we will be using here, but if you don’t have that, you can follow along using the free online alternative Method Draw.

Create a canvas at the same dimensions as your photo (1920 x 1280px) and place your photo directly centred in the frame.

Tip: Lock this photo so that it doesn’t budge.

imported-locked
The image has the Lock enabled in the layer panel to the right.

Using the Pen Tool, draw a path around the t-shirt, be sure to zoom in as much as possible and really focus on getting this path as close to pixel perfect as possible. It sounds daunting, but doing this by hand will result in the most accurate final outcome and the Pen Tool is something that while takes a bit of practice, gets faster the more you use it.

clear-cut-4

Don’t know how to use the Pen Tool? here’s a great instructional video (~5min)

A couple pointers

  • Undo is your friend here, it’s easier to undo an anchor and try again than it is to move it into the correct place
  • For what we want to do, having it a pixel bigger than the t-shirt is better than having it cutting into the t-shirt a pixel
  • Disable both stroke color and fill color while you do this, they seem to get in the way

Remember, you can make multiple paths around different sections of the photo if you for instance wanted to change a hat color as well as the t-shirt.

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

Exporting Your SVG

You now have your path around the shirt, fill it with any color to see the result, you can safely delete the underlying photo leaving you with this:

the-path

When we export this SVG, it’s important that Illustrator keeps the white space around the shape, because the photo will fill this area on our web page.

If you’re using Method Draw instead, go to View > Source, this is done by default

This isn’t done by default in Illustrator though, so we need to use File > Export > Export for Screens which exports the whole artboard, keeping the relative position intact.

export-panel

Export the SVG as a file to your computer, wherever makes sense to you. Open this file with your text editor and you’ll see the SVG markup inside. This is the HTML that we will use on our webpage. Copy all of it.

copy-svg

Cleaning the SVG Markup (Optional)

Head to SVGOMG.

Paste your markup and click on Markup, your SVG is now cleaner than what Illustrator exported.

paste-markup

svgomg

If you’ve drawing multiple paths around different items that should be color changed independently, its worth disabling the “Merge Paths” option. This can be helpful in situations like our example though, where the shirt is two paths in the original SVG markup and ideally we’d want this as a single path element.

Copy the SVG markup, then start a fresh CodePen.

If you weren’t following along you can Fork my pen here:

See the Pen
Dynamic Colour Picking – Part 1
by Kyle Wetton (@kylewetton)
on CodePen.

Before we do anything, I recommend adding these styles to your CSS

body,
html {
  margin: 0;
  padding: 0;
  height: 100%;
}

*,
*:before,
*:after {
  box-sizing: border-box;
}

Part 2: The SVG and the Image

You want to add two ID’s to your HTML, these will be up to you, but for this example let’s use product-svg for the SVG element and product-shape for the path element.

Wrap your SVG inside a parent div, we will add the ID container for this tutorial. Add the position: relative style for the container.

#container {
  position: relative;
}

Your HTML should now look like this

<div id="container">
<svg id="product-svg">
<path id="product-shape" d="..." />
</svg>
</div>

Add these styles to the product-svg element.

#product-svg {
  position: relative;
  z-index: 2;
  mix-blend-mode: multiply;
}

mix-blend-mode:multiply is the property that “stains” the color into the background image.

Inside the container, add the image as second element beneath the SVG. We’ve given it the ID background-image for this tutorial.

<div id="container">
<svg id="product-svg">
<path id="product-shape" d="..." />
</svg>

<img id="background-image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1376484/alex-holyoake-unsplash_hkda7r.jpg" alt="">

</div>

Add these styles for the background-image element.

#background-image {
  position: absolute;
  top: 0;
  width: 100%;
  height: auto;
}

The two child elements in our container should now be stacked on top of each other.

It’s important that the image never shifts in size or position compared to the SVG, we want to keep them the same size aspect ratio at all times.

In your SVG, your path element will likely have a fill attribute that includes the HEX of the color you added in Illustrator. Let’s remove that attribute and add these styles to the product-shape element.

#product-shape {
  fill: #DBED64;
}

The fill property is the HEX color we will dynamically update in the next step.

Your project should look like this:

See the Pen
Dynamic Colour Picking – Part 2
by Kyle Wetton (@kylewetton)
on CodePen.

Part 3: Changing the Color on the Fly

Its not a stretch from here conclude that the possibilities from here are massive, all you have to do is use JavaScript to change out the fill color of your path element to any color you want, (or any color you have for offer).

If you’re comfortable with JavaScript, and you have ideas on how you would update the fill property, you’ve learned the fundamentals and can safely head off and continue on your own, if however you’d like some insight in how to do that, the rest of this tutorial covers a basic function that will let you update the fill property.

I’ve prepared some color options for us. Copy and paste the HTML below your container, and copy and paste the CSS at the bottom of your CSS.

HTML

<div class="colors">
  <div class="color" style="background-color: #e1e851" data-hex="#e1e851"></div>
  <div class="color" style="background-color: #8cd147" data-hex="#8cd147"></div>
  <div class="color" style="background-color: #4a9ccf" data-hex="#4a9ccf"></div>
  <div class="color" style="background-color: #661f45" data-hex="#661f45"></div>
  <div class="color" style="background-color: #1e2024" data-hex="#1e2024"></div>
</div>

CSS

.colors {
  display: flex;
  position: fixed;
  bottom: 2em;
  right: 2em;
}

.color {
  height: 36px;
  width: 36px;
  margin-left: 0.5em;
  border-radius: 18px;
  box-shadow: 0px 4px 10px rgba(0,0,0,0.3);
  border: 2px solid #aaa;
  cursor: pointer;
}

Lets write a simple changeColor function that takes a path and a HEX

JavaScript

// Reference the color shape that was drawn over the image
const overlay = document.getElementById("product-shape");

// Click on a color

var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
  el[i].onclick = changeColor;
}

function changeColor(e) {
  // get the hex color
  let hex = e.target.getAttribute("data-hex");
  // set the hex color
  overlay.style.fill = hex;
}

Try it out!

See the Pen
Dynamic Colour Picking – Part 3
by Kyle Wetton (@kylewetton)
on CodePen.

Using these principles you can imagine how useful it could be for a store to be able to show actual images of all of their color options, just from an array of HEX colors. Wild.

The Fine Print

Browser support for this feature is always growing, but you should know that as of now (mid-late 2019), IE, Edge, and unfortunately Chrome for Android (but only for Android) currently don’t support the mix-blend-mode property. More info here

Worth mentioning that Mozilla considers Safari and and Safari on iOS to not support mix-blend-mode on SVG element, however it appears to work fine in both.

Final Word

As a parting gift, here’s a more complete CodePen. I’ve used the library jscolor which sends a HEX to our changeColor function. And a very useful function that will take our SVG, and simulate the CSS property background-size: cover inside a parent div. This function is worth investigating if you’re planning on implementing this feature on a website where the photo + SVG is inside a fluid parent.

See the Pen
Dynamic Colour Picking – Part 4
by Kyle Wetton (@kylewetton)
on CodePen.

Kyle Wetton

Working as a front-end developer from Auckland, New Zealand, I love CSS, JavaScript, hot wings and guitars.

Stay in the loop: Get your dose of frontend twice a week

👾 Hey! Looking for the latest in frontend? Twice a week, we'll deliver the freshest frontend news, website inspo, cool code demos, videos and UI animations right to your inbox.

Zero fluff, all quality, to make your Mondays and Thursdays more creative!

Feedback 14

Comments are closed.
  1. This tutorial is unique and awesome, will definitely try it out.
    What happened to the download option for Codrops resources?

    • Hi Michelle, thank you for your feedback! We figured since the demo is on Codepen, you can easily download the source from there (bottom right “Export .zip”). Hope this helps, cheers, ML

  2. As an alternative for those looking for a more cross-compatible method of going about this idea – though not without its own caveats – you could take the image into Photoshop, create your Pen Tool path around the item of clothing to colour, desaturate this area and tweak the levels until the majority of the material is White with some grey shadows. Mask out the area within the path so that the areas that were true White shows as transparent with the grey shadows semi-transparent (less transparent as the shadows go darker, make sure to hide/remove any background layer so you can see the checkboard to indicate transparency). Save the file as a PNG-24 with transparency enabled, then simply create a container/wrapper div around the image with a background-color that changes based on the colour selected (you’ll probably need some Javascript for that). This method would also allow you to use a pattern or gradient to fill the clothing area. The only thing to be aware of with this method being a PNG-24 can be quite a large file size, unless you take that into account during the initial stages (have a minimal/white background behind the subject, lower resolution, reduce noise, less intricate details that introduce more colour), you could also use a PNG-8 which would be smaller in file size but the transparency tends to have a very aliased White border around (or within) the transparent area, so choose your poison appropriately!

  3. This is a good tutorial. Only problem with real world usage is that we would have to do manual tweaking of color values and their names to match the true colors used for that product. Problem is that “multiply” filter only adds colors on top of underlying ones and some hues would be very hard to match.

    Other than that – good tech demo.

    • Hey Sebastian, its because my pens were private, apologies! Give it a go now and let me know how you get on

  4. Hey Kyle!

    Thanks for this great tutorial. Surprised to see how easy it was, thank for the walk through.

    One quick edit that might be needed is on part 3 in the CSS code there is no mentioned of the `z-index:3;`.

    Thanks again for the article.