Search code examples
htmlsvggrunt-svgstore

Gradients not working for inline SVG on webpage


I have an SVG sprite which is embedded inline in a web page which contains several images as symbols, and some of these images have gradient fills defined in the <defs> section of the SVG. However when I try to use any of the images on the page by using a <use> tag the image displays, but doesn't have any of the gradients. e.g.

<html>
    <body>
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
            <defs>
                <linearGradient id="foo" />
            </defs>
            <symbol id="bar">
                <path fill="url(#foo)">
            <symbol>
        </svg>

        <!-- This displays the image contained in the symbol #bar but doesn't show the gradient defined in #foo -->
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
            <use xlink:href="#bar" />
        </svg>
    </body>
</html>

I believe this is the correct way to include the gradients, with the defs section defined outside the symbol. However it doesn't work in chrome, firefox or IE11 / Edge (actually in IE / Edge it doesn't show the image properly either, but for now I'm tempted to blame IE for that) so since it doesn't work in any modern browser I'm guessing it is a mistake on my part.

This is of course a very simplified example, the SVG sprite is a composite of several images generated with grunt SVG-store, but an individual image does display fine if I try displaying it on the page like so:

<img src="bar.svg" />

So the SVG itself seems to be correct. I have also tried placing just one image from the sprite inline on the page (modified slightly so it is a symbol as above) and referenced it with <use> and it displays OK. I have tried comparing the XML of an individual image and its symbol in the sprite and as far as I can see they are identical (including the parts of the <defs> section relevant to the image).


Solution

  • The issue was because the sprite was hidden with display: none in the css because otherwise the browser includes it in the flow and allocates space for it because it is at the top of the body. Removed display:none and changed it to position:absolute; left: 9999px;