192

I am trying to create a canvas element that takes up 100% of the width and height of the viewport.

You can see in my example here that is occurring, however it is adding scroll bars in both Chrome and FireFox. How can I prevent the extra scroll bars and just provide exactly the width and height of the window to be the size of the canvas?

2

7 Answers 7

332
+50

In order to make the canvas full-screen width and height always, meaning even when the browser is resized, you need to run your draw loop within a function that resizes the canvas to the window.innerHeight and window.innerWidth.

Example: http://jsfiddle.net/jaredwilli/qFuDr/

HTML

<canvas id="canvas"></canvas>

JavaScript

(function() {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');

  // resize the canvas to fill browser window dynamically
  window.addEventListener('resize', resizeCanvas, false);
        
  function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
                
    /**
     * Your drawings need to be inside this function otherwise they will be reset when 
     * you resize the browser window and the canvas goes will be cleared.
     */
    drawStuff(); 
  }
  
  resizeCanvas();
        
  function drawStuff() {
    // do your drawing stuff here
  }
})();

CSS

* { margin:0; padding:0; } /* to remove the top and left whitespace */

html, body { width:100%; height:100%; } /* just to be sure these are full screen*/

canvas { display:block; } /* To remove the scrollbars */

That is how you properly make the canvas full width and height of the browser. You just have to put all the code for drawing to the canvas in the drawStuff() function.

15
  • 2
    Why is it necessary to remove the padding and set width, height to 100%?
    – Kos
    Commented Jan 22, 2013 at 17:07
  • 3
    I believe it is mainly for overriding the user stylesheet which the browser has defaults for. If you are using some kind of normalize or reset css file, this isn't necessary since that will be taken care of already.
    – jaredwilli
    Commented May 24, 2013 at 15:16
  • 2
    If you expect quite a lot of resizing; on a portrait/landscape device for instance, you'd want to debounce the resize otherwise you'll flood the browser.
    – dooburt
    Commented Apr 8, 2014 at 8:07
  • 30
    display: block: Not only does this remove scrollbars, but it removes 2px from the document body's height, that are normally added under text lines inside a block. So +1 for that
    – Neptilo
    Commented Dec 18, 2014 at 13:41
  • 6
    plus one for no jQuery Commented Oct 6, 2016 at 19:00
30

You can try viewport units (CSS3):

canvas { 
  height: 100vh; 
  width: 100vw; 
  display: block;
}
6
  • 6
    Add display: block; and it does the job.
    – superlukas
    Commented Aug 20, 2014 at 12:40
  • 21
    I tried this and found that in Chrome and Firefox, the canvas simply shows the image stretched to the full viewport. Even newly drawn elements are stretched, as well. Commented Aug 21, 2014 at 3:03
  • 9
    @Daniel is right - this answer is wrong. It won't set the internal dimension of the canvas context, but rather the dimensions of the DOM element. For the difference, see my answer to a related question. Commented Jul 3, 2015 at 2:32
  • 32
    This method does not work, it stretches the text. You unfortunately have to use JS.
    – i336_
    Commented May 10, 2016 at 1:56
  • There are cases where you want to stretch (i.e. progress bar). Thanks, great for my case! Commented Oct 14, 2020 at 6:59
19

I'll answer the more general question of how to have a canvas dynamically adapt in size upon window resize. The accepted answer appropriately handles the case where width and height are both supposed to be 100%, which is what was asked for, but which also will change the aspect ratio of the canvas. Many users will want the canvas to resize on window resize, but while keeping the aspect ratio untouched. It's not the exact question, but it "fits in", just putting the question into a slightly more general context.

The window will have some aspect ratio (width / height), and so will the canvas object. How you want these two aspect ratios to relate to each other is one thing you'll have to be clear about, there is no "one size fits all" answer to that question - I'll go through some common cases of what you might want.

Most important thing you have to be clear about: the html canvas object has a width attribute and a height attribute; and then, the css of the same object also has a width and a height attribute. Those two widths and heights are different, both are useful for different things.

Changing the width and height attributes is one method with which you can always change the size of your canvas, but then you'll have to repaint everything, which will take time and is not always necessary, because some amount of size change you can accomplish via the css attributes, in which case you do not redraw the canvas.

I see 4 cases of what you might want to happen on window resize (all starting with a full screen canvas)

1: you want the width to remain 100%, and you want the aspect ratio to stay as it was. In that case, you do not need to redraw the canvas; you don't even need a window resize handler. All you need is

$(ctx.canvas).css("width", "100%");

where ctx is your canvas context. fiddle: resizeByWidth

2: you want width and height to both stay 100%, and you want the resulting change in aspect ratio to have the effect of a stretched-out image. Now, you still don't need to redraw the canvas, but you need a window resize handler. In the handler, you do

