mo.

Coloring an SVG with masks

Published on Aug 20, 2025

We have a lot of SVGs at work that use currentColor for their fill or stroke properties. This is useful for icons that aren’t brand-specific, so they can use different colours when rendered inline.

For example, we can render the same checkmark icon, but control its colours like this:

.my-tomato-icon {
  color: tomato;
}
.my-purple-icon {
  color: rebeccapurple;
}

or this:

This approach is handy, but it has some limitations. One of which I ran into at work today when I tried to use an SVG as a background image. Since the image is an external resource and not in the DOM, we can’t directly control its colour with CSS.

.box {
  color: red;
  background-image: url("image");
  background-repeat: no-repeat;
  background-position: center;
}

One neat way around this obstacle comes from Noah Blon’s blog post on Codepen.

Blon’s solution is to instead use a background colour and then apply the svg as a mask. This causes the background colour to “seep” through the mask:

.box2 {
  height: 100px;
  width: 100px;
  background-color: tomato;
  mask-image: url("image");
  mask-repeat: no-repeat;
  mask-position: center;
}

Hurray!

CSS masks stil feel like a black box to me, but I can already see some useful (if not just fun) applications for them, like this transition between two background images.

.image-transition {
  position: relative;
  width: 400px;
  height: 250px;
  background: url("https://picsum.photos/id/1018/800/600") center/cover;
  overflow: hidden;
  margin: 2rem auto;
}

.image-transition::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("https://picsum.photos/id/1025/800/600") center/cover;
  -webkit-mask-image: linear-gradient(
    to right,
    black 0%,
    black 50%,
    transparent 50%,
    transparent 100%
  );
  -webkit-mask-size: 200%;
  animation: reveal 4s infinite;
}

With two background images (one in an :after element) covered by a mask, we can animate the mask itself to “reveal” the second image: