Patrick Crosby's Internet Presents

Responsive SVG

26 Mar 2014

Many of the charts on StatHat are changing from server-rendered PNGs to browser-rendered SVGs. There are a lot of reasons for this, but one is that we'd like the charts to be more responsive to different screen sizes and retina displays.

Since SVG stands for Scalable Vector Graphics, it should be a piece of cake to scale them. If you just put an svg with a width and height in an HTML page:

<body>
<svg width="940" height="280">......</svg>
</body>

and resize your browser, it will always stay at 940x280 pixels.

Remove the width and height and use viewBox and preserveAspectRatio:

<body>
<svg viewBox="0 0 940 280" preserveAspectRation="xMinYMin meet">......</svg>
</body>

Now you can resize your browser, look at the page on any device, and it will fill the browser window, the lines will be nice clean vectors.

There's just one issue. For some reason, the svg element is square. So anything that you'd like to put after the svg is pushed way down the page. A CSS trick that I found on Dudley Storey's blog solves this issue.

Add a container div, and a class for the svg:

<body>
<div class="svg-container">
  <svg viewBox="0 0 940 280" preserveAspectRation="xMinYMin meet" class="svg-content">......</svg>
</div>
</body>

The CSS that fixes it all up:

.svg-container {
    display: inline-block;
    position: relative;
    width: 100%;
    padding-bottom: 30%;
    vertical-align: middle;
    overflow: hidden;
}

.svg-content {
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
}

The tricky thing is that you need to set the padding-bottom of the container to the aspect ratio of the SVG element. In this case it's (280 / 940) * 100, which is just about 30%. So if you have SVG elements with different aspect ratios, you would need a class for each one with the padding-bottom value adjusted accordingly. All the charts on StatHat have the same aspect ratio, so this wasn't an issue.

View an example chart

I really like this solution. It's simple, there's no JavaScript required. Unfortunately, due to the interactive features of the StatHat charts, we're going to have to do more and use JS to update certain UI elements. Also, the resizing of the text in this solution makes it difficult to read the axes on small screens.