Be careful with your viewBox

In Sara Soueidan’s article: SVG Style Inheritance and the ‘Flash of Unstyled SVG’, Sara explains the importance of having width, height, and viewBox attributes on SVG elements. This reminded me of two issues I ran into last week building my new design.

I have an SVG sprite for social icons:

These three icons live within a single file (see Sara’s guide to SVG sprites). To reused an icon is as simple as referencing it like so:

<svg>
  <use xlink:href="icons.svg#twitter"></use>
</svg>

With CSS I can style the size and colour of individual icons, amongst other properties. At least that is the basic principle. Of course, when your asset pipeline is a mess of custom node scripts, what’s eventually rendered in the browser can be a delightful surprise.

My icons weren’t displaying at all.

I checked my SVG sprite source and it looked correct:

<svg xmlns="http://www.w3.org/2000/svg">
    <symbol id="twitter" viewbox="0 0 34 28">
        <!-- [path data] -->
    </symbol>
    <symbol id="github" viewbox="0 0 28 28">
        <!-- [path data] -->
    </symbol>
    <symbol id="codepen" viewbox="0 0 28 28">
        <!-- [path data] -->
    </symbol>
</svg>

I checked my minified SVG sprite source and it looked suspiciously empty:

<svg xmlns="http://www.w3.org/2000/svg">
</svg>

If you’re using a minifying tool based on SVGO you need to disable a couple of plugins (‘cleanupIDs’ and ‘removeViewBox’). This will ensure the <symbol> elements are not removed from your sprite.

That fixed, I refreshed to find my icons were now visible but not scaling correctly. Regardless of what CSS width or height values I set they refused to listen. After a brief spell of bewilderment I realised that my minified sprite was still missing the viewBox attributes on each <symbol>. Browsers will not scale SVG without this attribute.

Why was it being removed? That’s because — and this took me an embarrassingly long time to notice — my viewbox attributes were lower-case. From testing it seems browsers don’t actually care but SVGO is case-sensitive in this scenario. Not recognising the lower-case viewbox it was being removed.

I’ve uploaded an example on CodePen to demonstrate:

I suppose I’ve learnt two important lessons here:

  • Never remove the viewBox
  • Beware of meddling tools that do!

It’s funny how long front-end problems can take to debug. I sat there comparing my website to a previous one I’d built playing spot-the-difference for the longest time. The solution was no more than a capital “B”.

Buy me a coffee! Support me on Ko-fi