Search code examples
htmlsvgxlinkinline-svg

How can I reference a radialGradient from a different inline SVG element?


I'm building an icon solution using SVG, where parts of icons need to be reusable. There are a few different <svg /> elements inline in my HTML document, and the <use /> element works perfectly for reusing shapes – rects, paths and so on, even between svg elements.

However, reusing other definitions, like <radialGradient /> doesn't work for me. When the gradient is defined within a <defs /> element in the same <svg /> element, it works as expected, but not when the gradient is defined in another <svg /> element.

Pseudo code

<!-- Near the top of my BODY element -->
<!-- This is where I keep the SVG stuff I want to reuse -->
<svg id="for-reuse" style="display:none">
  <defs>
    <path id="marker" d="M63 127L49 93C44 80 52 69 63 69L64 69C75 69 83 80 78 93L64 127" />
    <radialGradient id="shadow">
      <stop offset="10%" stop-color="rgba(0,0,0,0.4)" />
      <stop offset="90%" stop-color="rgba(0,0,0,0)" />
    </radialGradient>
  </defs>
</svg>

<!-- Further down the html document -->
<svg viewBox="0 0 128 128" style="width:64px; height:64px" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <!-- This use element works fine! -->
  <use xlink:href="#marker" style="fill:black" />

  <!-- But this fill attribute does not! -->
  <rect x="5" y="5" width="20" height="20" fill="url(#shadow)" />
</svg>

Why is it possible to use shapes from other svg elements, but not attribute values like this? When I move the shadow gradient into a defs element inside the visible svg element, the reference works perfectly.

Here is a JSFiddle that illustrates both working and non-working: https://jsfiddle.net/7tfna0L8/2/

The solution

Robert Longson pointed out that my "repository" of reusable svg had a style of display:none. For me, that feels like the correct way to do this. After all, this repository should not be displayed in any way. The problem is that the browser optimizes this by probably not even parsing any style at all, which makes it possible to reference elements, but not style (like my gradient)

Working jsFiddle: https://jsfiddle.net/atornblad/7tfna0L8/3/


Solution

  • Your far-gradient is in an svg which has a style of display:none. That disables all CSS within that fragment so it doesn't work. Try width="0" height="0" instead of display:none.