Open ouqu5 opened 1 year ago
Hi ouqu5, have you tried to set the option maintainAspectRatio to false? And also, you will probably need to set the width and height in the parent container, not in the canvas element.
Read this docs about responsiveness: Responsive charts, read the important note about responsive charts and also check this example which is full responsive.
I know that maintainAspectRatio fixes this problem but it should work event with this option enabled. I've followed all steps in docs so my chart setup is 100% valid.
Example you've send works because it's using chart.js 3.5.1 version while problem occurs only from version 4 of this library.
@ouqu5 the example also works with the latest version
There is indeed an issue with version 4.x. When reducing size of container, it works. But not when increasing. Last working version 3.9.1.
@igomonteiro example works only because of maintainAspectRatio: false. Try enabling it, as it is by default.
seeing this issue as well, with 4.1.1. in most cases. I would think this should work regardless of what maintainAspectRatio
is set to.
Any update on this? Still appears to be an issue in 4.2.0
From my experience you have to define the height of the container, too, now. maintainAspectRatio respects container height.
By setting an aspect-ratio
on the containing div I was able to get the same responsiveness for graphs using an aspect ratio. This confuses me because it seems like maintainAspectRatio
should control the size of the canvas because if I wanted to size the container I would just size the container in the first place.
Have this issue as well.
I've had this issue as well—I have found a workaround, however. I'm using MUI specifically.
As long as the chart has a sibling that consumes space inside its parent, auto-resizing works. As soon as the chart sits alone in a parent, it will resize down but not up.
This does not work:
return (
<Box>
<Chart
type="bar"
datasetIdKey="name" // the dataset property to use as the unique identifier for the data set. See: https://react-chartjs-2.js.org/docs/working-with-datasets/
options={options}
data={data}
plugins={[legendExtraMargin]}
/>
</Box>
This does not work:
return (
<Box>
<div />
<Chart
type="bar"
datasetIdKey="name" // the dataset property to use as the unique identifier for the data set. See: https://react-chartjs-2.js.org/docs/working-with-datasets/
options={options}
data={data}
plugins={[legendExtraMargin]}
/>
</Box>
This does work:
return (
<Box>
<div> </div>
<Chart
type="bar"
datasetIdKey="name" // the dataset property to use as the unique identifier for the data set. See: https://react-chartjs-2.js.org/docs/working-with-datasets/
options={options}
data={data}
plugins={[legendExtraMargin]}
/>
</Box>
YMMV but hopefully this workaround helps. Obviously, being forced to display something is not ideal, but you could adjust the size of the rendered element to mitigate. Interestingly, making it very small (max-height: 1px
, font-size: 1px
, or line-height: 0.1
) causes the resize to animate very slowly ¯\(ツ)\/¯
I was able to fix this without setting an exact container height by defining an aspect-ratio instead. The default aspect ratio for Chart.js is 2, so doing this restores Chart.js 3 behaviour:
<div class="chart-container" style="aspect-ratio: 2">
<canvas id="chart"></canvas>
</div>
I would suggest just to fix it instead of using workarounds. This is maybe not critical but important issue.
Bumping this issue.
If I pass an onResize function to the options array of a chart component, like onResize: () => {console.log('Resizing chart')},
I am experiencing that the function fires when scaling the chart down, but it doesn't fire when the viewport scales up.
I was able to fix this without setting an exact container height by defining an aspect-ratio instead. The default aspect ratio for Chart.js is 2, so doing this restores Chart.js 3 behaviour:
<div class="chart-container" style="aspect-ratio: 2"> <canvas id="chart"></canvas> </div>
@athisun 's workaround worked for me
Also onResize()
is never being called for me with responsive: true
...
On version 4.2.1
I created a duplicate ticket for this issue (I didn't see this ticket prior to creating that one). I created a couple of Stackblitz demos to show the behavior working in 3.9.1 and not working in 4.3.0. I figured I'd cross-post them here:
Here's the 3.9.1 version, where responsiveness works: https://stackblitz.com/edit/angular-9rtbka
...And here's the 4.3.0 version, where responsiveness doesn't work (I also tried with 4.2.1, and got the same behavior): https://stackblitz.com/edit/angular-bcncvn
As noted above, responsiveness works when the browser width shrinks, but the chart doesn't expand as the browser width grows.
Hope this helps! Thanks!
For me the event was only being triggered when my viewport increased in size, and the height property never seemed to update, only the width.
I was able to fix the issue with with this workaround:
canvas {
width: 100% !important;
height: 100% !important;
}
For what it's worth, I'm using Vue.js and including my charts with PrimeVue. The version of chart.js is v4.3.0
.
If you're using this fix then the styles need adding globally.
I'll throw my hat into this. I have the problem, I - for the life of mine - can not get it to shrink. At all. The example demo seems to work with all relative values, but when I do use percentages in my Angular (+ Tailwind) project, it does not.
<!-- This works! -->
<div class="chart-container w-[80vw] h-[300px]">
<canvas #chart [id]="chartId" aria-label="Chart" role="img">
<p>Chart could not be loaded</p>
</canvas>
</div>
However...
<!-- This works! -->
<div class="chart-container w-[100%] h-[300px]">
<canvas #chart [id]="chartId" aria-label="Chart" role="img">
<p>Chart could not be loaded</p>
</canvas>
</div>
Does not.
I - for the life of mine - can not get it to shrink
@akleimrey This is likely since the new resize behaviour prioritizes maintaining the container height. Have you tried the above method of setting an aspect ratio instead of a height and width? https://github.com/chartjs/Chart.js/issues/11005#issuecomment-1475697112
I - for the life of mine - can not get it to shrink
@akleimrey This is likely since the new resize behaviour prioritizes maintaining the container height. Have you tried the above method of setting an aspect ratio instead of a height and width? #11005 (comment)
@athisun I did but to no result. But in a perfect "Rubber Duck" problem-solving moment, I got a bit closer to my problem. My problem is the flexbox, but I can't simply replace my solution. It basically looks currently like this:
<div id="main" class="flex flex-col min-h-[100%] dark:bg-dark-background dark:text-background">
<app-header></app-header>
<div id="content" class="lg:w-[75rem] mx-auto">
<router-outlet>
</router-outlet>
</div>
<app-footer></app-footer>
</div>
And my dashboard page looks rather simple like that:
<app-map></app-map>
<app-chart [plugins]="plugin" chartType="HORIZONTAL_BAR"></app-chart>
<app-chart [plugins]="plugin2" chartType="BAR"></app-chart>
With a single chart component just looking like this:
<div class="chart-container w-[90%] h-[300px]">
<canvas #chart [id]="chartId" aria-label="Chart" role="img">
<p>Chart could not be loaded</p>
</canvas>
</div>
So, the div with the id main is mostly used to at least occupy 100% space but is also used to always at the minimum have the footer at the bottom, without having to define positions. If the content is larger, the page grows nicely. I'm going through solutions to make this work, but apparently, there is no single simple solution ever.
None of these are permanent solutions, though, right? We have a clear regression in behavior from 3.9 to 4.x when it comes to how responsive charts behave (in particular, when the browser increases in width). There are no indications in the documentation that this is a breaking change--if there were a documented best practice going forward (e.g., some kind of different CSS on the canvas
or parent tag), then I think we could all happily upgrade. So until we hear otherwise, this just feels like a bug that needs to get addressed at the library level, rather than library consumers figuring out workarounds which may or may not work.
If I've missed something, and there really is documentation that this is a breaking change and we need to invoke our charts in a different fashion, I retract my above statement.
For me the event was only being triggered when my viewport increased in size, and the height property never seemed to update, only the width.
I was able to fix the issue with with this workaround:
canvas { width: 100% !important; height: 100% !important; }
For what it's worth, I'm using Vue.js and including my charts with PrimeVue. The version of chart.js is
v4.3.0
.If you're using this fix then the styles need adding globally.
This worked for me using PrimeVue 3.25.0 and chart.js 4.3.0.
I am also observing the fact that the options.onResize
function is only called when the container gets smaller; it doesn't fire when the container gets larger.
I am also observing the onResize function getting called occasionally in an infinite loop when the container gets smaller. I put a console.log in there and sometimes it logs 100s of times in a few seconds; it seems to catch itself if you continue resizing, but something occurs to make it decide to call onResize infinitely.
I have same behavior with css
table-layout: fixed
https://angular-chart-js-nhvr2v.stackblitz.io
When the view grows, charts grow accordingly, when view goes smaller, chart size doesn't change correctly. When outside change is triggered, ie. do onblur from input, chart sizes are correct again. What's more, if I try the workaround of setting canvas size, the behavior changes to the opposite, increasing doesn't work and decreasing does.
I tried to replicate my use case as closely as possible, but it is kind of extreme behavior, so maybe this is not the best example for the problem, but leaving it here anyway in case it helps. It is very stable solution though in the environment I use it, the decreasing size is the only problem.
I have the same problem. When responsive and maintaining aspect ratio the chart does not properly resize on expand. Collapsing works fine.
When the view grows, charts grow accordingly, when view goes smaller, chart size doesn't change correctly.
🐛 Same issue. You have to reload the page after an enlargement to get the correct size of the chart again.
📖 I using chart.js@4.3.0
, vue-chartjs@5.2.0
and nuxt@3.5.3
.
Same issue. The chart scales down when page size reduces but does not properly expand when page size increases again. I have to reload the page to get back the correct size of the chart.
Example is shown here: https://www.teyanglau.com/ (on the nested radial chart)
This still appears to be a problem in 4.4. Is there any word at all on the status of this issue? I don't think I've seen any of the library maintainers chime in on this thread.
@etimberg Apologies for pinging you, but it would be great if you or one of the other maintainers could chime in on this issue. This seems like a clear regression from 3.9.x to 4.x.x, and it's preventing (at least) those of us on this thread from upgrading to 4.x of the library. I can't find anywhere in the docs that indicates this is a breaking change which involves some modification to how we invoke ChartJS for responsiveness.
Thanks!!
Had the same issue, and for me this proposal solved it - https://github.com/chartjs/Chart.js/issues/11243
So one thing to do was to use aspect-ratio
in chart container:
Using the
aspect-ratio
property it's possible to make a chart fit nicely within the parent container's width instead of the window size.
And what actually fixed the scaling issue when you resize the window to expand it - is to use overflow: hidden
:
overflow: hidden
is also needed otherwise the height won't change and won't trigger a redraw.
<div class="chart-container" style="position: relative; width: 100%; aspect-ratio: 2/1; overflow: hidden;">
<canvas id="chart"></canvas>
</div>
That sounds like some sort of css issue, but still it should be addressed in some way by the Chart.js (as a fix, or in docs).
All credits goes to @PeterN !
ChartJS also has an aspect ratio attribute. Do you need to set both in order for this to work? Also, do things work correctly if you change the aspect ratio after load?
@sergei-krylov it looks like that...works? Here's a Stackblitz:
https://stackblitz.com/edit/angular-dhvdfm
That works on a Mac in Chrome, Safari, Edge, and Firefox for me. (Testing was very limited, though)
The one thing to note is that, at least for me, the css aspect-ratio
needs to match the aspectRatio option passed into ChartJS. Is that your experience as well? And have you tried changing the aspect ratio dynamically (e.g. when screen size crosses a particular break point, change aspect ratio)?
If this works, then that's great, but it still bothers me that none of the maintainers have chimed in on this front. Without any sort of official word from them that
Do you need to set both in order for this to work?
For that way of doing things - no, you don't need to set aspect ratio in chart options, and even if you do, it seems ignored (at least in my case). Can set it only for container, or match it for both chart and container.
Also, do things work correctly if you change the aspect ratio after load?
Yes.
And have you tried changing the aspect ratio dynamically (e.g. when screen size crosses a particular break point, change aspect ratio)?
I'm changing this "dynamically", but not depends on screen size. In my case I need the chart to stay with fixed aspect ratio no matter the screen size. And only change the aspect when it changes by clicking a button (it's a bit more complicated, but could be just that). And it works well.
What makes it work is having the aspect-ratio
in container style, and adding the overflow: hidden
to container as well, that's the key thing that triggers the chart to redraw when scaling down.
I am also observing the fact that the
options.onResize
function is only called when the container gets smaller; it doesn't fire when the container gets larger.
(👆 mentioned previously in the thread) This is true for me without the overflow: hidden
. And onResize
is fired properly when it's added.
Actually, that's not truly a fix, but more a workaround. You control the aspect ratio not through Chart.js itself by passing the aspect ratio value to the chart options, you control it by setting it to the container instead, so container controls its size. And overflow: hidden
forces the container to resize when you update container's aspect ratio css value, so in turn it also triggers a resize for the chart.
At least that's how I understood what's happening there 😄
Another different thing is that having aspect ratio in container allows you to display and resize all types of the charts in the same way. Otherwise, the default aspect ratio for bar
chart is 2
, for example. So if you set aspect ratio as 2
for all of your charts - the bar
ones will result in 4
actually and will still be displayed twice wider (or twice as low as others) in comparison to pie
or other charts.
That was the thing for me to also consider and "fix" - I was need all types of charts to be displayed and behave in the same way. It differs and changes the standard behavior and probably a thing to consider if you go that way of handling the aspect ratio.
@sergei-krylov thanks for the reply. In the Stackblitz I linked above: https://stackblitz.com/edit/angular-dhvdfm
...I do need aspectRatio set in both places. if I remove it from the ChartJS config, the chart won't take up 100% of the available width. But if that is really all it takes for this to be a stable solution, that would be pretty great. I still don't trust it, though...
Hello fellas, this issue seems to still be there, also on the official documentation examples.
We're almost to the one year mark of this issue getting opened. Does anyone have any insight into whether a fix for this will be prioritized? Thanks!
style="aspect-ratio: 2"
This helped. I was reading through the documentation but no luck. Glad I found this. Thank you
style="aspect-ratio: 2"
This helped. I was reading through the documentation but no luck. Glad I found this. Thank you
Not the best solution since it will force the canvas area to 2:1 aspect ratio for all charts and breakpoints, which is probably not what you want.
The best solution I’ve found so far that isn’t a design tradeoff is to make sure there’s always a sibling element (like an empty div) before or after the canvas element. If you have a React component wrapper or something, it’s easy to ensure this always happens.
style="aspect-ratio: 2"
This helped. I was reading through the documentation but no luck. Glad I found this. Thank you
Not the best solution since it will force the canvas area to 2:1 aspect ratio for all charts and breakpoints, which is probably not what you want.
The best solution I’ve found so far that isn’t a design tradeoff is to make sure there’s always a sibling element (like an empty div) before or after the canvas element. If you have a React component wrapper or something, it’s easy to ensure this always happens.
I will also try to look into this. Thank you
I had the same problem. Using chart.js
(version 4.4.1), vue
, vue-chartjs
and bootstrap
.
Applying the workaround from @athisun worked for me. So I'm now defining the aspect-ratio on the chart parent container: I changed the parent div from <div class="row">
to <div class="row ratio" style="--bs-aspect-ratio: 50%">
.
Hopefully this issue will be fixed in the Chart.js library in the future, then this workaround should not be required anymore.
Using a Blazor Web Assembly app I couldn't get any of these solutions to resize the chart back to being larger once the browser window is made larger again. The canvas has a hardcoded width and height added to it which changes if you make the window smaller but remains the same if you make the window larger again. If you edit the canvas width and height in the built in browser dev tools or just remove them (they are repeated in there again in the style tag) then it goes back to being the full size. So it's hardly responsive with the hardcoded size. Then I realised the bug is even present on the examples on the ChartJS website such as the bar chart here: https://www.chartjs.org/docs/latest/charts/bar.html
Make the window small so the bar chart goes smaller then make the window full screen and the chart remains small.
I have found 2 fixes which trigger when the window is resized to either refresh the page or modify the canvas tag.
In the end I went for this which worked for me and means you get the nice little chart animation as it loads: https://stackoverflow.com/a/37008766/915426
In case the linked article goes here is the JS for it:
var resizeTimeout;
window.addEventListener('resize', function(event) {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function(){
window.location.reload();
}, 1500);
});
The timeout part is there so that if dragging a window to resize you don't end up with too many requests to refresh.
Using version 4.4.1 in a blazor web app (.net 8) and had the same issue. @athisun 's solution worked for me as well.
@robinwilson16 I got it working with the aspect-ratio workaround, the scss looks like this:
.chart-container {
width: 100%;
padding: 10px;
aspect-ratio: 2;
canvas {
width: 100%;
}
}
Chart.js 4.2 - Can't believe this is still not fixed...
I am using it in react-charjs-2 and @ZLevine solution "fixed" it for me. Although I agree this makes the enlargement animation kind of choppy and slow...
Over a year with this issue, it's preventing us from upgrading to v4 - is there a plan to work on this?
@etimberg could you please give us some kind of update on this issue? Those of us on this ticket have been unable to update to 4.x because of this issue, and (unless we have all missed something) it's a serious enough regression that we cannot upgrade until this is addresses. Much appreciated in advance!
Respectfully, repeatedly pinging the maintainers is poor practice. If there are no contributions to be made, consider upvoting the issue and subscribing to the thread instead of commenting, since it unnecessarily notifies everyone in the thread and makes it harder for newcomers to find the existing workarounds above. There are plenty of technical people in this discussion that could assist the maintainers by investigating further. I'll start:
Based on the release notes, I believe the breaking change was introduced in Release v4.0.0-alpha.1, in file src/helpers/helpers.dom.js
(now helpers.dom.ts, with these 2 related Pull Requests:
I'd like to experiment with reverting these 2 commits locally and checking if the original behaviour returns, but I haven't the time right now. If it does resolve the issue, then we could look at adding extra unit tests and amending the logic to pass all tests.
If anybody else is interested in experimenting, that's where I'd start.
@athisun you're not wrong at all. My apologies. I have both upvoted and followed this issue (for nearly a year, I think), so partially it's just frustration making me do it. I'll also say that the issue at hand seems so severe that I don't understand how anybody could use the 4.x release in a modern web environment where nearly everything is responsive. And that's why I'd like the maintainers to weigh in--maybe there's something deeper at play, or maybe it's just missing documentation, since there is a workaround in this thread that for all I know is the right way to do things moving forward. Kudos to you for looking at the PRs, though.
in case this solution is helpful for others, @wfortin and i found that since the canvas is struggling to rerender even given changes to its parent container through react code, we can utilize css to force dimension updates. the docs mention needing a parent wrapper exclusive to the canvas and with relative positioning, so if we give the canvas absolute positioning, it will be able to update itself accordingly (because your parent container knows it's own layout ie. through flexbox etc)
const ChartWrapper = styled.div`
position: relative;
height: 100%;
// forces canvas to rely on its parent container's dimensions
canvas {
position: absolute;
}
`;
I don't know if i'm doing something wrong, but I seem to get the exact opposite of this issue. The chart resizes up to expand and fill available space, but doesn't resize down leading to an overflow, which I must either allow or hide affecting the layout of the page.
I'm using chart.js 4.4.2 and react-chartjs-2 5.2.0
I would like anybody to pls help me know, if it's the same issue here, or this is just peculiar to me.
@dew-dr0p I had the same problem as you, @skinsshark `s answer worked for me, a wrapper div with those css of his answer.
Another thing that worked as a temporary solution before i found this canvas css, was putting another div wrapper with height 99% and width 99%, strangely it worked too.
I think some engineering will need to be done to resolve this permanently. I have had to resolve to either using the 2.5.0 library and figuring out the syntax for charting for such an old version or 3.9.1 with some fiddly styling in the container div to make it work ( eg. style="position: relative; width: 100%; aspect-ratio: 2/1; overflow: hidden;")
What can we do to help the team get this resolved?
Expected behavior
Chart should be resized when window size changes. (now it resizes only when scaling to smaller resolution)
Current behavior
I am using "responsive" option to resize chart based on it's parent container size. Everything works while scaling window size down, but when it comes to changing window resolution to larger one that doesn't work.
Reproducible sample
https://codepen.io/ouqu5/pen/ZEjEPqm
Optional extra steps/info to reproduce
Possible solution
No response
Context
No response
chart.js version
4.1.1
Browser name and version
No response
Link to your project
No response