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.
How I caught it
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. ✨
Prevention
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:
Specifically in code
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!
More generally
Use svg-inject combined with the
makeIdsUnique
param when rendering SVGs.If using React or other virtual DOM library, create a wrapper component using something like
react-svg
wherebeforeInjection
can call the aboveSVGInject
function to modifyid
s 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.
Top comments (0)