DavaViz for Everyone: Responsive Maps With D3

Aug 26, 2013

I spent an hour this weekend updating this site to Bootstrap 3, making the site responsive (and mobile first!) by default. That means the next step is to make visualizations that can handle a browser of any size, too.

Let's make maps and charts that resize automatically and work everywhere.

1. Start with a responsive framework

I'm using Bootstrap, but Foundation or any other framework will do fine. Or roll your own. The point is that you want everything responding to changes in the viewport size. This makes the next step easier.

2. Size and scale SVG elements based on their containers.

I used to hard-code dimensions into my maps and charts. Often, this was already duplicating what I'd done in CSS, and it anchored the chart to a certain viewport size. Not on a 13-inch MacBook Pro? Tough.

This gets us 90% of the way to responsiveness, because the map will be rendered at the right size on load. Pull this up on your phone, and it'll fit. Same for your giant desktop.

But it won't adjust if you rotate your phone (or tablet). As much as web developers are the only people who test the responsiveness of sites by resizing the browser, real users really do turn their devices sideways (even by accident). And it's no fun reloading a bunch of GIS data on your phone.

3. Resize when the window size changes.

This turns out to be simpler to solve than I expected. You need to catch window.onresize, and you need to resize the map. Do this by recalculating the container size, adjusting the projection's scale, then re-running the function that originally drew the map. Here's the code:

The reason the last two lines work is D3's data-binding. Remember, each selection is bound to an array of data, and each datum is stored on a corresponding element as __data__. This means you can access it later by simply reselecting the elements, and you can use it by re-setting the d attribute.

The map above is obviously missing things: There's no legend, first and foremost. I'll get to that in my next post. The interaction is also pretty sparse and totally mouse-driven (no hovering on mobile).

This also might not be the best way to present the data, so I'll circle back and do a responsive chart in post three of this series.