What's the best way to make a d3.js visualisation layout responsive?

d3.js, javascript, responsive-design

Solution

There's another way to do this that doesn't require redrawing the graph, and it involves modifying the viewBox and preserveAspectRatio attributes on the `<svg>` element:

<svg id="chart" viewBox="0 0 960 500"
  preserveAspectRatio="xMidYMid meet">
</svg>

Update 11/24/15: most modern browsers can infer the aspect ratio of SVG elements from the `viewBox`, so you may not need to keep the chart's size up to date. If you need to support older browsers, you can resize your element when the window resizes like so:

var aspect = width / height,
    chart = d3.select('#chart');
d3.select(window)
  .on("resize", function() {
    var targetWidth = chart.node().getBoundingClientRect().width;
    chart.attr("width", targetWidth);
    chart.attr("height", targetWidth / aspect);
  });

And the svg contents will be scaled automatically. You can see a working example of this (with some modifications) here: just resize the window or the bottom right pane to see how it reacts.

Problem

Assume I have a histogram script that builds a 960 500 svg graphic. How do I make this responsive so on resize the graphic widths and heights are dynamic? ``` <script> var n = 10000, // number of trials m = 10, // number of random variables data = []; // Generate an Irwin-Hall distribution. for (var i = 0; i < n; i++) { for (var s = 0, j = 0; j < m; j++) { s += Math.random(); } data.push(s); } var histogram = d3.layout.histogram() (data); var width = 960, height = 500; var x = d3.scale.ordinal() .domain(histogram.map(function(d) { return d.x; })) .rangeRoundBands([0, width]); var y = d3.scale.linear() .domain([0, d3.max(histogram.map(function(d) { return d.y; }))]) .range([0, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); svg.selectAll("rect") .data(histogram) .enter().append("rect") .attr("width", x.rangeBand()) .attr("x", function(d) { return x(d.x); }) .attr("y", function(d) { return height - y(d.y); }) .attr("height", function(d) { return y(d.y); }); svg.append("line") .attr("x1", 0) .attr("x2", width) .attr("y1", height) .attr("y2", height); </script> ``` Full example histogram gist is: https://gist.github.com/993912

Original source

Related problems