DEV Community

Cover image for Masking and coloring product images using CSS and SVG
Mads Stoumann
Mads Stoumann

Posted on

Masking and coloring product images using CSS and SVG

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:

Top comments (7)

Collapse
 
stackedboost profile image
Peter Hallander

Really clever approach — using SVG masks + CSS custom properties to swap color variants from a single image cuts down on photo shoot overhead significantly. The mix-blend-mode: multiply trick for applying color over a white background is elegant.

One thing I've seen trip up merchants who try to DIY this on Shopify: they invest in the technical color-swap solution but still have inconsistent base images — different backgrounds, padding, brightness levels from different photo shoots — and the CSS coloring layer ends up highlighting rather than hiding the inconsistency.

We built a Shopify app called Eye Catching (apps.shopify.com/beautiful-brands) that tackles the base consistency problem: standardizing backgrounds, padding, and applying overlays and badges across product catalogs automatically. The CSS color-swap technique you've shown pairs well with it — consistent base images make the masking much cleaner. I'm a developer at Stackedboost. Nice technique, bookmarking the Codepen.

Collapse
 
link2twenty profile image
Andrew Bone

I made Shaggy from Scooby Doo

shaggy

Collapse
 
madsstoumann profile image
Mads Stoumann

😂

Collapse
 
zerooeffect profile image
Damon Cahill

love ur work dude!

Collapse
 
madsstoumann profile image
Mads Stoumann

Thank you!

Collapse
 
akinzeman profile image
akin zeman

how to apply only to the masked t-shirt ? (ignore background)

Collapse
 
madsstoumann profile image
Mads Stoumann

Just remove the background from the figure-tag