user1938653 user1938653 - 17 days ago 8
CSS Question

Two floating divs around a dynamic div

I am trying to achieve something like this:

enter image description here

In the middle there is a div that usually takes half of the total screen space (it contains a canvas and I calculate it's size with jQuery).

But around that div I am trying to make 2 divs float; one to the right, one to the left, the problem is sometimes they present weird problems by floating downwards for no apparent reason.
I've been working for hours but can't find a solution.

Answer

Use a full-viewport flexbox and set the divA and divC below to flex:1 and the middle dynamic div to flex:2 to get the widths right:

body {
  height: 100vh;
}
.wrapper {
  display: flex;
  width: 100%;
  height: 100%;
}
.wrapper div {
  flex: 1;
}
.wrapper .divB {
  flex: 2;
}

Now dynamically calculate the width and height of the divB and set it to the canvas - also put in a re-size handler to respond with window re-size dynamically - see demo below:

var canvas = document.getElementById("canvas");

var width = document.getElementsByClassName('divB')[0].getBoundingClientRect().width;
var height = document.getElementsByClassName('divB')[0].getBoundingClientRect().height;

document.getElementById("canvas").style.width = width + 'px';
document.getElementById("canvas").style.height = height + 'px';
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, width, height);

// resize handler Ref: https://developer.mozilla.org/en-US/docs/Web/Events/resize
(function() {
  window.addEventListener("resize", resizeThrottler, false);
  var resizeTimeout;

  function resizeThrottler() {
    if (!resizeTimeout) {
      resizeTimeout = setTimeout(function() {
        resizeTimeout = null;
        actualResizeHandler();
      }, 66);
    }
  }

  function actualResizeHandler() {
    var width = document.getElementsByClassName('divB')[0].getBoundingClientRect().width;
    var height = document.getElementsByClassName('divB')[0].getBoundingClientRect().height;

    document.getElementById("canvas").style.width = width + 'px';
    document.getElementById("canvas").style.height = height + 'px';
    ctx = canvas.getContext("2d");
    ctx.fillStyle = "red";
    ctx.fillRect(0, 0, width, height);
  }
}());
* {
  box-sizing: border-box;
}
body {
  height: 100vh;
  margin: 0;
}
.wrapper {
  display: flex;
  width: 100%;
  height: 100%;
}
.wrapper div {
  flex: 1;
  border: 1px solid;
}
.wrapper .divB {
  flex: 2;
  border: none;
}
<div class="wrapper">
  <div class="divA"></div>
  <div class="divB">
    <canvas id="canvas"></canvas>
  </div>
  <div class="divC"></div>
</div>

EDIT:

Consider a variable WIDTH is the calculated width (from your JS).

var WIDTH = 500; // this comes from your calculations

Set the flex property of divB like this:

document.getElementsByClassName('divB')[0].style.flex = '0 0 ' + WIDTH + 'px';

Demo below - you can test by varying the value of WIDTH:

var canvas = document.getElementById("canvas");

var WIDTH = 500; // this comes from your calculations

document.getElementsByClassName('divB')[0].style.flex = '0 0 ' + WIDTH + 'px';

var width = document.getElementsByClassName('divB')[0].getBoundingClientRect().width;
var height = document.getElementsByClassName('divB')[0].getBoundingClientRect().height;

document.getElementById("canvas").style.width = width + 'px';
document.getElementById("canvas").style.height = height + 'px';
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, width, height);

// resize handler Ref: https://developer.mozilla.org/en-US/docs/Web/Events/resize
(function() {
  window.addEventListener("resize", resizeThrottler, false);
  var resizeTimeout;

  function resizeThrottler() {
    if (!resizeTimeout) {
      resizeTimeout = setTimeout(function() {
        resizeTimeout = null;
        actualResizeHandler();
      }, 66);
    }
  }

  function actualResizeHandler() {
    var width = document.getElementsByClassName('divB')[0].getBoundingClientRect().width;
    var height = document.getElementsByClassName('divB')[0].getBoundingClientRect().height;

    document.getElementById("canvas").style.width = width + 'px';
    document.getElementById("canvas").style.height = height + 'px';
    ctx = canvas.getContext("2d");
    ctx.fillStyle = "red";
    ctx.fillRect(0, 0, width, height);
  }
}());
* {
  box-sizing: border-box;
}
body {
  height: 100vh;
  margin: 0;
}
.wrapper {
  display: flex;
  width: 100%;
  height: 100%;
}
.wrapper div {
  flex: 1;
  border: 1px solid;
}
.wrapper .divB {
  border: none;
}
#canvas {
  vertical-align:top;
}
<div class="wrapper">
  <div class="divA"></div>
  <div class="divB">
    <canvas id="canvas"></canvas>
  </div>
  <div class="divC"></div>
</div>

Comments