Or: gaining a deeper understanding of how SVGs are rendered by remembering their HTML roots.
I like SVGs. They're tiny compared to images & allow greater flexibility when rendering. But with this flexibility comes more room for weird issues. Here's what was blocking a task I was working on for way too long:
When a SVG is shared between a component that's visible on the page and another that isn't and the hidden one is higher in the DOM tree, the visible one won't render properly. So when using CSS
display rules for multiple components, ordering in the DOM is paramount.
Side-note: interestingly, some of the colors will bleed through as you may notice the tiny green border, but ignore that because it just made debugging this take longer.
By getting all of the SVGs on the page via
document.getElementsByTagName('svg'), I was able to see that there were instances that weren't visible by hovering my mouse over them. From there, I tried stubbing the non-visible components wrapping them to return
null, and the issue was resolved. ✨
I reported this as a Chromium bug, but turns out this is the same as a bug report that was filed in 2013. (Safari surprisingly doesn't have this issue though.) 😴 So instead of pushing for a fix, here are some workarounds:
Instead of using CSS and
@media queries to hide certain elements on the page, use viewport size detection to prevent those components from being rendered at all. The bug only exists when the first SVG is hidden, so if they're both visible it magically works!
Use svg-inject combined with the
makeIdsUniqueparam when rendering SVGs.
If using React or other virtual DOM library, create a wrapper component using something like
beforeInjectioncan call the above
SVGInjectfunction to modify
ids and make them unique.
And that's (finally) that. I'm glad I finally got to the bottom of this. And hopefully this prevents someone else from going down the SVG rabbit hole.