Responsive charts with Chart.js

Creating responsive layouts that scale elegantly with screen size is pretty much a default mandate for UI development in 2019. There are plenty of powerful and useful tools at your disposal to help make that happen -- flexbox, for example, or any of the jumzillions of grid-based frameworks out there, or judicious use of media queries (but only judicious use!).

One HTML element that causes some responsive headaches is our old friend canvas. A canvas element's render size is independent of its display size; changing it programmatically has no effect. Check this snippet to see what I mean:

See the Pen canvas responsiveness by john (@perezvon) on CodePen.

Since a lot of charting libraries use canvas elements to draw charts, we can run into some issues here. In particular, I'm working on a project now where I need to show a chart overlaying a video; the video could be any size from a 300px phone screen to a full-width desktop monitor, and my chart will have to scale appropriately.

Luckily, if you're using Chart.js, you've got the solution prepackaged for you already. In fact, it's quite simple, but since the docs are either a tad confusing or I just missed the important line, I thought I might try to shed a small amount of additional light on the subject.

Basically there are three steps involved:

  1. Create a container div with position: relative;
  2. Don't put anything except for your chart's canvas element in that div
  3. Add an option to your chart maintainAspectRatio: false, like so:
  const chart = new Chart(ctx, {
    type: chartType,
    data: chartData,
    options: {
      maintainAspectRatio: false,    }

This setting is the equivalent of what's happening in #canvas3 in our example: the chart itself will fill its parent div if that parent is relatively positioned, and contains the canvas element and no other elements.

For further explanation, check out the very good docs that make perfect sense after you have already spent hours trying to figure out why they don't.

Enjoy and happy coding!