Home > Blockchain >  How to apply linear gradient to SVG <symbol> in <use> tag?
How to apply linear gradient to SVG <symbol> in <use> tag?

Time:11-25

I have in my HTML file these lines:

<div class="account-container">
 <svg id="icon-account" style="width: 5rem; height: 5rem;">
  <use href="/icons.svg#icon-account" />
 </svg>
</div>

icons.svg looks like this:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>

  <linearGradient id="gradient1" x1="21.3635" y1="1.72727" x2="21.3639" y2="41"     gradientUnits="userSpaceOnUse">
   <stop stop-color="#7DC2C9"/>
   <stop offset="1" stop-color="#446B73"/>
  </linearGradient>

  <symbol id="icon-account" viewBox="0 0 42 42" >
   <path d="M6.09091 34.3314C10.9277 29.4164 15.2241 27.245 21 27.1818C27.3352 27.4877 31.7332 29.4904 36.2727 33.9136M41 21C41 32.0457 32.0457 41 21 41C9.95431 41 1 32.0457 1 21C1 9.95431 9.95431 1 21 1C32.0457 1 41 9.95431 41 21ZM26.4545 15.1818C26.4545 18.1943 24.0125 20.6364 21 20.6364C17.9875 20.6364 15.5455 18.1943 15.5455 15.1818C15.5455 12.1694 17.9875 9.72727 21 9.72727C24.0125 9.72727 26.4545 12.1694 26.4545 15.1818Z" fill="none"/>
  </symbol>

 </defs>
</svg>

I want to apply #gradient1 to the icon. Setting the stroke either on the path in the SVG file or in CSS with stroke=url(#gradient1) doesn't work and the icon is not rendered at all.

Including the following SVG defs in the HTML document itself allow to reference the gradient and then it works:

<svg
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
>
  <defs>
    <linearGradient
      id="gradient1"
      x1="21.3635"
      y1="1.72727"
      x2="21.3639"
      y2="41"
      gradientUnits="userSpaceOnUse"
    >
      <stop stop-color="#7DC2C9" />
      <stop offset="1" stop-color="#446B73" />
    </linearGradient>
  </defs>
</svg>

But, I would like to avoid polluting the HTML with SVG definitions, and keep all SVG related code in the seperate icons.svg file.

How do I apply the gradient to this icon?

Thanks!

CodePudding user response:

Seems like a Chrome bug, probably the infamous Issue 109212: SVG (filter | fill […]) from external files not applied from 2012; found in related question: Gradient in defs not showing up in SVG sprite in Chrome.

<svg style="width: 5rem; height: 5rem;">
 <use href='data:image/svg xml,<svg version="1.1" 
  xmlns="http://www.w3.org/2000/svg">
  <defs>
   <linearGradient id="gr">
    <stop offset=".2" stop-color="red" />
    <stop offset=".8" stop-color="blue" />
   </linearGradient>
   <symbol id="icon" viewBox="0 0 8 8" >
    <path d="M0 0 L 8,0 8,8 0,8 Z M 2,2 L 6,2 6,6 2,6 Z" 
     fill="url(#gr)"
     stroke="gold" />
   </symbol>
  </defs>
 </svg>#icon' />
</svg>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

This sample code uses dataURI to simulate external resource. In Firefox it renders gold stroke and red-blue gradient fill properly, but in Chrome only stroke is visible.


For parity, same SVGs with defs placed in HTML directly, works in both browsers:

Show code snippet

<svg style="width: 5rem; height: 5rem;">
 <use href='#icon' />
</svg>

<svg version="1.1" 
  xmlns="http://www.w3.org/2000/svg">
  <defs>
   <linearGradient id="gr">
    <stop offset=".2" stop-color="red" />
    <stop offset=".8" stop-color="blue" />
   </linearGradient>
   <symbol id="icon" viewBox="0 0 8 8" >
    <path d="M0 0 L 8,0 8,8 0,8 Z M 2,2 L 6,2 6,6 2,6 Z" 
     fill="url(#gr)"
     stroke="gold" />
   </symbol>
  </defs>
 </svg>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

And self-contained SVG loaded into image, proving references in same true SVG (not SVG-in-HTML) works in both browsers.

Show code snippet

<img src="data:image/svg xml;charset=utf-8,
<svg xmlns='http://www.w3.org/2000/svg' version='1.1'>
 <defs>
  <linearGradient id='gr'>
   <stop offset='.2' stop-color='red'/>
   <stop offset='.8' stop-color='blue'/>
  </linearGradient>
  <symbol id='icon' viewBox='0 0 8 8'>
   <path d='M0 0 L 8,0 8,8 0,8 Z M 2,2 L 6,2 6,6 2,6 Z'
    fill='url(#gr)'
    stroke='gold'/>
  </symbol>
 </defs>
 <use href='#icon'/>
</svg>"></img>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related