How do I use svg patterns in a cross browser consistent way?

Viewed 2705

I want a SVG image (prerendered, but inserted with js in an svg tag, to allow for some further manipulation) to be able to use a predefined pattern, using the "pattern" tag. Sounds simple enough, doesn't it? Well, turns out Chrome (Webkit?) behaves a bit different from any other browsers, and now I'm not sure what the best way would actually be to achieve this.

My svg looks like this:

<svg>
 <defs>
  <pattern id="specialPattern">...</pattern>
 </defs>
 <path class="special"></path>
</svg>

and I want paths with the class special to have "pattern" as fill.

Attempt one: Works in Chrome, not in FF or Opera

My first attempt was to simply put this in my css:

 .special { fill:url("#specialPattern");}

This actually works in Chrome, though when you think about it, it probably shouldn't. The other browsers I tried interpret this url as relative to the file it's in (the css file), which makes more sense.

Attempt two: Works in FF and Opera, not in Chrome

Next attempt: Provide an absolute url to the pattern.

 .special { fill:url("//example.com/styles/svgWithStyleDeclaration.svg#specialPattern");}

While this works as expected in FF and Opera, Chrome now resets the fill instead (I have no idea where it is actually looking for that style)

Attempt three: Works, kind of

Inlining the style in the SVG works everywhere it seems: style="fill:url('#specialPattern')"

And though I guess this is a case where the lines between content and presentation is blurred, in my case at least it would be much better to keep style decclarations elsewhere (not least because this would make my SVG need to be much bigger)

Attempt four: Works (?) but dirty

I haven't tested a lot of browsers, so I'm not sure about how water proof it is, but it seems to me like using a css hack to detect webkit browsers would work:

@media screen and (-webkit-min-device-pixel-ratio:0) {
  .special {fill: url("#specialPattern");}
}
 .special { fill:url("//example.com/styles/svgWithStyleDeclaration.svg#specialPattern");}

Now, there MUST be a more elegant way to solve this. How should it be done?

Edit: Turns out that IE behaves like Chrome here, so you would also need to make sure IE<=9 has 'fill: url(#specialPattern)'

1 Answers
Related