'Chart.js 3.x migration problem – thin white border / padding appears around chart on first load

I'm using Chart.js with a React wrapper (react-chartjs-2). I want to upgrade to the latest major version of Chart.js (3.x) to remove the dependency on moment, among other benefits. There are lots of breaking changes in 3.x, and I've gotten nearly everything working again with all the breaking changes, except for this one infuriatingly small thing that's making me pull my hair out.

There is a tiny white border around the whole chart that I cannot for the life of me get rid of. The weird part is that it disappears when the data for the chart changes and it causes a re-render. This is what it looks like:

chart with white border underneath it

And this is what it's supposed to look like (seamlessly disappearing into the next div on the page): chart without white border underneath it

It's probably one line in options that I need to change, but I can't figure out which line it would be. I thought it might be scale.[id].grid.zeroLineColor because the 3.x upgrade guide says this: "scales.[x/y]Axes.zeroLine* options of axes were removed. Use scriptable scale options instead." But I set color using the scriptable options like this:

grid: {
  color: () => "transparent"
}

and that only fixed part of the issue. Because now the "zero line" isn't grey, but there still seems to be 1px of padding or something around the whole chart, on the bottom and on the right side.

I've set every other property I can think of.

Here's what the options look like right now:

const options = {
  hover: { intersect: false },
  borderWidth: 0,
  clip: 0,
  plugins: {
    legend: {
      position: "bottom",
      align: "center",
      display: false,
    },
    tooltip: {
      intersect: false,
      mode: "index",
      callbacks: {
        //This removes the tooltip title
        // title: function () {},
        label: ({ raw }) => {
          return `$${formatNumber(raw)}`;
        },
      },
      //this removes legend color
      displayColors: false,
      padding: 15,
      position: "average",
      pointHitRadius: 20,
      pointRadius: 30,
      caretSize: 10,
      backgroundColor: "rgba(255,255,255,.9)",
      borderColor: rgbaStringFromRGBObj(palette.Vibrant.rgb, 0.35),
      borderWidth: 2,
      bodyFont: {
        family: "Satoshi",
        size: 18,
      },
      bodyColor: "#303030",
      titleFont: {
        family: "Satoshi",
      },
      titleColor: "rgba(0,0,0,0.6)",
    },
  },
  scales: {
    y: {
      ticks: {
        backdropPadding: 0,
        display: false,
      },
      stacked: false,
      grid: {
        drawBorder: false,
        borderWidth: 0,
        drawTicks: false,
        color: "transparent",
        width: 0,
      },
      drawBorder: false,
      drawTicks: false,
    },
    x: {
      padding: 0,
      ticks: {
        display: false,
        padding: 0,
        mirror: true,
        backdropPadding: 0,
      },
      grid: {
        drawBorder: false,
        drawTicks: false,
        display: false,
      },
      drawBorder: false,
      drawTicks: false,
    },
  },
  maintainAspectRatio: false,
}

and here's a pull request with all the code in context.

Thanks for reading!



Solution 1:[1]

This problem was happening for me when responsive was set to true in the chart's options because the width and height that the chart assumes is set to the "ones" place - it doesn't include decimals. Example:

enter image description here

vs.

enter image description here

The canvas rendered by ChartJS ignores the decimal-level specificity of its parent wrapper... Whether by bug or by design.

Solution

In my case, the aforementioned bug resulted in a small white line at the bottom of the chart.

I got around the problem by setting the parent's style to display: flex; and flexing the chart to the end with flex-direction: column; and justify-content: flex-end. Since the chart was slightly shorter than the parent, flexing it to the end (bottom) of its parent wrapper effectively "removed" the white line.

Generally: Experiment with positioning the chart with knowledge that it's probably a fraction of a pixel less wide/less tall than its parent.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nick