$(ctx.canvas).css("height", window.innerHeight);

fiddle: messWithAspectratio

3: you want width and height to both stay 100%, but the answer to the change in aspect ratio is something different from stretching the image. Then you need to redraw, and do it the way that is outlined in the accepted answer.

fiddle: redraw

4: you want the width and height to be 100% on page load, but stay constant thereafter (no reaction to window resize.

fiddle: fixed

All fiddles have identical code, except for line 63 where the mode is set. You can also copy the fiddle code to run on your local machine, in which case you can select the mode via a querystring argument, as ?mode=redraw

2
  • 1
    fyi: $(ctx.canvas).css("width", "100%"); is equivalent to $(canvas).css("width", "100%"); (the context's canvas is just the canvas)
    – Brad Kent
    Commented Jan 24, 2017 at 15:59
  • @BradKent when you call a helper function which does the "canvas-things" you want done, you can either, as argument(s) 1) pass the canvas object, 2) pass the canvas context, 3) both. I don't like 3), and ctx.canvas is a lot shorter than canvas.getContext('2d') - that's why I do 2). Hence, there is no variable called canvas, but there is ctx.canvas. That's where ctx.canvas comes from. Commented Dec 6, 2019 at 5:55
12

http://jsfiddle.net/mqFdk/10/

<!DOCTYPE html>
<html>
<head>
    <title>aj</title>
</head>
<body>

    <canvas id="c"></canvas>

</body>
</html>

with CSS

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }
6
  • This works, but it leaves my canvas without a defined width and height. The canvas width and height must be defined on the element I believe.
    – aherrick
    Commented Nov 26, 2010 at 22:49
  • @aherrick: No, you do not have to have an explicit width/height set on the canvas element for it to work. This code should work fine.
    – Jon Adams
    Commented Sep 13, 2011 at 14:04
  • 21
    Actually yes, canvas elements do need an explicit width/height set. Without it they default to some browser pre-set (in chrome, I think it's 300x150px) size. All drawing to the canvas gets interpreted at this size and then scaled to 100% of the viewport size. Try drawing anything in your canvas to see what I mean -- it'll be distorted.
    – user578895
    Commented Dec 13, 2011 at 8:46
  • if you're trying to make the canvas 100% width and height then that doesnt even matter at all. you just resize it anyways
    – jaredwilli
    Commented Jan 21, 2012 at 12:58
  • 2
    The intrinsic dimensions of the canvas element equal the size of the coordinate space, with the numbers interpreted in CSS pixels. However, the element can be sized arbitrarily by a style sheet. During rendering, the image is scaled to fit this layout size.
    – jaredwilli
    Commented Jan 21, 2012 at 13:05
11

I was looking to find the answer to this question too, but the accepted answer was breaking for me. Apparently using window.innerWidth isn't portable. It does work in some browsers, but I noticed Firefox didn't like it.

Gregg Tavares posted a great resource here that addresses this issue directly: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html (See anti-pattern #'s 3 and 4).

Using canvas.clientWidth instead of window.innerWidth seems to work nicely.

Here's Gregg's suggested render loop:

function resize() {
  var width = gl.canvas.clientWidth;
  var height = gl.canvas.clientHeight;
  if (gl.canvas.width != width ||
      gl.canvas.height != height) {
     gl.canvas.width = width;
     gl.canvas.height = height;
     return true;
  }
  return false;
}

var needToRender = true;  // draw at least once
function checkRender() {
   if (resize() || needToRender) {
     needToRender = false;
     drawStuff();
   }
   requestAnimationFrame(checkRender);
}
checkRender();
2

(Expanding upon 動靜能量's answer)

Style the canvas to fill the body. When rendering to the canvas take its size into account.

http://jsfiddle.net/mqFdk/356/

<!DOCTYPE html>
<html>
<head>
    <title>aj</title>
</head>
<body>

    <canvas id="c"></canvas>

</body>
</html>

CSS:

body { 
       margin: 0; 
       padding: 0
     }
#c { 
     position: absolute; 
     width: 100%; 
     height: 100%; 
     overflow: hidden
   }

Javascript:

function redraw() {
    var cc = c.getContext("2d");
    c.width = c.clientWidth;
    c.height = c.clientHeight;
    cc.scale(c.width, c.height);

    // Draw a circle filling the canvas.
    cc.beginPath();
    cc.arc(0.5, 0.5, .5, 0, 2*Math.PI);
    cc.fill();
}

// update on any window size change.
window.addEventListener("resize", redraw);

// first draw
redraw();
2

For mobiles, it’s better to use it

canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;

because it will display incorrectly after changing the orientation.The “viewport” will be increased when changing the orientation to portrait.See full example

Not the answer you're looking for? Browse other questions tagged or ask your own question.