I have prepared a simple test web page at Github (using the main.css file) for my question:
In a vertical flexbox layout I am trying to use ResizeObserver to watch a parent div element with flex-grow:1 and then keep the 1:1 aspect ratio on its child canvas element.
The reason I am trying to the keep the canvas aspect ratio is that in my real app a PixiJS canvas is embedded in a ReactJS app and if I just scale the canvas element to fill the div parent, then the PixiJS content is stretched:
Unfortunately, the parent
div element pushes the hint
div element off the bottom of the screen -
I think, that something minor is missing in my code, please recommend a fix:
const parentElement = document.getElementById("parent");
const childElement = document.getElementById("child");
const resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
const { width, height } = entry.contentRect;
const minDimension = Math.min(width, height);
console.log(
`parent: ${width} x ${height} -> child: ${minDimension} x ${minDimension}`
);
childElement.style.width = `${minDimension}px`;
childElement.style.height = `${minDimension}px`;
}
});
resizeObserver.observe(parentElement);
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.flexRoot {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: stretch;
width: 100%;
height: 100vh;
}
/* the parent holds: status, canvas, hint */
.parent {
border: 4px solid red;
flex-grow: 1;
}
canvas {
width: 1020px;
height: 1020px;
background-color: yellow;
border: 4px green dotted;
box-sizing: border-box;
}
.hint,
.status {
background: lightblue;
font-style: italic;
text-align: center;
flex-grow: 0;
}
<div class="flexRoot">
<div class="status">Game #1 Score1:Score2</div>
<div class="parent" id="parent">
<canvas id="child"></canvas>
</div>
<div class="hint">A game hint to do this and that...</div>
</div>
To make sure the size of a .parent
is determined by a .flexRoot
instead of a #child
it shouldn't allow an overflow:
.parent {
overflow: hidden;
}
Optional: a canvas is centered using flex
.
const parentElement = document.getElementById("parent");
const childElement = document.getElementById("child");
const resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
const {
width,
height
} = entry.contentRect;
const minDimension = Math.min(width, height);
console.log(
`parent: ${width} x ${height} -> child: ${minDimension} x ${minDimension}`
);
childElement.style.width = `${minDimension}px`;
childElement.style.height = `${minDimension}px`;
}
});
resizeObserver.observe(parentElement);
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.flexRoot {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: stretch;
width: 100%;
height: 100vh;
}
/* the parent holds: status, canvas, hint */
.parent {
border: 4px solid red;
flex-grow: 1;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
canvas {
width: 1020px;
height: 1020px;
background-color: yellow;
border: 4px green dotted;
box-sizing: border-box;
}
.hint,
.status {
background: lightblue;
font-style: italic;
text-align: center;
flex-grow: 0;
}
<div class="flexRoot">
<div class="status">Game #1 Score1:Score2</div>
<div class="parent" id="parent">
<canvas id="child"></canvas>
</div>
<div class="hint">A game hint to do this and that...</div>
</div>