I want to make canvas-based uPlot plots responsive in width.
The ResizeObserver
observes the parent div width and changes the plot/canvas width accordingly.
It works for simple layouts. If the parent div is part of a flexbox layout, growing works, but shrinking doesn't. Why?
const plotContainer1 = document.getElementById("plot-container1");
const plotContainer2 = document.getElementById("plot-container2");
const plot1 = document.getElementById("plot1");
const plot2 = document.getElementById("plot2");
const resizeObserver1 = new ResizeObserver(() => {
plot1.width = plotContainer1.clientWidth;
});
resizeObserver1.observe(plotContainer1);
const resizeObserver2 = new ResizeObserver(() => {
plot2.width = plotContainer2.clientWidth;
});
resizeObserver2.observe(plotContainer2);
.container {
display: flex;
}
.left {
width: 300px;
flex-grow: 0;
flex-shrink: 0;
}
.main {
width: 100%;
flex-grow: 0;
flex-shrink: 1;
}
.plot-container {
background: red;
}
.plot {
display: flex !important;
background: black;
}
<h1>Plot full width</h1>
<div class="plot-container" id="plot-container1">
Plot 1
<canvas class="plot" id="plot1"></canvas>
</div>
<h1>Plot in flexbox layout</h1>
<div class="container">
<div class="left">Navigation</div>
<div class="main">
<div class="plot-container" id="plot-container2">
Plot 2
<canvas class="plot" id="plot2"></canvas>
</div>
</div>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Example on codepen: https://codepen.io/lukasberbuer/pen/LYjLmdE
CodePudding user response:
Because as it seems, display:block
and display:flex
have a slightly different behaviour when it comes to their width. By default, both their width is 100% that of their parent. When the parent grows, they grow with it. Now when the parent shrinks, they are both trying to keep their width 100% that of their parents, BUT they contain something. They contain a canvas whose witdh has been constrained. So there's a conflict between the parent shrinking from the outside and the canvas pushing from the inside.
I believe display:block
prioritizes the parent and shrinks, allowing in return the canvas to be resized down.
But display:flex
seems to prioritize the canvas and is prevented from shrinking.
CodePudding user response:
A detailed answer can be found here: https://stackoverflow.com/a/36247448/9967707
Simply had to add min-width: 0 !important;
to .main
.