Home > OS >  Adaptive canvas width in flexbox layout w/ ResizeObserver
Adaptive canvas width in flexbox layout w/ ResizeObserver

Time:10-29

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.

  • Related