0
votes

So I have a sprite SVG with lots of icons laid out in a grid like pattern (each has it's own 30 x 30 block) and until now I have been using this as a background image which has been working fine.

I have recently discovered that you can use CSS classes to change the fill colours of individual paths contained within the SVG. This would be great because I have a few chevron icons in my sprite and I've had to copy & paste them a bunch of times to get different coloured chevrons. It would be great if I could just have one chevron and change the colour dynamically.

I am aware that this cannot be done with the background-image method and the SVG has to actually be embedded on the page.

I'm curious as to what the best method for this is because I have quite a few icons in my sprite svg and rendering this all on the page just feels a bit painful.

Regardless, I had a go.

For this example, my sprite is 60 x 30, so there are two icons on it, I want the second one so my origin is -30, 0.

<object type="image/svg+xml" data="sprite-icon-test.svg#House1" width="30" height="30">Your browser does not support SVG</object>

I can't see the second icon because I can't specify an offset.

I was following the technique shown on this page http://www.sitepoint.com/use-svg-image-sprites/ but they place all their sprites on top of each other which would work fine but I don't want to put them all on top of each other because I have a lot of icons and it'll just be a nightmare.

Can anyone provide an alternative/way around this so that I can still apply styles to paths with CSS but retain my grid format. Also, embedding the whole SVG object in the page every time I want to use an icons seems a bit crazy when I have a large sprite with lots of icons on it and I imagine this would be terrible for performance so can anyone provide any information on whether this is avoidable or not?

Update:

This is where I've got to so far.

<html>
<head>
    <title>SVG Test</title>

    <style>
        .red {fill:#ec1937;}
    </style>

</head>

<body>
    <svg id="sprite" width="0" height="0">

        <g id="chevron">
            <path fill="#E8213B" d="M9.683,14.274c-0.378,0.399-0.378,1.053,0,1.452l5.932,6.264c0.378,0.399,1.006,0.408,1.395,0.019
                l1.286-1.286c0.389-0.389,0.389-1.026,0-1.415L14.7,15.707c-0.389-0.389-0.388-1.026,0-1.415l3.598-3.598
                c0.389-0.389,0.389-1.025,0-1.414L17.01,7.991c-0.389-0.389-1.016-0.38-1.395,0.019L9.683,14.274z"/>
        </g>

        <g id="house">
            <polygon fill="#3E123E" points="44.753,10.503 37.378,17.878 37.378,25.253 52.128,25.253 52.128,17.878   "/>
            <polygon fill="#3E123E" points="44.837,8.747 53.128,17.01 55.128,15.01 44.837,4.747 34.462,15.01 36.462,17.01   "/>
            <polygon fill="#3E123E" points="52.128,10.018 52.128,5.33 48.878,5.33 48.878,6.777  "/>
        </g>
    </svg>

    <svg width="30" height="30">
        <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#house" class="red" x="-30" y="0"></use>
    </svg>

</body>

Sadly, the red styling does not apply when you use a tag.

I also tried what was suggested by Erik but the SVG code is nowhere on the page so the CSS selector has nothing to target as the tag is only referencing a in the external SVG file.

1
You can probably use an SVG Fragment identifier with a translate transform for this. See w3.org/TR/SVG/linking.html#SVGFragmentIdentifiersRobert Longson
You're really asking two questions here. The more you change it to emphasise the second issue the less Eric's answer makes sense.Robert Longson

1 Answers

0
votes

One way to do this is to use <view> elements.

In your svg you define views as some particular area in your (larger) viewBox that shows just one of the resources inside:

<svg viewBox="0 0 1000 1000">
  <view id="star" viewBox="40 80 32 32" />
  ...
</svg>

Then you can reference that view from outside like this:

<img src="sprites.svg#star">

Here's a full example showing this.