Set Fill Color of SVG Background-image

A quick guide explaining how to change the color of an SVG when it’s used as a CSS background-image.

If you want you can jump to the code, else we can explore how this works together.

SVG Background Color Fill Demo

We’ll start with a live demo, focus, hover, or click on the circle below and the background color will animate.

I’ll let the cat out of the bag.

This is just a normal button with an SVG used as a CSS mask

Instead of changing the fill color of the SVG we change the background-color of the button. But that shouldn’t spoil the fun as it opens up a world of possibilities but we’ll get to that.

Using An SVG As A CSS Mask

We can see our cool smiley SVG below 😎

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <g
        stroke-linecap="round"
        stroke-width="4"
        stroke="rgb(0, 0, 0)"
        fill="none"
    >
        <circle cx="12" cy="12" r="10" />
        <path d="M7 11 H17" />
    </g>
</svg>

What’s amazing about the timeline we live in is that we can pass the SVG to the CSS url() function without base64 encoding it or escaping all kinds of characters.

  1. Prefix the SVG with data:image/svg+xml,
  2. Add some structure by ending a line with \
  3. Just like that a readable SVG has appeared in our CSS.

Allright, let’s first assign the SVG to the background property so we can see it, we’ll turn it into a mask in a couple minutes.

button {
    /* ...Other styles */

    /* Color */
    background-color: Crimson;

    /* Store the SVG in a variable so it's easy to re-use */
    --svg: url('data:image/svg+xml,\
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">\
        <g stroke-linecap="round" stroke-width="4" stroke="rgb(0, 0, 0)" fill="none">\
            <circle cx="12" cy="12" r="10"/>\
            <path d="M7 11 H17"/>\
        </g>\
    </svg>');

    /* Assign the SVG variable */
    background-image: var(--svg);
}

button:hover,
button:focus {
    background-color: Turquoise;
}

button:active {
    background-color: Gold;
}

We can interact with the live demo below to see the SVG has loaded and the styles are correctly applied.

Now it’s time to remove the background property and assign the --svg variable to the mask property.

The black parts of the SVG will be the visible parts of the element and the transparent parts will become invisible.

button {
    /* ...Other styles */

    /* Chrome, still requires prefix in 2022 */
    -webkit-mask: var(--svg);

    /* Firefox and Safari */
    mask: var(--svg);
}

Tadaa! 🥳

If you have trouble getting the mask to work, a handy trick is to temporarily assign the mask to the background-image property.

This allows us to visually see where the black and transparent parts of your mask are, this becomes especially useful when building more complex masks.

Any Background Goes

Because we’re masking the button we can use any background style or effect we can think of.

The Complete SVG Background-image Style Code Snippet

You can find the copy button on the right hand side of the code snippet, enjoy!

<button type="button">I'm a cool circle button</button>

<style>
    button {
        /* Base styles */
        display: block;
        width: 4rem;
        height: 4rem;
        border: none;
        cursor: pointer;

        /* Hide button caption text */
        overflow: hidden;
        color: transparent;

        /* The fill animation */
        background-color: Crimson;
        transition: background-color 0.2s;

        /* Store the SVG in a variable so it's easy to use */
        --svg: url('data:image/svg+xml,\
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">\
            <g stroke-linecap="round" stroke-width="4" stroke="rgb(0, 0, 0)" fill="none">\
                <circle cx="12" cy="12" r="10"/>\
                <path d="M7 11 H17"/>\
            </g>\
        </svg>');

        /* Chrome, still requires prefix in 2022 */
        -webkit-mask: var(--svg);

        /* Firefox and Safari */
        mask: var(--svg);
    }

    button:hover,
    button:focus {
        background-color: Turquoise;
    }

    button:active {
        background-color: Gold;
    }
</style>

Conclusion

We learned a nice trick where we used the CSS mask property to change the fill color of a SVG when it’s used as a background-image

On top of that we learned that the mask property is identical to the background property so we can switch them out to make debugging the mask image easier.

I share web dev tips on Twitter, if you found this interesting and want to learn more, follow me there

Or join my newsletter

More articles More articles