Canvas is stretched when using CSS but normal with "width" / "height" properties

CssHtmlCanvasHeightWidth

Css Problem Overview


I have 2 canvases, one uses HTML attributes width and height to size it, the other uses CSS:

<canvas id="compteur1" width="300" height="300" onmousedown="compteurClick(this.id);"></canvas>
<canvas id="compteur2" style="width: 300px; height: 300px;" onmousedown="compteurClick(this.id);"></canvas>

Compteur1 displays like it should, but not compteur2. The content is drawn using JavaScript on a 300x300 canvas.

Why is there a display difference?

alt text

Css Solutions


Solution 1 - Css

It seems that the width and height attributes determine the width or height of the canvas’s coordinate system, whereas the CSS properties just determine the size of the box in which it will be shown.

This is explained in the HTML specification:

> The canvas element has two attributes to control the size of the element’s bitmap: width and height. These attributes, when specified, must have values that are valid non-negative integers. The rules for parsing non-negative integers must be used to obtain their numeric values. If an attribute is missing, or if parsing its value returns an error, then the default value must be used instead. The width attribute defaults to 300, and the height attribute defaults to 150.

Solution 2 - Css

To set the width and height you need, you may use

canvasObject.setAttribute('width', '475');

Solution 3 - Css

For <canvas> elements, the CSS rules for width and height set the actual size of the canvas element that will be drawn to the page. On the other hand, the HTML attributes of width and height set the size of the coordinate system or 'grid' that the canvas API will use.

For example, consider this (jsfiddle):

var ctx = document.getElementById('canvas1').getContext('2d');
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 30, 30);

var ctx2 = document.getElementById('canvas2').getContext('2d');
ctx2.fillStyle = "red";
ctx2.fillRect(10, 10, 30, 30);

canvas {
  border: 1px solid black;
}

<canvas id="canvas1" style="width: 50px; height: 100px;" height="50" width="100"></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px;" height="50" width="100"></canvas>

Both have had the same thing drawn on them relative to the internal coordinates of the canvas element. But in the second canvas, the red rectangle will be twice as wide because the canvas as a whole is being stretched across a bigger area by the CSS rules.

Note: If the CSS rules for width and/or height aren't specified then the browser will use the HTML attributes to size the element such that 1 unit of these values equals 1px on the page. If these attributes aren't specified then they will default to a width of 300 and a height of 150.

Solution 4 - Css

The canvas will be stretched if you set the width and height in your CSS. If you want to dynamically manipulate the dimension of the canvas you have to use JavaScript like so:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');

Solution 5 - Css

The browser uses the css width and height, but the canvas element scales based on the canvas width and height. In javascript, read the css width and height and set the canvas width and height to that.

var myCanvas = $('#TheMainCanvas');
myCanvas[0].width = myCanvas.width();
myCanvas[0].height = myCanvas.height();

Solution 6 - Css

Shannimal correction

var el = $('#mycanvas');
el.attr('width', parseInt(el.css('width')))
el.attr('height', parseInt(el.css('height')))

Solution 7 - Css

CSS sets the width and height of the canvas element so it affects the coordinate space leaving everything drawn skewed

Here's my way on how to set the width and height with Vanilla JavaScript

canvas.width = numberForWidth

canvas.height = numberForHeight

Solution 8 - Css

canvas renders image by buffer, so when you specify the width and height html attributes the buffer size and length changes, but when you use css, the buffer's size is unchanged. making the image stretched.

Using html sizing.

size of canvas is changed -> buffer size is changed -> rendered

Using css sizing

size of canvas is changed -> rendered

since the buffer length is kept unchanged, when the context renders the image, the image is displayed in resized canvas (but rendered in unchanged buffer).

Solution 9 - Css

If you want a dynamic behaviour based on, e.g. CSS media queries, don't use canvas width and height attributes. Use CSS rules and then, before getting the canvas rendering context, assign to width and height attributes the CSS width and height styles:

var elem = document.getElementById("mycanvas");

elem.width = elem.style.width;
elem.height = elem.style.height;

var ctx1 = elem.getContext("2d");
...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSirberView Question on Stackoverflow
Solution 1 - CssSamBView Answer on Stackoverflow
Solution 2 - CssfermarView Answer on Stackoverflow
Solution 3 - CssBen JacksonView Answer on Stackoverflow
Solution 4 - CssBluerainView Answer on Stackoverflow
Solution 5 - CssRussell HarkinsView Answer on Stackoverflow
Solution 6 - CssXaviGuardiaView Answer on Stackoverflow
Solution 7 - CssAnthony GedeonView Answer on Stackoverflow
Solution 8 - CssCoder_NaveedView Answer on Stackoverflow
Solution 9 - CssManoloView Answer on Stackoverflow