D3.js tutorial - Part 9 - Resize chart

Assume we now want to change the size of our chart in order to get a page width chart. We add the following CSS to our main division in order to get the full width:

#bar-chart { width:100%; background-color:grey; }

Here is the result:

Of course, this is not what we expect. Since we fixed the SVG size in the source code, our chart size does not adapt to our division. Let's improve that!

Get parent size

To adapt our chart to the parent division, we need to know its size. The parent size can be retreived with the style() or getBoundingClientRect() functions.

The style function returns the value of a given CSS property. the following line return the width of the parent division bar-chart:

var width = d3.select("#bar-chart").style('width');

For example, in my case, it returns 385px. the problem with this function is that you have to remove the px string at the end to get an interger:

var width = d3.select("#bar-chart").style('width');
width = parseInt(width);

The second option is to call the function getBoundingClientRect():

var size = d3.select('#bar-chart').node().getBoundingClientRect();

It returns an object containing all the properties of the bounding rectangle, for example:

DOMRect {
    x: 8
    y: 116.875
    width: 385
    height: 0
    top: 116.875
    right: 393
    bottom: 116.875
    left: 8
}

Select to key width to get the width of the parent div:

var width = d3.select('#bar-chart').node().getBoundingClientRect().width;

It returns 385 which is an integer.

Resize our SVG

Once the width is retreived, we can resize our SVG. In the previous example, the width of our chart was twice the height, let's keep this ratio and update our SVG size:

var width = d3.select('#bar-chart').node().getBoundingClientRect().width;
var height = width/2;

// Create our SVG container with grey background
var svg = d3.select("#bar-chart")
            .append("svg")
            .attr("width", width)
            .attr("height", height);

Here is the result:

The SVG is resized, but not the bars.

Resize bars

To solve the previous problem, one solution is to calculate the properties of each element acording to the parent width and height:

// Bind data to chart, and create bars
bars.selectAll('rect')
    .data(dataset)
    .enter()    
    .append('rect')
    .attr('x', (d,i) => i*(width/dataset.length) )
    .attr('y', (d) => height-d*(height/100))
    .attr('width', 0.8*(width/dataset.length))
    .attr('height', (d) => d*(height/100) );

It works, but it is not the best solution. D3.js provides dedicated tools for resizing charts.

See also


Last update : 01/29/2020