Of course I overcomplicated things.

Way back when I was looking for a way to have CSS-definable colors for my icons and logos, I stumbled across clip-path and figured it was the way to go. It’s a fantastic technique and I can see myself getting a lot of mileage out of it somewhere down the line, but I ran in to too many issues with it to make it worth my while right now.

Somehow I forgot that it’s possible to directly manipulate SVG elements with CSS.


To recap, I’m looking for a way to define the shape and color of an icon separately, so that I can both quickly change the color while experimenting with color schemes, and change the color during events like mouseovers.

It was the hunt for mouseover techniques that led me to realize how much I had overcomplicated the issue.

Any <path> or <circle> or other kind of shape is going to have a fill attribute associated with it. As luck would have it, these can be manipulated with CSS.

Let’s start off with a simple blue circle:

1
2
3
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
    <circle id="circle1" style="fill: blue;" cx="16" cy="16" r="15" />
</svg>

which produces:

Nice, right?

Note the style attribute: this functions exactly the same as the style attribute in any other HTML element, which means that we can alter it with CSS:

1
2
3
svg #circle2 {
    fill: red !important;
}

There’s one very important detail here that took me a few minutes to catch on to: the id. A simple svg { isn’t going to cut it, no matter how many !importants you throw at it.

Now that we have the fill working, we can alter it further.

1
2
3
4
5
6
7
8
9
svg #circle3 {
    fill: red !important;
}
svg:hover #circle3 {
    fill: green !important;
}
svg:active:hover #circle3 { /*mousedown*/
    fill: orange !important
}

Try it out:

There are a few final things to take note of:

  • the !important is required,
  • the space between the :hover and the id is required,
  • and the :hover selector must be applied to the svg element.

Unfortunately, the last one means that the :hover will be triggered when the cursor passes into the bounding box of the svg, not of the element within the svg. I’m sure there is a way around this, but I haven’t looked into it.