16

I've got an SVG object that contains a linear gradient embedded directly in a document. It works fine in Chrome and Firefox, but in Safari nothing is rendered. If I create the SVG as a file and embed it using the Object tag, it works fine in Safari. Other shapes and fills work, it's just linear gradient that doesn't work. I guess I could use the object, but I'd prefer to embed the SVG directly.

I've create a demo here (works in Chrome, not Safari): http://jsfiddle.net/sjKbN/

I came across this answer which suggests setting the content type to application/xhtml+xml, but this in itself seems to cause other problems.

Just wondering if anyone had come across any other fixes or ideas to get this working.

Community
  • 1
  • 1
Christian
  • 19,605
  • 3
  • 54
  • 70
  • 1
    The gradient works in the nightly webkit build version of safari (available for download http://nightly.webkit.org/ ) so there is a good chance it will work in a future released version of safari. – Brian Swift Jul 03 '12 at 04:31
  • Ahh that's awesome, glad to see they've fixed it. Cheers for the tip! – Christian Jul 03 '12 at 04:57

5 Answers5

32

Your gradient will work in Safari if you wrap a defs tag around it:

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="300px" height="300px" viewBox="0 0 300 300" enable-background="new 0 0 300 300" xml:space="preserve">
 <defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="5.6665" y1="149.5" x2="293.333" y2="149.5">
    <stop  offset="0" style="stop-color:#FFF33B"/>
    <stop  offset="0.0595" style="stop-color:#FFE029"/>
    <stop  offset="0.1303" style="stop-color:#FFD218"/>
    <stop  offset="0.2032" style="stop-color:#FEC90F"/>
    <stop  offset="0.2809" style="stop-color:#FDC70C"/>
    <stop  offset="0.6685" style="stop-color:#F3903F"/>
    <stop  offset="0.8876" style="stop-color:#ED683C"/>
    <stop  offset="1" style="stop-color:#E93E3A"/>
</linearGradient>
</defs>
<rect x="5.667" y="5.333" fill="url(#SVGID_1_)" width="287.667" height="288.333"/>
</svg>

​It seems that wrapping your references in defs is encouraged but not obligatory according to spec. So this is a bug in Safari.

methodofaction
  • 70,885
  • 21
  • 151
  • 164
23

About Alpha : It seems that Safari (7 at this moment) does not cover SVG color alpha channel, use stop opacity attribute. it works fine!

<stop stop-color="rgba(x,y,z,0.5)"> //safari does not work
<stop stop-color="rgb(x,y,z)" stop-opacity="0.5"> //ok
Sebastien
  • 241
  • 2
  • 5
  • The code in the question does not use rgba colours, so it's not an answer to this particular question. – Robert Longson Oct 07 '14 at 06:21
  • 8
    Wrong Sir Longson! First searching for the defect on linear gradient that did not work as same in safari than other browser, I saw this post first. Second, The topic is related to the safari different behaviour of linear gradient. Alpha channel is a part of this global topic :"SVG Linear gradient doesn't work in Safari" – Sebastien Oct 07 '14 at 09:14
  • 2
    @Sebastien, great answer. It is definitely relevant to have it here! Thank you – dev4life Feb 03 '15 at 12:58
  • Perfect! you saved my acc :')). here is my code: `{offset: "100%", color: "rgb(130,130,130)", opacity:"0"}` for data and `.attr("stop-opacity", function(d) { return d.opacity; }); ` when you append `stop`. Cheers. – DragonKnight Nov 08 '18 at 00:58
16

The accepted answer was not the solution for me.

My problem was the presence of a <base href="/" /> tag in my index file. Simply removing it solved the problem for me.

If you cannot remove it, probably some workaround already exist: found this gist but I did not tested it.

Update

Simply removing the href broke the child routing of my angular app, the proper workaround is to prepend to the linearGradient id with the page relative location. I wrapped the logic in a method like this:

get svgFill(): string {
  return `url(${this.location.path()}#${this.gradientId}) white`;
}
michelepatrassi
  • 2,016
  • 18
  • 32
  • 1
    You can use: `window.location.pathname` as the prefix. Example: `url(${window.location.pathname}#${this.gradientId}) white` – OfekA Mar 10 '20 at 09:39
  • @OfekA That will break if there are query parameters: `http://example.com/page.html?arg=val` – blahdiblah Mar 20 '20 at 21:51
2

The answer is simple, all id's (not only <linear gradient>) need to be UNIQUE for all SVG files.

daxtersky
  • 410
  • 3
  • 9
0

I had some troubles too making an inline SVG with a linear gradient work. The designer had put a - in the id of the <linearGradient. The solution was as simple as removing it.

<linearGradient id="linear-gradient">
...
<path fill="url(#linear-gradient)" d="..."/>

with

<linearGradient id="lineargradient">
...
<path fill="url(#lineargradient)" d="..."/>
select
  • 2,513
  • 2
  • 25
  • 36