Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Responsive charts issue when using FlexBox or CSS grids #411

Open
ozziexsh opened this issue Jan 4, 2019 · 21 comments
Open

Responsive charts issue when using FlexBox or CSS grids #411

ozziexsh opened this issue Jan 4, 2019 · 21 comments
Labels

Comments

@ozziexsh
Copy link

ozziexsh commented Jan 4, 2019

Reproducible demo here: https://codesandbox.io/s/lp16vvz6n7

As you can see, the top chart here (in the flex row) is not responsive.

Happy to help contribute if no one on the core team immediately knows. It might have something to do with react-measure that's used in @nivo/core for the <ResponsiveWrapper> component.

@ja0nz
Copy link

ja0nz commented Mar 26, 2019

I solved this issue with the AutoSizer HOC.

import { AutoSizer } from 'react-virtualized'
<AutoSizer>
    {({ height, width }) => (
        <Pie
            height={height}
            width={width}
            ...
         />
    )}
</AutoSizer>

Because of the known issues like "infinitely growing diagrams" I almost always use the AutoSizer wrapper in favour of the <Responsive*> components.

@timmydoza
Copy link

I ran into this issue too. I ended up using Recharts instead because I was on a deadline and I needed something that worked. It's unfortunate, because the Nivo charts certainly look better.

@Pearce-Ropion
Copy link

@ja0nz Wow this works great. I've been using React Virtualized for a while now but I never would have thought to use its auto-sizer. Thanks

@ConnorTCM
Copy link

ConnorTCM commented May 2, 2019

I was having the same issue when using the <ResponsiveLine> component inside a flex container. Strangely, when increasing the viewport width the chart would resize perfectly, but when decreasing it the chart would stay as it was as its widest point. Refreshing the page would fix everything again.

I've since implemented @ja0nz solution (as well as changing from <ResponsiveLine> to <Line>) and can confirm that it works a treat.

@plouc plouc added the bug label May 2, 2019
@tomaswitek
Copy link

react-virtualized is a great library but quite heavy.
There is a separate package for auto sizing called react-virtualized-auto-sizer.

The following code is a light-weight version of @ja0nz's solution.

import AutoSizer from "react-virtualized-auto-sizer";

@tanmaybhatt
Copy link

tanmaybhatt commented May 8, 2020

Minor addition to @ja0nz's solution. I think AutoSizer width should be 100% to keep the tooltips inbound.

import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
<AutoSizer style={{ width:'100%' }}>
    {({ height, width }) => (
        <Pie
            height={height}
            width={width}
            ...
         />
    )}
