Masking and coloring product images using CSS and SVG

Mads Stoumann - Jul 24 '22 - - Dev Community

If you have a product that's available in several colors, it can be cumbersome and expensive to take pictures of each variant.

Luckily, we can use CSS and SVG to mask a single image.

In this tutorial, we'll create a mask for the "product"-part of an image, so we can replace it's color. We'll also remove the background of the image, so we can add our own.


Initial steps

1.
Find a useable image. I searched for "white t-shirt" on pexels.com, and found this image:

Person in a white t-shirt

2.
Then I removed the background using remove.bg (you get 1 free credit per month, so use it wisely!)

3.
I converted this image to webp, using an online converter.

4.
Then I opened the converted image in Vectornator, a great, free vector-editor – and added a path using the Pen tool (for clarity, I added a layer behind the image with a solid background-color):

Path in Vectornator

5.
Finally, I exported the mask to svg, and cleaned it up using SVGOMG.

Phew! A lot of steps, but the only time-consuming step is the "masking" in Vectornator. If you need to do this for a lot of products, consider hiring a specialist on Fiverr or similar.


Now for the fun part! First, we need some markup:

<figure>
  <img src="image.webp" alt="Text" />
  <div></div>
</figure>
Enter fullscreen mode Exit fullscreen mode

For the figure-tag, we'll add a few CSS Custom Properties, to set the t-shirt-color in hsl():

figure {
  --h: 168;
  --s: 40%;
  --l: 65%;
}
Enter fullscreen mode Exit fullscreen mode

We want to set the background to the contrast-color of the t-shirt-color. That equals rotating the hue (--h) 180 degrees.

To make it a bit more interesing, we create a gradient with subtracted saturation (20%) for the first color, and subtracted lightness (20%) for the second:

figure {
--_bg: linear-gradient(15deg,
  hsl(calc(var(--h) + 180),
  calc(var(--s) - 20%),
  var(--l)), 
  hsl(calc(var(--h) + 180),
  var(--s),
  calc(var(--l) - 20%)));

  background: var(--_bg);
}
Enter fullscreen mode Exit fullscreen mode

Let's try it out, with different --h-values:

Colored background

Cool - now, let's color the t-shirt using a mask.


Enabling the mask

div {
  background-color: hsl(
    var(--h),
    var(--s),
    var(--l)
  );
  inset: 0;
  mask-image: url('mask.svg');
  mask-position: center;
  mask-repeat: no-repeat;
  mask-size: 100%;
  mix-blend-mode: multiply;
  position: absolute;
}
Enter fullscreen mode Exit fullscreen mode

Note: For Chrome and Safari, you need to add -webkit-prefixes to all the mask-properties.

Final result

Cool! Play around in Dev Tools with the three colors variables: --h, --s and --l.


A note on the SVG-mask

To be honest, I'm not very good at masking – and I've only used Vectornator a couple of times.

To make up for my masking-skills, I decided to make the mask a bit blurry, by adding a Gaussian blur to the svg:

<filter id="f1" x="0" y="0">
  <feGaussianBlur
    in="SourceGraphic"
    stdDeviation="3" />
</filter>
Enter fullscreen mode Exit fullscreen mode

And then, in the path itself:

<path filter="url(#f1)" ...>
Enter fullscreen mode Exit fullscreen mode

And that's it!

Here's a Codepen with added controls, so you can play around with the hsl-values:

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player