Webkit SVG height bug workaround

Lately, I’ve been working with Dmitry Baranovskiy’s excellent Raphaël Javascript library. If you are not aware of it already, it uses Javascript to render SVG images in Webkit, Gecko and Presto based browsers (Safari, Chrome, Firefox, Opera et al) – with a VML fallback for those recalcitrant, older Internet Explorer versions. First of all, this is brilliant because SVG images scale infinitely without loss of quality; which means they’re great for responsive web design solutions. Secondly, every SVG object is a DOM object. Which means every element in the entire image is fully scriptable. Finally, before Raphaël there was no way to render SVG images across all browsers. Support in browser layout engines ranged from full implementation of the standard – it’s a W3C standard by the way – (Webkit), through partial (Gecko) to non-existant (Trident, until Internet Explorer 9 anyway).

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):

function fixWebkitHeightBug(){

var svgW = 658;
var svgH = 500;
var curSVGW = $(‘#floor’).width();
var newSVGH = heightInRatio(svgH,svgW,curSVGW);
$(‘#floor’).height(newSVGH);

function heightInRatio(oH,oW,nW){

return (oH / oW * nW);

}

}

$(window).resize(function() {

fixWebkitHeightBug();

});
$(document).ready(function() {

fixWebkitHeightBug();

});

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.