Reading List

TIL: A situation where the <svg> doesn't fully appear in Safari. from Oh Hello Ana RSS feed.

TIL: A situation where the <svg> doesn't fully appear in Safari.

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.