Anton Harald
Anton Harald

Reputation: 5964

How can an element of a fixed size (canvas) be resized in a flex container?

An HTML canvas element can be automatically resized by the dynamics of a HTML page: Maybe because its style properties are set to a percentage value, or maybe because it is inside a flex container. Thereby the content of the canvas gets resized as well: Because of the interpolation the canvas content looks blurred (loss of resolution).

In order to keep the resolution to the maximum, one must render the canvas content based on the current pixel size of the element.

This fiddle shows how this can be done with the help of the function getComputedStyle: https://jsfiddle.net/fx98gmu2/1/

setInterval(function() {
  var computed = getComputedStyle(canvas);
  var w = parseInt(computed.getPropertyValue("width"), 10);
  var h = parseInt(computed.getPropertyValue("height"), 10);

  canvas.width = w;
  canvas.height = h;

  // re-rendering of canvas content...
}, 2000); // intentionally long to see the effect

With a setTimeout function I'm updating the width and height of the canvas to the computed values of these properties.

As the fiddle shows, this works only when increasing the size of the window. Whenever the window size gets decreased, the canvas (item of the flexbox) stays fixed.

Upvotes: 4

Views: 2306

Answers (2)

Oriol
Oriol

Reputation: 288700

Set its flex-basis to 0, allow it to shrink with flex-shrink, and don't force any minimum width:

#canvas {
  flex: 1 1 0;
  min-width: 0;
}

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d");
setInterval(function() {
  var computed = getComputedStyle(canvas),
      w = parseInt(computed.width, 10),
      h = parseInt(computed.height, 10);
  canvas.width = w;
  canvas.height = h;
  ctx.clearRect(0, 0, w, h);
  ctx.beginPath();
  ctx.arc(w/2, h/2, h/2, 0, Math.PI*2, true);
  ctx.stroke();
}, 2000); // intentionally long to see the effect
#container {
  border: 1px solid blue;
  width: 100%;
  display: flex;  
}
#canvas {
  border: 1px solid red;
  flex: 1 1 0;
  min-width: 0;
  height: 150px;
}
<div id="container">
  <canvas id="canvas"></canvas>
  <div>something else...</div>
</div>

Upvotes: 5

c-smile
c-smile

Reputation: 27480

You need to place the canvas into a container with overflow:hidden and set canvas dimensions to dimensions of that container:

window.setTimeout( function() {
  var div = $("div");
  div.find("canvas").attr( { width:div.width(), height:div.height()} );
})
canvas { background:gold; display:block; }

div { width:50%; height:50%; border:1px solid; overflow:hidden; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <canvas width="200" height="100" /> 
</div>

Upvotes: 1

Related Questions