Let's consider this code:
.canvas {
width:150px;
height:150px;
}
canvas {
box-sizing:border-box;
border:5px solid;
}
<canvas height="150" width="150"></canvas>
<canvas class="canvas"></canvas>
We have two canvas
defined with the same width/height, same border and box-sizing:border-box
. We can clearly see that the canvas where we used CSS properties is respecting the box-sizing
(borders are reduced from the width/height) but the first one defined with attribute is ignoring box-sizing
(borders are added to width/height).
I first thought it has to do with the use of attribute but it seems not as it works as intended when using img
or iframe
.
.canvas {
width:150px;
height:150px;
}
iframe,img {
box-sizing:border-box;
border:5px solid;
}
<iframe height="150" width="150"></iframe>
<iframe class="canvas"></iframe>
<img height="150" width="150" src="https://picsum.photos/200/300?image=1069">
<img class="canvas" src="https://picsum.photos/200/300?image=1069">
Why such behavior with canvas
element?
After some search, I found that using width/height properties with canvas should be avoided as it will scale the canvas and will not resize it like we may think.
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d");
ctx.fillRect(0, 0, 150, 150);
canvas {
width: 150px;
height: 150px;
border:1px solid red;
}
<canvas ></canvas>
Intuitively, the above code should produce a 150x150
square but we ended with a rectangle! This is because the canvas was initially 300x150
(default dimension) and our square was drawn inside. Then we scaled the whole think like we do with an image and we obtain the unwanted result.
However, using attribute will create the needed result:
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d");
ctx.fillRect(0, 0, 150, 150);
canvas {
border:1px solid red;
}
<canvas height="150" width="150"></canvas>
This somehow explain why the browser is ignoring box-sizing
in order to avoid the shrink effect but it still remain counter-intuitive as it may lead to other unwanted issues outside the canvas
. If this was the reason, then the broswer should also do the same with img
because they face the same shrink effect.
So again, why such behavior? Why the browser decide to ignore the box-sizing
instead of shrinking the canvas?
Most important question: where such behavior is defined?
I am not able to find which part of the specification is dealing with this.