I have a problem with sizing my canvas element properly. The result as seen below is a canvas element (green outline) that extends it’s height outside of it’s parent div. What is causing this problem and what can I do to fix it?
HTML: Here is the HTML code, there isn’t much to it.
<div id="container"> <div id="content"> <div id="menu"> ... </div> <div id="canvas-container"> <canvas> </canvas> </div> </div> </div>
SCSS: The more interesting SCSS code.
* { margin: 0; padding: 0; } html, body { height: 100%; font-size: 16px; font-family: 'Inter', sans-serif, } #container { height: 100%; display: flex; align-items: center; justify-content: center; #content { outline: 2px solid rgb(0, 0, 0); width: 80%; height: 80%; #menu { padding: 1em; border-bottom: 2px solid black; select { padding: 1em; } a { background-color: rgb(91, 134, 195); text-decoration: none; font-weight: bold; padding: 0.8em; color: white; } a:hover { background-color: rgb(75, 122, 189); } } #canvas-container { width: 100%; height: 100%; canvas { outline: 2px solid green; } } } }
Javascript: And lastly the JS code that actually does the sizing of the Canvas element.
var canvas = document.querySelector('canvas'); fitToContainer(canvas); function fitToContainer(canvas){ // Make it visually fill the positioned parent canvas.style.width ='100%'; canvas.style.height='100%'; // ...then set the internal size to match canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; }
Advertisement
Answer
Whenever you use a height of 100% and you want the height based on it’s parent, you need to set the parents position to relative.
Also the layout your using looks like it will fit into a flexbox layout nicely.
Lastly, if you want this to be responsive, your going to want to attach a resize event for setting the canvas size.
Below is an example of using these techniques, I’ve also included a footer section, flexbox makes these layout a breeze. hint: run the snippet fullscreen, and resize the window to see the resizing in action.
const c = document.querySelector('canvas'); const cc = document.querySelector('.canvas-container'); function drawSomething() { const ctx = c.getContext('2d'); const w = c.offsetWidth; h = c.offsetHeight; const cnt = 25; const sw = w / cnt; sh = h / cnt; for (let l = 0; l <= cnt; l ++) { ctx.moveTo(0, l * sh); ctx.lineTo(w - l * sw, 0); ctx.moveTo(w, l * sh); ctx.lineTo(l * sw, 0); ctx.moveTo(0, l * sh); ctx.lineTo(w - l * sw, h); ctx.moveTo(w, l * sh); ctx.lineTo(l * sw, h); } ctx.stroke(); } function resize() { c.width = cc.offsetWidth; c.height = cc.offsetHeight; drawSomething(); } window.addEventListener('resize', resize); resize();
body { margin: 0; } .container { overflow: hidden; display: flex; flex-direction: column; height: 100vh; } .header, .footer { color: white; background-color: green; } .canvas-container { flex: 1; position: relative; } canvas { background-color: lightgreen; position: absolute; }
<div class="container"> <div class="header">This is the menu</div> <div class="canvas-container"> <canvas></canvas> </div> <div class="footer">footer</div> </div>