26

I want to resize the canvas element so that if fits its parent, whether it's <body> ("full-screen") or some <div> for instance. This is my attempt:

// called at each frame
function update() {
    var canvasNode = document.getElementById('mycanvas');
    canvasNode.width = canvasNode.parentNode.clientWidth;
    canvasNode.height = canvasNode.parentNode.clientHeight;
}

For some reason, the canvas doesn't stop growing! Maybe client* aren't the right parameters?

See the code in action here: http://jsfiddle.net/ARKVD/24/

Giovanni Funchal
  • 8,934
  • 13
  • 61
  • 110
  • 1
    If the canvas is `155px` high, the body is `160px` high, which makes the canvas keep growing `5px` each time (the body seems to be `5px` ahead each time the canvas grows). I've no idea why, though, since you did set all margins/paddings on `0px`. (This is on Chrome.) – pimvdb Dec 24 '11 at 11:55
  • Thanks, on Linux/Firefox, I'm seeing either 4px or 3px offset (depending on whether my window is maximized or not)... annoying! – Giovanni Funchal Dec 24 '11 at 11:59
  • Weird thing is, if the canvas is set to a height of `0px`, the body is `20px` high. The body only collapses to `0px` if the canvas is actually removed. – pimvdb Dec 24 '11 at 12:08
  • 2
    You also have to set `html`'s height to 100%: http://jsfiddle.net/ARKVD/25/ – Felix Kling Dec 24 '11 at 12:09
  • That's weird. Anyway then it doesn't work in a DIV (I want the canvas to fit it's parent size): http://jsfiddle.net/ARKVD/29/ – Giovanni Funchal Dec 24 '11 at 12:16
  • @GiovanniFunchal A `div` element doesn't have the `width` and `height` attributes. To give it a fixed height and width to it using CSS. – Some Guy Dec 24 '11 at 14:51
  • Post an answer if you know the solution. – Giovanni Funchal Dec 24 '11 at 15:18
  • try this on for size... http://jsfiddle.net/rlemon/9FyNZ/2/ works well for me. although document.body will not be cross browser way to select the body. – rlemon Dec 24 '11 at 20:35
  • Are you tried innerWidth/innerHeight like this: http://stackoverflow.com/questions/8625208/working-with-canvas-in-different-screen-sizes/8628215#8628215 – Muaz Khan Dec 26 '11 at 03:43
  • use the `resize` event on `window` instead of doing it on every frame – Ricardo Tomasi Dec 26 '11 at 04:13
  • @MuazKhan innerWidth only work with if canvas is in whole window, in my case I want it to fit to body or a div. – Giovanni Funchal Dec 26 '11 at 10:56

4 Answers4

24

The easiest thing to do is to always keep the canvas in its own div.

The only thing that will ever be in this div is the canvas.

Then you can use CSS to resize the div however you want. You want it as large as the body? Give the div width: 100%.

Then you can always rightfully do:

canvas.width = theDiv.clientWidth;
canvas.height = theDiv.clientHeight;

If you do this you won't have to worry about the weird issues that you're currently facing when the body is the direct parent of the div.

Simon Sarris
  • 62,212
  • 13
  • 141
  • 171
  • 1
    Can you explain why it doesn't work with body (ie. why need DIV)? – Giovanni Funchal Dec 24 '11 at 19:18
  • If you want it to be as large as the body having a div makes it easier because you can specify a width and height with CSS (like 100% width and so on). 100% width doesn't necessarily make it as large as the body's `clientWidth`. Instead it makes it as large as the "containing block" as its called in the CSS spec, which is different (smaller) than the clientWidth and Height of the body. Start with this: http://jsfiddle.net/9FyNZ/ – Simon Sarris Dec 24 '11 at 19:36
  • Thanks! This solved a very annoying issue I was having. – Brad Jun 29 '14 at 23:58
  • 8
    That doesn't work (at least in Chrome). If the containing div has width/height 100% it still continually grows. See here http://jsfiddle.net/aakv7L7f/ – Sam Sep 29 '14 at 10:02
6

You can workaround the problem by breaking the circular dependency between the parent node and the child node. The size allocation of the DOM elements should only propagate top-down (from the parent to the child). You can ensure that the child element (canvas) does not affect the parent's size by setting

canvasNode.style.position = 'absolute';

This puts it into its own document flow that is independent of the parent.

Imran
  • 71
  • 1
  • 1
3

I've found that the cleanest approach is to simply "remind" the canvas element how big it's supposed to be upon resize:

window.onresize = function () {
    canvas.style.width = '100%';
    canvas.height = canvas.width * .75;
}

The height setting in this case is there to simply maintain a 4:3 ratio. You can, of course, make it 100% as well if you desire.

Josh Langley
  • 351
  • 2
  • 6
  • 2
    This will cause pixelation as it gets larger. Resizing the style height stretches the canvas but does nothing for it's pixel count. The renderer will need to be updated. – E10 Jun 08 '22 at 17:25
0

I found the same problem happening, and the only way I could find to work around it was to set the canvas height to parentHeight - 1. This was using CEF. In this fiddle I had to set it to parentHeight - 5.

canvasNode.height = div.clientHeight - 5;
Sam
  • 3,320
  • 1
  • 17
  • 22