Wednesday, June 24, 2015

Responsive SVG

I mentioned the other day that I was working on an update for caseyleonard.com that included even more full-screen frog images. Much like the current site, I want to use SVG images and have the frogs scale right along with the browser window, for a smooth responsive effect.

And as usual, Microsoft Internet Explorer has to ruin the party.

Instead of using <img> tags for the frogs this time, I am going to embed SVG markup directly in the HTML of the page. This has been possible for quite a while (IE support began with version 9) but is not often seen on "normal" web pages. Any page with my name on it will be far from normal.

You can try this yourself if you have some SVG lying around. It's best to use minified SVG (see last Wednesday's post) so your pages don't get too terribly large. Here is an example with the actual SVG stuff blanked out to save space:

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Responsive SVG</title>
</head>

<body>

  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 276 281">
    ...
  </svg>

</body>

</html>

By including a viewBox attribute to set the aspect ratio of the image and not including width or height attributes, good browsers like Chrome and Firefox scale the image to the maximum width of the container. Bad browsers like Internet Explorer assume a fixed height of 150 pixels and scale the width to create an image with the appropriate aspect ratio. Huh?

Properly scaled frog, in Chrome

Improperly scaled frog, in Internet Explorer

It turns out this is a known issue with IE, and it easily correctable with some CSS. First, wrap the SVG element in a <div> of class container. Then add the following CSS to the page:

.container {
    width: 100%;
    height: 0;
    padding-top: 102%;
    position: relative;
}

svg {
    position: absolute;
    top: 0;
    left: 0;
}

The value of container width is 100% because I want the frog to be as big as the window. You can use other values if you want your image to be smaller. The value for padding-top is calculated based on a formula and will be different for every image. To get the percent for padding top, do

( ( svg height) / (svg width) ) x (container width)

So in my example, the height of the frog image with my desired aspect ratio (from the viewBox) is 281 and the width is 276. I divide height by width and then multiply by 100 to get a value of 102. I use that for the padding-top percentage. Another look at the page in IE shows the correct result, and the page looks unchanged in Chrome.

Correct this time, Internet Explorer

And that looks much better! It's still a shame that IE makes us do all this extra work. And speaking of extra work, in today's comic the frogs take server hardening a little too far.

Amphibian.com comic for 24 June 2014