</AutoSizer>```

@popa-marius
Copy link

Like @tanmaybhatt said, the tooltip (both anchor and tooltip width) has problems when using @ja0nz 's solution.
To sum it up, the Autosizer container for the chart has 0 width, which causes the tooltip calculation to incorrectly detect a width of 0 all the time here

if (x < bounds.width / 2) anchor = 'right'

which then decides to always use the same anchor direction.

My fix for it was something like this:
(do take into account that my chart has a fixed height)

    <AutoSizer disableHeight>
      {({width}) => (
        <div style={{width: width + 'px'}}>
          <Line
            height={500}
            width={width}
           //...
          />
        </div>
    </AutoSizer>

@ronsigter
Copy link

ronsigter commented Jul 1, 2020

Reproducible demo here: https://codesandbox.io/s/lp16vvz6n7

Got similar problem and tried to tinker with your sandbox.
I solved this by adding min-width: 0

.flex-1 {
  flex: 1 1 0%;
  min-width: 0;
}

@carloscastelano
Copy link

carloscastelano commented Aug 3, 2020

@ronsigter, like this:

<div style={{
     minWidth: 0, 
     height: 400}}>
     <WaffleChart data={data} />
</div>

?

Didn't work here

@outlawpractice
Copy link

Any update on this bug? I am seeing the same behavior in both flexbox and grid. react-virtualized doesn't feel like a great work-around for me.

@Nathaniel-Fernandes
Copy link

Nathaniel-Fernandes commented Dec 17, 2020

I tried to use Autosizer but then any buttons one below the chart component are unclickable. Any thoughts?

Edit: I know the problem now but not the solution. The <Autosizer> component is in a <div> with a button. The Parent <div> height is 400px. The button is 20px. The <Autosizer> assumes the parent's full height of 400 instead of 380 px. I'm not familiar with Autosizer, so is this the expected behavior?

@TerryCLAWong
Copy link

I think I had a similar issue where my <ResponsiveBar> would respond if zooming out but would not shrink when zooming in with my React app. The fix was to put the <ResponsiveBar> into a <div> that had a width of less than 100%.

So the following fixed my problem:

<div style = {{width: "99%"}}>
<ResponsiveBar
...
/>
</div>

@hjdr
Copy link

hjdr commented Feb 15, 2021

Not an ideal solution but setting the width of the parent container to 100vw worked. Had to use the calc function to take into account padding and side nav, but it will do for now until Nivo release a fix.

also @TerryCLAWong's solution works perfectly too

@luizeboli
Copy link

Solution from @ronsigter worked for me 👍🏻

@plouc plouc changed the title Charts are not responsive when inside a Flex Row Responsive charts issue when using FlexBox or CSS grids Aug 25, 2021
@yasincaliskan
Copy link

@ronsigter 's solution worked! I added it to container class.

@gravyboat
Copy link

gravyboat commented Sep 15, 2021

Wasn't a big fan of the container class solution due to how my app is set up so I had to do the following on a Typescript React app where flexbox is used.

My pie chart component looks like this:

interface pieData {
  id: string
  label: string
  value: number
  color: string
}

interface pieProps {
  data: pieData[]
  minHeight?: number | string
  minWidth?: number | string
}

export const DatavizSVGPie = ({
  data,
  minHeight = 0,
  minWidth = 0
}: pieProps) => {
  return (
    <div
      style={{
        minHeight: minHeight,
        minWidth: minWidth,
        height: '100%',
        width: '100%'
      }}
    >
      <ResponsivePie
        data={data}
        ...
      />
    </div>
)

Then on the page where I'm using the component:

<div className="flex gap-6">
  <div className="flex-1 flex flex-col items-center justify-center">
    <DatavizSVGPie data={pieDataFormattedData} minHeight={292} />
  </div>
</div>

minHeigth and minWidth are provided as variables to the component but default to 0. This covers cases where you have a large legend that has to be accounted for such as the demo of programming languages provided on the main Nivo site.

This correctly inherited the height and width of the flexbox so it doesn't have to be set manually.

@okbakhenissi
Copy link

Hello, Is there any update concerning this issue. The workarounds proposed are working, however it's better to have a fix.
Thank you in advance

@rhadamez
Copy link

Using the min-width: 0 worked for me too. Thanks.

@jonasbjoralt
Copy link

I think I had a similar issue where my <ResponsiveBar> would respond if zooming out but would not shrink when zooming in with my React app. The fix was to put the <ResponsiveBar> into a <div> that had a width of less than 100%.

So the following fixed my problem:

<div style = {{width: "99%"}}>
<ResponsiveBar
...
/>
</div>

This was the correct solution for me too. I tried using minWidth but it didn't work.

I also noticed some strange behaviour too: If you set width: "99.9%" and animate={false}, you'll see a really slow animation of the graph shrinking to the correct size. With width: "99.5%" the animation is there still, but much faster. At "99%" the animation roughly keeps up with me scaling the window so it's no longer that visible

@mmirus
Copy link

mmirus commented Apr 27, 2023

This seems like a good solution so far:

<div
  style={{
    display: 'grid',
    gridAutoColumns: 'minmax(0, 1fr)',
    height: '24rem',
  }}
>
  <ResponsiveLine ... />
</div>

Note that, as shown, your container must have a height as well as the grid-auto-columns value.

@Mordecaikama
Copy link

Mordecaikama commented Jul 17, 2023

display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: minmax(0px, 1fr);
height: 300px;

this is for the grid container, grid template columns depends on the number of grid items within the container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests