Search code examples
highcharts

How make the chart of Highcharts to be responsive?


I work with [email protected] && [email protected] && react@19 and saw millions of similar questions in StackOverflow how to make the chart responsive, but I didn't figure out how to do it.

I have a lot of different charts, and I want them to fit 100% of their parent div, no matter what. That's all. Many times I see that in the first load the chart take 100% height and width, but in my app the client can change the height & width of "parent" div, and then it's no more responsive.

To reproduce the problem here is the code:

.App {
  font-family: sans-serif;
  text-align: center;
}

.parent {
  height: 200px;
  width: 600px;
  background: red;
  padding: 10px;
}

import { useEffect, useRef } from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";

import "./styles.css";

const options = {
  title: {
    text: "My chart",
  },
  series: [
    {
      data: [1, 2, 3],
    },
  ],
};

export default function App() {
  const chartRef = useRef();

  useEffect(() => {
    const container = chartRef.current?.container.current;
    container.style.height = "100%";
    container.style.width = "100%";
    chartRef.current?.chart.reflow();
  }, [chartRef, chartRef.current]);

  return (
    <div className="App">
      <h1>Hello to Highcahrts dynamic height problem</h1>
      <div className="parent">
        <HighchartsReact
          highcharts={Highcharts}
          options={options}
          ref={chartRef}
        />
      </div>
    </div>
  );
}

Link to codesandbox: https://codesandbox.io/p/sandbox/6jsx4p?file=%2Fsrc%2FApp.js%3A1%2C1-41%2C1

Result: enter image description here

It simply overflows the parent div.

The docs says:

By default (when null) the height is calculated from the offset height of the containing element, or 400 pixels if the containing element's height is 0.

from: https://api.highcharts.com/highcharts/chart.height

So in the example above, the height of the arent is hardcoded 200px, and still the chart somehow decide that the parent height is 0 and apply 400px on the chart.

Any idea how to solve it?


Solution

  • To ensure Highcharts adapts to its parent container, observe size changes in the parent and trigger a chart reflow(). This can be achieved using ResizeObserver, as shown below:

    import React, { useEffect, useRef } from "react";
    import Highcharts from "highcharts";
    import HighchartsReact from "highcharts-react-official";
    
    import "./styles.css";
    
    const options = {
      title: {
        text: "My chart",
      },
      series: [
        {
          data: [1, 2, 3],
        },
      ],
    };
    
    export default function App() {
      const chartRef = useRef(null);
      const parentRef = useRef(null);
    
      useEffect(() => {
        const parent = parentRef.current;
    
        if (parent && chartRef.current) {
          const resizeObserver = new ResizeObserver(() => {
            if (chartRef.current?.chart) {
              chartRef.current.chart.reflow();
            }
          });
    
          resizeObserver.observe(parent);
    
          return () => {
            resizeObserver.disconnect();
          };
        }
      }, []);
    
      return (
        <div className="App">
          <h1>Hello to Highcharts dynamic height problem</h1>
          <div
            ref={parentRef}
            className="parent"
            style={{
              height: "200px",
              width: "400px",
              background: "red",
              padding: "10px",
            }}
          >
            <HighchartsReact
              highcharts={Highcharts}
              options={options}
              ref={chartRef}
              containerProps={{ style: { height: "100%", width: "100%" } }}
            />
          </div>
        </div>
      );
    }
    

    Demo: https://codesandbox.io/p/sandbox/highcharts-dynamic-height-forked-mwc3j3?file=%2Fsrc%2FApp.js%3A1%2C1-63%2C1&workspaceId=ws_SQD7xuD6UZfZrJ83WwT92Y