Making D3 charts responsive

D3.js is one of the most popular JavaScript library for manipulating documents based on data and creating charts. There many examples available on the website but none of them are responsive. And with advent of responsive design, everthing is going “mobile-friendly”, so why should charts be left behind. There are many libraries that offer responsiveness out of the box, some are dependent on D3.js itself and some are not. We’ll be using a technique described in this tympanus blog post. We’ll be using this chord diagram as an example and will be making it responsive.

Code overview

As you can see in the code, height and width are set as fixed attributes on the svg element. This the main cause for non-responsiveness.

//....some code...

var width = 960,
    height = 500,
    innerRadius = Math.min(width, height) * .41,
    outerRadius = innerRadius * 1.1;

//.....some more code....

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

//.....some more code....

Full code available as gist or demo. SVG in action

Going responsive

As per the blog post mentioned earlier, we need to peform the following steps
1. Remove height and `width attributes
2. Add viewBox attribute

So the above code will change as follows

//....some code...

var width = 960,
    height = 500,
    innerRadius = Math.min(width, height) * .41,
    outerRadius = innerRadius * 1.1;

//.....some more code....

var svg = d3.select("body").append("svg")
    //.attr("width", width)
    //.attr("height", height)
    .attr("viewBox", "0 0 " + width + " " + height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

//.....some more code....

Full code available as gist or demo. SVG in action

That’s it! We’re done, but as long as we use Firefox, Chrome or Opera. As soon as you test it in IE, this code fails. (PS: I don’t have access to mac or safari to comment on it, but I assume that it’ll work as it is a webkit browser.)

Hacking for IE

IE notoriously sets the height of svg to 150px. The workaround for this is called ‘padding-hack’.
What we need to do is
1. Wrap the svg in a container div. (You can use any other element too.).
2. Set the position of the container as relative and that of svg as absolute.
3. Calculate the aspect-ratio of the svg.
4. Apply the aspect-ratio to container using padding.

<div class="svg-container">
    <svg viewBox="0,0, 960, 500">

    </svg>
</div>
.svg-container{
    position: relative;
    width: 100%; /* conatiner-width */
    height: 0;
    padding-top: 52.083%;  /* (svg-height/svg-width) * container-width => (500/960) * 100 */
}

.svg-container > svg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

Full code available as gist or demo. SVG in action

Now we are done. Now we have a cross-browser responsive svg.

Leave a Reply