Masking and coloring product images using CSS and SVG
Tags: css, svg, tutorial, webdev
Published: 2022-07-24 16:45:50

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](https://www.pexels.com/da-dk/foto/mode-person-model-blondine-1304647/):

![Person in a white t-shirt](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/210ymupwfwml78hmd9pf.jpg)

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

**3.**
I converted this image to webp, using an [online converter](	https://ezgif.com/jpg-to-web).

**4.**
Then I opened the converted image in [Vectornator](https://www.vectornator.io/), 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ct7jvkb3vdlk91m7ne7i.png)

**5.**
Finally, I exported the mask to `svg`, and cleaned it up using [SVGOMG](https://jakearchibald.github.io/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](https://fiverr.com/) or similar.

---

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

```html
<figure>
  <img src="image.webp" alt="Text" />
  <div></div>
</figure>
```

---

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%;
}
```
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:

```css
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);
}
```

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

![Colored background](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi670zni86jne3byaewo.png)

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

---

## Enabling the mask

```css
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;
}
```

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

![Final result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghllz1oxj6jr5qme0n9p.png)
 
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](https://en.wikipedia.org/wiki/Gaussian_blur) to the `svg`:

```xml
<filter id="f1" x="0" y="0">
  <feGaussianBlur
    in="SourceGraphic"
    stdDeviation="3" />
</filter>
```
 
And then, in the `path` itself:

```xml
<path filter="url(#f1)" ...>
```

And that's it! 

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

{% codepen https://codepen.io/stoumann/pen/GRxvgPZ %}