Boxy SVG editor comes with built-in support for creation and editing of SVG icon sprites.
You can play with a sample SVG sprite on https://boxy-svg.com/#demo-symbols. Individual icons are shown under "Defs Panel -> Symbols". To edit an icon just double-click its thumbnail. To make part of an icon recolorable, select that part and then click "Fill Panel -> Paint -> Type -> Inherit".
You could then create separate symbols which contain a recolored instance of the original symbol. The underlying markup will look something like this:
hmm, I didn't know you can use fragment identifiers in src attribute, that changes the game quite a bit. I remember looking for stuff like that, though. Not sure why I didn't anything, because it seems like it's been supported for quite a while. I only found the reuse inside svg in the same parent html document.
Fragment identifiers in "src" attribute seem to be supported by all modern browsers, but now I realized my example was wrong - you can reference <view> elements, but not <symbol> elements directly.
To make it work you would have to either replace <img src="sprite.svg#green"/> with <svg ...><use href="sprite.svg#green"></use></svg> or add views to the sprite file:
That makes a lot of sense. If you use some client-side routing (e.g. Next.js), you might be fine, because the page does not reload during navigation. But if you don't, every HTML page will contain all the SVGs increasing the HTML size unnecessarily.
P.S. I actually went ahead and changed the implementation to a separate file on my website after I saw your comment :D
It's something like this (I just quickly took this from my project, not sure if it works in this form now). This one uses the defs/use trick to reuse a path, but you can also just put two different svgs next to each other and not use the defs/use at all.
The icon:
<!-- the icon width is 2x wider, to accommodate both 26x26 variants -->
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="26">
<defs>
<!-- here's the icon defined, you can basically put anything here and
mark it with an id (you can even use another svg) -->
<path id="icon" path="..."/>
</defs>
<!-- first variant with no fill -->
<use stroke="#fff" href="#icon"/>
<!-- second variant with fill, shifted by 26 (dimensions of the icon) -->
<use x="26" fill="#00ACA0" stroke="#00ACA0" href="#a"/>
</svg>
HTML:
<!-- make sure you use dimensions of the single variant -->
<img src="icon.svg" width="26" height="26" class="hover-icon">
CSS:
.hover-icon {
/* make sure that only first block of the image is visible */
object-fit: cover;
object-position: left;
}
.hover-icon:hover {
object-position: right;
}
Btw, for such simple re-colouring I'd probably rather used CSS hue shift filter or similar effect, and kept the SVG "dumb". But for having different shapes or geometric properties this approach is indeed nifty.
Yes, I do that, too. The benefit of using the sprite system is that it's pretty general, so once you have some CSS for it, it's easy to keep adding new icons. CSS filters are usually more special for each case, but I use them too (mostly for brightness and greyscale things that are repeated on multiple places, e.g. tabs or disabled state).
You might want to check out old tech articles, as sprites were a very common approach from roughly 2005-2012-ish. Lots of interesting little techniques.