I wasn't entirely sure how to title this blog post as it isn't straightforward to describe it but here it goes. I should also preface that my knowledge of SVGs is quite high level so maybe someone who is may more experienced than me would have spotted this out easily but I feel like this warrants a post because it doesn't happen in all browsers and quirks are annoying to solve.
Recently, we had a very intricate SVG that wasn't rendering as expected in Safari. Chrome, Edge and Firefox seemed to be happy with it. This SVG was an illustration and its code was automatically generated by a design platform and it included a raster image.
The following isn't the actual SVG but a high level presentation of the structure of the SVG. I substituted some random values with the word value
as they aren't particularly important to the goal or issue.
<svg width="600" height="300" viewBox="0 0 600 300">
<defs>
<pattern id="pattern-a" patternUnits="objectBoundingBox" x="value" width="100%" height="100%">
<use href="#image-a" transform="scale(value)"/>
</pattern>
<image id="image-a" width="1223" height="2190" xlink:href="data:image/png;base64,VALUE">
</defs>
<path d="value value" fill="url(#pattern-a)" fill-rule="nonzero"/>
<!--Lots of paths from here on without any links to patterns in the fill attribute-->
</svg>
When opened in Safari, all the path
would render as expected except the path
that was requesting to be filled with a pattern. So visually, people could describe it as "half of the image doesn't appear". It took me a bit to understand what was the problem because the svg file was really long.
Long story short: either the pattern
or the use
wasn't finding #image-a
in Safari which looks like it might be a scope issue.
I moved the image
to be inside the pattern
and it began to appear twice. Which made sense. So my solution was to delete the use
and use the image
directly inside the pattern
.
<svg width="600" height="300" viewBox="0 0 600 300">
<defs>
<pattern id="pattern-a" patternUnits="objectBoundingBox" x="value" width="100%" height="100%">
<image id="image-a" width="328" height="329" xlink:href="data:image/png;base64,VALUE">
</pattern>
</defs>
<path d="value value" fill="url(#pattern-a)" fill-rule="nonzero"/>
<!--Lots of paths from here on without any links to patterns in the fill attribute-->
</svg>
The image ended up needing some adjustments to its width and height but this finally fixed it in all browsers.
Now I know.