Size of HTML5 Canvas via CSS versus element attributes
The explanation is here: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#attr-canvas-width as seen in another post, thanks!
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.
HTML5 get scaled canvas size
The canvas
element has it own width
and height
attributes, so editing the width
and height
in css
will only scale it but the canvas
' attributes will remain the same. So to change the canvas
size you will have to resize it by JavaScript
with onresize
function.
Canvas width and height in HTML5
The canvas
DOM element has .height
and .width
properties that correspond to the height="…"
and width="…"
attributes. Set them to numeric values in JavaScript code to resize your canvas. For example:
var canvas = document.getElementsByTagName('canvas')[0];
canvas.width = 800;
canvas.height = 600;
Note that this clears the canvas, though you should follow with ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height);
to handle those browsers that don't fully clear the canvas. You'll need to redraw of any content you wanted displayed after the size change.
Note further that the height and width are the logical canvas dimensions used for drawing and are different from the style.height
and style.width
CSS attributes. If you don't set the CSS attributes, the intrinsic size of the canvas will be used as its display size; if you do set the CSS attributes, and they differ from the canvas dimensions, your content will be scaled in the browser. For example:
// Make a canvas that has a blurry pixelated zoom-in
// with each canvas pixel drawn showing as roughly 2x2 on screen
canvas.width = 400;
canvas.height = 300;
canvas.style.width = '800px';
canvas.style.height = '600px';
See this live example of a canvas that is zoomed in by 4x.
var c = document.getElementsByTagName('canvas')[0];var ctx = c.getContext('2d');ctx.lineWidth = 1;ctx.strokeStyle = '#f00';ctx.fillStyle = '#eff';
ctx.fillRect( 10.5, 10.5, 20, 20 );ctx.strokeRect( 10.5, 10.5, 20, 20 );ctx.fillRect( 40, 10.5, 20, 20 );ctx.strokeRect( 40, 10.5, 20, 20 );ctx.fillRect( 70, 10, 20, 20 );ctx.strokeRect( 70, 10, 20, 20 );
ctx.strokeStyle = '#fff';ctx.strokeRect( 10.5, 10.5, 20, 20 );ctx.strokeRect( 40, 10.5, 20, 20 );ctx.strokeRect( 70, 10, 20, 20 );
body { background:#eee; margin:1em; text-align:center }canvas { background:#fff; border:1px solid #ccc; width:400px; height:160px }
<canvas width="100" height="40"></canvas><p>Showing that re-drawing the same antialiased lines does not obliterate old antialiased lines.</p>
Is canvas scaling more performant via CSS or JS?
This is unclear. Should I make the canvas as small as possible, then scale with CSS, or set the larger canvas dimensions from the canvas.width and canvas.height attributes (and "not scale the canvas" at all?)
Yes and no, it means scaling an element (canvas or any other) is faster using transforms (ie. transformation matrix) than using CSS width and height on the element, as transforms uses the available GPU. Plus:
Everything goes through transform matrices anyways (unless optimized not to when a identity matrix is encountered). Layout properties such as width and height etc. triggers layout reflow. Transforms can usually skip to paint and composition.
Example: As you can see here, the second div has transforms applied but does nothing to layout (the ghost space for the div is still there):
div { width:100px;padding:100px 0 0 0;margin:0 5px; display:inline-block;background:#7f9;border:2px solid #000 }
div:nth-child(2) { transform:scale(1.5) translate(30px, 30px)}
<div></div><div></div><div></div><div></div>
HTML5: Canvas width and height
Yes, those units are always in pixels and applies to the bitmap the canvas element uses. However, if there is no size defined on the element using CSS (ie. style
attribute or using a style sheet) the element will automatically adopt to the size of its bitmap.
There is no other way of setting the size of the bitmap than by number of pixels. Using CSS will only change the size of the element itself, not the bitmap, stretching whatever is drawn to the bitmap to fit the element.
To use other units you will have to manually calculate these using JavaScript, for example:
// using % of viewport for canvas bitmap (pixel ratio not considered)
var canvas = document.getElementById("myCanvas"),
vwWidth = window.innerWidth,
vwHeight = window.innerHeight,
percent = 60;
canvas.width = Math.round(vwWidth * percent / 100); // integer pixels
canvas.height = Math.round(vwHeight * percent / 100);
// not to be confused with the style property which affects CSS, ie:
// canvas.style.width = "60%"; // CSS only, does not affect bitmap
If you want to support retina then you need to use the window.devicePixelRatio
and multiply it with the sizes. In this case CSS would be necessary as well (combine with code above):
var pxRatio = window.devicePixelRatio || 1,
width = Math.round(vwWidth * percent / 100),
height = Math.round(vwHeight * percent / 100);
canvas.width = width * pxRatio;
canvas.height = height * pxRatio;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
Difference between HTML width attribute and CSS width property (canvas)?
According to the relevant spec:
4.8.11 The canvas element — HTML5
The canvas element has two attributes to control the size of the coordinate space:
width
andheight
. 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.
Emphasis added.
In your case, since the first element, #trail
, doesn't have a width
or height
attribute, the attribute values default to width="300" height="150"
, which is why you're seeing a difference.
In essence, the width
/height
attributes set the intrinsic dimensions of the canvas's coordinate space, whereas the CSS properties set the actual size of the canvas
element:
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.
Therefore if you gave the canvas
element the attributes width="100" height="100"
, then set a CSS width of 100%
, the image would be scaled to fit the layout while maintaining the aspect ratio (example).
Canvas is stretched when using CSS but normal with width / height properties
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
andheight
. 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. Thewidth
attribute defaults to 300, and theheight
attribute defaults to 150.
Related Topics
How to Make an Element Fill the Remaining Viewport Height
Align ≪Div≫ Elements Side by Side
Bootstrap Center Vertical and Horizontal Alignment
How Does Flex-Wrap Work With Align-Self, Align-Items and Align-Content
Svg Data Image Not Working as a Background-Image in a Pseudo Element
Difference Between Max-Device-Width and Max-Width For Mobile Web
Center an Element in Bootstrap Navbar
Css3'S Attr() Doesn't Work in Major Browsers
Any Recommendations For a CSS Minifier
Fullcalendar: Change the Color for Specific Days
How to Fix Invalid Request (Unsupported Ssl Request)
Child Inside Parent With Min-Height: 100% Not Inheriting Height
Change Navbar Color in Twitter Bootstrap