RJo
RJo

Reputation: 16291

SVG use and gradients as fill

I've been trying to externalize my SVG icons to a file and referencing them with markup like <svg><use xlink:href="file.svg#icon" /></svg>. In theory this works really nicely, but different browsers have issues with rendering. All the browsers are able to render the svg correctly when referencing the symbol with <use> inside the file and opening the svg file's url directly.

In short, is there a cross-browser way to get SVG linearGradients working as fills for elements when referencing the symbols with <svg><use/></svg> in the markup?

I set up a plunker demonstrating the problem: http://plnkr.co/edit/feKvZ7?p=preview

Simplified, the markup is like the following:

<!DOCTYPE html>
    <html>
      <body>
        <h1>SVG sprite test</h1>
        <svg width="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
          <use xlink:href="icon.svg#icon" />
        </svg>
      </body>
    </html>

And the SVG file looks like this:

  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
      <defs>
        <linearGradient id="gradient">
          <stop offset="0" stop-color="black" />
          <stop offset="1" stop-color="white" />
        </linearGradient>
      </defs>
      <symbol id="icon" viewBox="0 0 100 100">
        <circle cx="50" cy="50" r="40" stroke="black" fill="url(#gradient)" />
      </symbol>
    
      <use id="iconuse" xlink:href="#icon" width="100" height="100" />
    
    </svg>

This is what it looks like in the different browsers: Different results of rendering linear gradients for symbols in different browser

Upvotes: 48

Views: 5035

Answers (2)

Alexandr_TT
Alexandr_TT

Reputation: 14545

The symbol tag is used to hide the elements that are inside it. Elements inside the symbol are called using the <use> command by their unique indicator.
Therefore, it is better to use this method of calling individual elements rather than calling the whole symbol

In addition, elements when using <use> fall into the shadow DOM and using CSS in some cases becomes impossible
Therefore, it is better to delete all internal styles inside symbol and assign them directly to the use command

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="gradient">
      <stop offset="0" stop-color="black" />
      <stop offset="1" stop-color="white" />
    </linearGradient>
  </defs>
  <symbol  id="icon"  viewBox="0 0 100 100"> 
    <circle id="circle" cx="50" cy="50" r="40"   />
     <rect id="rect" x="100" y="10" width="100" height="100" />
  </symbol>

  <use class="iconuse" xlink:href="#circle" width="100" height="100" fill="url(#gradient)" stroke="black" />
     <use class="iconuse" xlink:href="#rect" width="100" height="100" fill="url(#gradient)" />
</svg>

Upvotes: 1

FieryCat
FieryCat

Reputation: 1887

Try next one (it's how Inkscape provide implementation of gradients):

<linearGradient id="gradient">
  <stop
     style="stop-color:black;"
     offset="0"/>
  <stop
     style="stop-color:white;"
     offset="1" />
</linearGradient>
...
<path
   style="fill:url(#gradient); ...

Upvotes: 0

Related Questions