February 8, 2012
So, you can now use SVG everywhere. But there’s one situation where it will cause you problems: when used in a responsive design in a Webkit browser, such as Safari (including the mobile version) or Chrome. Which is a real pity, as (repeating myself) SVG is great for responsive designs. Specifically, the trouble is that Webkit doesn’t report the height of the SVG images correctly.
If you check out the demo I put together you can see the problem. There are three SVG images on the page (rendered by Raphaël). All three are set to 100% height/width using JQuery. The containers that hold each SVG have their widths set in percentages, this maintains the ratios of the layout as the page re-sizes (the height should look after itself automatically). Which is where Webkit’s failure to correctly report the height of the SVG causes problems. The height of the SVG is always reported far larger than it actually is. Which means the containers end up being far too tall for the SVG they contain. You can see this in the demo. The green areas show the space between the actual edges of the image and where Webkit thinks the edges are. This is seriously problematic for responsive layouts, as it breaks them completely.
I’ve reported this bug to the Webkit project. But it takes time for bugs to get fixed, and more time still for those fixes to find their way into the browsers on people’s computers.
Happily there’s a workaround. Once more, it’s JQuery to the rescue. The answer lies in using the Window.onresize and Document.ready events to calculate this formula: (original SVG height / original SVG width * current SVG width). This gives the height in ratio for the current SVG width. We can then use this value to control the container height – and negate the Webkit SVG height bug.
Here’s the code to I used to fix the bug (NB ‘#floor’ is the id of the main SVG in the demo page):
var svgW = 658;
var svgH = 500;
var curSVGW = $(‘#floor’).width();
var newSVGH = heightInRatio(svgH,svgW,curSVGW);
return (oH / oW * nW);
It’s not great having to use JQuery to fix issues like this, but it works; and that’s all your users will care about.