How to Refer to an Internal Gradient Definition Inside an Svg Sprite Symbol

How can I refer to an internal gradient definition inside an SVG sprite symbol?

Firstly please note the edit to my question - whereupon I discover that the use of display: none to hide the SVG symbols until we need them was the problem.

I kept fiddling and settled upon this "answer", which is far from perfect, but should still be reliable for any such situation.

All you need to do is wrap the entire <svg> code in a <div> container which must be displayed but will never affect layout, so I've just done this via mega overkill CSS such as:

height: 0; width: 0; position: absolute; visibility: hidden;

And this works great. See the final fiddle: http://jsfiddle.net/Qtq24/5/

If anyone has a better solution, I'd love to hear it as this feels like a bit of a hacky way of doing it but I guess no more hacky than having to use display: none; anyway.

Why can't I reference an SVG linear gradient defined in an external file (paint server)?

After more research, it looks like this is a browser support issue. See:

  • https://code.google.com/p/chromium/issues/detail?id=109212
  • https://bugs.webkit.org/show_bug.cgi?id=105904

Sadly, I'd come across this question before posting mine, and had thought that surely, in 5-1/2 years, browser support would have caught up - but that doesn't appear to be the case.

As of 2015, apparently Firefox and Opera are the only two browsers to support this in any substantial way.

Back to the drawing board...

svg-sprite: symbol conversion to single svg icon

There isn't a lot you need to change (see http://jsfiddle.net/yo8bhxfu/):

  • Remove the view box from the SVG element
  • Adapt the style of the SVG element so it's visible and specifies the proper size (taken from the symbol's view box)
  • Convert the symbol tags into g tags

You might be on the safe side if you additionally remove the class attributes, the id attributes and the title.

<svg xmlns="http://www.w3.org/2000/svg" style="width:500px; height:500px;">
<g viewBox="0 0 500 500" id="test-icon">
<title>test</title>
<ellipse class="background" id="test-background" fill="#fff" cx="248.8" cy="251.4" rx="246.2" ry="244.8"/>
<path class="test-frame" d="M249.4 18C121.1 18 16.8 122.3 16.8 250.6S121.3 483 249.4 483 482 378.8 482 250.5 377.7 18 249.4 18m0 480.8c-66 0-128.3-26.4-176.2-73.1C27.6 378.9 1.3 316.5 1.3 249.3s26.3-128.2 73.1-175 109.1-73.1 175-73.1 128.3 26.4 176.2 73.1c46.7 46.8 73.1 109.2 73.1 176.2s-26.4 128.3-73.1 176.2c-46.7 45.6-109 72.1-176.2 72.1"/>
<path class="test-figure" d="M133.8 103.5v293h232.5V148.9l-22-22-23.4-23.4H133.8zm17.9 22h108.7v12.4H151.7v-12.4zm0 24.8h108.7v12.4H151.7v-12.4zm192.5 211.8H151.7v-24.7h191.2v24.7h1.3zm0-41.2H151.7v-24.7h191.2v24.7h1.3zm0-42.7H151.7v-24.7h191.2v24.7h1.3zm0-44H151.7v-23.4h191.2v23.4h1.3z"/>
</g>
</svg>

Why is the browser rendering of this SVG gradient different in Inkscape vs browser/AI

Inkscape usually splits gradient elements into two parts, like in your case:

  • the path using the gradient references it with fill:url(#b),
  • <linearGradient id="b"> defines where to place the gradient and references the second one with xlink:href="#a",
  • <linearGradient id="a"> defines the color stops along the gradient.

But Inkscape has a bug: it assumes that gradient #b will contain the full information about where to place the end points of the gradient. These are computed by taking into account six attributes: gradientUnits, x1, y1, x2, y2, gradientTransform.

In your case, only five of them are defined on gradient #b, while the sixth is defined on gradient #a. The spec is clear on what to do in that case:

For any of the specified attributes not defined on the current element, the user agent must determine the value of the attribute for the template element and use it as the value for the current element.

Gradient #a is in the role of the template here, and the gradientTransform attribute should be used to determine where to place the gradient. Browser do this, and place the gradient approx. 600px to the right, but Inkscape does not.

Since the correct placement is achieved by ignoring the attribute, the solution is clear: remove the gradientTransform attribute from <linearGradient id="a">.

You can do this by either editing the SVG in an external text or XML editor, of by opening Inkscape's internal XML editor. (Shift+Ctrl+X or Edit -> XML Editor...)



Related Topics



Leave a reply



Submit