Search code examples
htmlcsscanvaslayout

Fit canvases to window, centred


I am drawing multiple HTML5 canvases (1 to 3) in a row. They must:

  • align next to each other
  • maintain their aspect ratio (stay at e.g: 16:9, and not scale out of proportion)
  • if the window ratio doesn't match exactly, then the background image should be visible.. see diagrams.
  • be cross-platform

This is my progress so far: https://codepen.io/p487morgan/pen/qeozxP

var CANVASES = 3;
for (var i = 0; i < CANVASES; ++i) {
    var canvas = document.createElement('canvas');
    canvas.id = "myCanvas"+i.toString();
    canvas.width = 2048;
    canvas.height = 1152;
    var width = 100 / CANVASES;
    canvas.style.width = width.toString() + "%";
}

I don't know css, and to me there are too many options of how to tackle it.

I am trying to follow some of the recommendations here: http://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html

..namely not using the 'resize' event to change the size of the canvas. Hence trying to use css as much as possible.

Currently I set the canvases' widths as a % of the div. This is ok when the window is too narrow, but when its not tall enough, the canvases are cut off, so it needs a different approach.

Also, I want the canvases to center as per the diagrams, which I've not tackled yet.

What css styles will help me accomplish the task?

diagrams of what is required


Solution

  • As mentioned in my comment, stick with JavaScript when it comes to resizing your canvas. If you use CSS to resize the canvas, the quality of your images will degrade. Note that the "Anti-Patterns" article you cite still uses JavaScript (gl.canvas.width = width) to resize the canvas—it just doesn't listen to the resize event to do so. (Note that he's not changing gl.canvas.style.width .)

    To position your canvases, use Flexbox. Add this CSS to your styles:

    /* Note: you should probably
       give your div a class or ID */
    div {
      display: flex;
      align-items: center;
      justify-content: center;
    }