JSFiddle - React, Tailwind, and code Playground

by Per Andersson

HTML

<div id="container">
    <div id="top">
        <ul>
            <li>green box with variable height</li>
        </ul>
    </div>
    <div id="bottom" data-calcattr="top,height,calc(100% - toppx)">
        <ul>
            <li>blue box with <code>height: 100%</code> overflows browser window and launches vertical scrollbar</li>
            <li>we could remove scroll with <code>overflow: hidden</code> on <code>#container</code>, but that truncates bottom of this box</li>
            <li>how could we set the height of this box to always fit perfectly inside the container?</li>
            <li>in other words, the height should be <code>height: calc(100% - &lt;&lt;variable height of #top&gt;&gt;</li>
        </ul>

        <br />
        <div id="container-inner">
            <div class="box left">w: 50px</div>
            <div class="box middle">width of this box is variable</div>
            <div class="box right" data-calcattr="left,width,calc(100% - leftpx)"> occupy remaining width</div>
        </div>
    </div>
</div>

CSS

/* height demo */

* { margin: 0; }

html, body {  height: 100%; }

#container { height: 100%; }
    
#top {
    background-color: lightgreen;
    padding: 10px 0;
    box-sizing: border-box;
}

#bottom {
    background-color: lightblue; 
    padding: 10px 0;
    box-sizing: border-box;
    height: 100%;
}

/* width demo */
#container-inner {
    width: 70%;
    border: 2px solid black;
    border-right: 2px dashed black;
    font-size: 0;
    white-space: nowrap;
    box-sizing: border-box;
    min-width: 350px;
}
    
.left {
    width: 75px;
    background-color: orangered;
}

.middle {
    background-color: lightgreen;
}

.right {
    width: 100%;
    background: rgba(0, 255, 255, .5);
    text-align: left !important;
    /*white-space: normal;*/
    overflow: hidden;
}

.box {
    box-sizing: border-box;
    padding: 15px 5px;
    text-align: center;
    display: inline-block;
    font-size: 16px;
    vertical-align: top;
}

JavaScript

function calcattr() {
    var els = document.querySelectorAll('[data-calcattr]');
    for (i = 0; i < els.length; i++) {
        var what = els[i].getAttribute('data-calcattr');
        if (what) {
            what = what.split(',');
            var rect = els[i].getBoundingClientRect();
            var parentrect = els[i].parentNode.getBoundingClientRect();
            var brd = window.getComputedStyle(els[i].parentNode,null).getPropertyValue('border-' + what[0] + '-width');            
            what[2] = what[2].replace(what[0],parseInt(rect[what[0]]-parentrect[what[0]]) - parseInt(brd));
            els[i].setAttribute("style", what[1] + ":" + what[2]);
        }
    }
}

window.onload = calcattr;

(function() {
  window.addEventListener("resize", resizeThrottler, false);
  var resizeTimeout;
  function resizeThrottler() {
    if ( !resizeTimeout ) {
      resizeTimeout = setTimeout(function() {
        resizeTimeout = null;
        actualResizeHandler();
       }, 66);
    }
  }
  function actualResizeHandler() {
      calcattr();
  }
}());