I have a full size page, containing a top toolbar, and below, a container with 2 columns:
- a right column
- a left column containing a canvas (centered horizontally and vertically in this column), which has its own coordinates system (typically 4000 x 3000) and should preserve this aspect ratio. This canvas has a "+" button layered on it. (In my real code, there are several canvas for multiple layers, and multiple buttons, but not important here)
Here it nearly works, but I can’t make the canvas occupy the full available space in the left column.
With all methods that I tried (max-width: 100%
, max-height: 100%
), either it fails when we zoom in / out in the browser (70% 80% … 150 %), or it fails because the method used prevents the button to stay on top of the canvas, at its right corner.
TL;DR: how to make this canvas take all available space in the left column, keeping its aspect ratio, keeping the layered buttons, without overflow?
Note: I’m looking for a CSS solution, the JS is not for the positioning, but only the drawing.
ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = "#FF0000"; ctx.fillRect(0, 0, 1000, 1000);
ctx.fillStyle = "#00FF00"; ctx.fillRect(1000, 1000, 1000, 1000);
ctx.fillStyle = "#0000FF"; ctx.fillRect(2000, 2000, 1000, 1000);
ctx.fillStyle = "#000000"; ctx.fillRect(3000, 0, 1000, 1000);
* {
padding: 0;
margin: 0;
}
.page {
display: flex;
flex-direction: column;
height: 100vh;
}
.toolbar {
background-color: yellow;
flex: 0 0 5em;
}
.container {
background-color: orange;
flex: 1 0 0;
display: flex;
}
.left {
background-color: magenta;
flex: 1 0 0;
display: flex;
align-items: center;
justify-content: center;
}
.right {
background-color: salmon;
flex: 0 0 10em;
}
.canvas-wrapper {
background-color: grey;
display: flex;
position: relative;
}
canvas {
height: 100px;
background-color: white;
}
.button {
background-color: yellow;
position: absolute;
top: 0;
right: 0;
width: 1em;
height: 1em;
}
<div class="page">
<div class="toolbar">
TOOLBAR OF HEIGHT 5 EM
</div>
<div class="container">
<div class="left">
<div class="canvas-wrapper">
<canvas width="4000" height="3000"></canvas>
<div class="button">+</div>
</div>
</div>
<div class="right">
RIGHT OF WIDTH 10 EM
</div>
</div>
</div>
PS: you have to open the snippet in "Full page" to see the browser zoom in / zoom out feature (CTRL + , CTRL -).
4
Answers
Here is an answer based on RokBenko's answer which seems to work, without the secondary wrapper and the secondary flex:
You need to change some alignments,
width
s,height
s,flex-grow
s and add an HTML wrapper (i.e.,<div class="canvas-wrapper-inner">
).See the snippet below.
There’s a handy unit size called cqmin which is the lowest size of the inline or block sizes. Set container wrapper as a container of type size so the content responds to both block and inline dimesions then set the width of the canvas to 100cqmin. Use aspect-ratio to maintain the, er, aspect ratio. See example below. I’ve put a codepen of it here too.
This is based on my other answer on the related question. The idea is:
To handle the
+
button, I suggest a similar solution where you wrap the canvas and the button inside a wrapper element which is forced to act like an inline-replaced element: