DEV Community

loading...
Cover image for A gnarly SVG visibility bug

A gnarly SVG visibility bug

Bryce Dorn
☕️ 🐶 🏃‍♂️ 🎶 🎮 ⚽️ 🍕
・2 min read

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.

Interesting

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

Invisible svg

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

  1. Use svg-inject combined with the makeIdsUnique param when rendering SVGs.

  2. If using React or other virtual DOM library, create a wrapper component using something like react-svg where beforeInjection can call the above SVGInject function to modify ids and make them unique.


Deflate

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.

Discussion (0)