Fabric.js changes my canvas size to 300x150 after initialization

JavascriptCanvasFabricjs

Javascript Problem Overview


HTML:

  <div class="canvas-wrapper">
    <canvas id="myCanvas"></canvas>
  </div>

CSS

.canvas-wrapper {
    width: 900px;
    min-height: 600px;
 }

 #myCanvas{
     border:1px solid red;
     position: absolute;
     top:22px;
     left:0px;
     height: 100%;
     width: 99%;
 }

JS

var myCanvas = new fabric.Canvas('myCanvas');

My canvas get resized to 300x150 after it's been initialized, why?

Javascript Solutions


Solution 1 - Javascript

in the latest version, you will have to do something like:

var canvas = new fabric.Canvas('myCanvas');
canvas.setHeight(500);
canvas.setWidth(800);

.... Your code ....

canvas.renderAll();

Works fine for me..

For dynamically changing size, this works too

Solution 2 - Javascript

When initializing canvas, Fabric reads width/height attributes on canvas element or takes width/height passed in options.

var myCanvas = new fabric.Canvas('myCanvas', { width: 900, height: 600 });

or:

<canvas width="900" height="600"></canvas>
...
var myCanvas = new fabric.Canvas('myCanvas');

Solution 3 - Javascript

A real answer to this question—not involving a new static size but actually permitting CSS to be effective—is one of the following options:

  1. In CSS, you can override individual properties and following them with !important; the downside to this is that any further definitions must also use !important or they will be ignored:

[width], [height], [style]
{
  width:      100vw!important;
  min-height: 100vh!important;
}

2. Using JQuery you can set the inline property values to an empty string. You can presumably achieve this without JQuery, but I will leave that as an exercise to you.

Javascript (JQuery):

$('[style]').attr(  'style',  function(index, style){  return ''; });
$('[height]').attr( 'height', function(index, height){ return ''; });
$('[width]').attr(  'width',  function(index, height){ return ''; });

CSS:

*, *:before, *:after
{
  box-sizing: border-box;
}

body
{
  width:      100vw; 
  min-height: 100vh;
  padding:    0;
  margin:     0;
}

.canvas-container,
canvas
{
  width:      inherit; 
  min-height: inherit;
}

canvas.lower-canvas
{
  position: absolute;
  top:      0;
}

After that, CSS will be applied as expected.

It is apparently also necessary to tell Fabric about the change:

function sizeCanvas()
{
  var width  = Math.max(document.documentElement.clientWidth,  window.innerWidth  || 0);
  var height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  canvas.setHeight( height )
  canvas.setWidth( width )
}

window.addEventListener('resize', draw, false);

function initDraw()
{
  // setup
}

function draw()
{  
  canvas.renderAll();  
}

sizeCanvas();
initDraw();

This will configure Fabric to the viewport size and keep it sized accordingly if it resizes.

It's worth noting that this problem arises for two reasons:

  1. Someone thought it was a good idea to use inline styles and should be severely castigated, as there is no situation where this is ever an appropriate practice.

  2. Fabric changes the DOM arrangement and nests the original canvas in a new div with a second nested canvas, which may result in surprises.

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
Questionuser469652View Question on Stackoverflow
Solution 1 - JavascriptSmitView Answer on Stackoverflow
Solution 2 - JavascriptkangaxView Answer on Stackoverflow
Solution 3 - JavascriptAsherView Answer on Stackoverflow