Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are Flexbox and vh height units not compatible in IE11?

I'm trying to use a flexbox-based layout to get a sticky footer for my page. This works well in Chrome and Firefox, but in IE11 the footer sits just after my main content. In other words, the main content isn't stretched to fill all of the available space.

body {      border: red 1px solid;      min-height: 100vh;      display: -ms-flexbox;      display: -webkit-flex;      display: flex;      -ms-flex-direction: column;      -webkit-flex-direction: column;      flex-direction: column;  }  header, footer  {      background: #dd55dd;  }  main {      background: #87ccfc;      -ms-flex: 1 0 auto;      -webkit-flex: 1 0 auto;      flex: 1 0 auto;  }
<body>      <header role="banner"><h1> .. </h1></header>      <main role="main">          <p>.....</p>      </main>      <footer>...</footer>  </body>

How can I get the main element to stretch in a flex layout when the containers height units are measured in vh in IE? I was looking to see if this behaviour is the result of a bug in the way IE implements the flexbox specs, but I couldn't find any mention of this problem elsewhere.

JSFiddle Demo

like image 266
Ritchie Allen Avatar asked Aug 07 '14 08:08

Ritchie Allen


1 Answers

The issue isn't vh units but min-height

I found a semi-working CSS-only solution:

min-height: 100vh; height: 100px; 

The extra height will enable IE to fill the screen vertically even if the content is not tall enough. The drawback is that IE will no longer wrap the content if it's longer than the viewport.


Since this is not enough I made a solution in JS:

Detection

This function tests the bug: true means it's buggy.

function hasBug () {     // inner should fill outer     // if inner's height is 0, the browser has the bug      // set up     var outer = document.createElement('div');     var inner = document.createElement('div');     outer.setAttribute('style', 'display:-ms-flexbox; display:flex; min-height:100vh;');     outer.appendChild(inner);     (document.body || document.documentElement).appendChild(outer);      // test     var bug = !inner.offsetHeight;      // remove setup     outer.parentNode.removeChild(outer);      return bug; } 

Fix

The fix consists of manually setting the height of the element in px

function fixElementHeight (el) {     // reset any previously set height     el.style.height = 'auto';       // get el height (the one set via min-height in vh)     var height = el.offsetHeight;       // manually set it in pixels     el.style.height = height + 'px';  } 

The element's height will be set to exactly the height of its content. height is used as a secondary min-height in IE, using the behavior observed in the CSS-only solution.

Usage

Once those two functions are defined, set it up this way:

if(hasBug()) {     // fix the element now     fixElementHeight(el);      // update the height on resize     window.addEventListener('resize', function () {         fixElementHeight(el);     }); } 

Demo

function hasBug () {      // inner should fill outer      // if inner's height is 0, the browser has the bug        // set up      var outer = document.createElement('div');      var inner = document.createElement('div');      outer.setAttribute('style', 'display:-ms-flexbox; display:flex; min-height:100vh;');      outer.appendChild(inner);      (document.body || document.documentElement).appendChild(outer);        // test      var bug = !inner.offsetHeight;        // remove setup      outer.parentNode.removeChild(outer);        return bug;  }    function fixElementHeight (el) {      // reset any previously set height      el.style.height = 'auto';         // get el height (the one set via min-height in vh)      var height = el.offsetHeight;         // manually set it in pixels      el.style.height = height + 'px';   }    var output = document.getElementById('output');  output.innerHTML = hasBug()?'Browser is buggy':'Browser works correctly';      var el = document.getElementById('flex');    if(hasBug()) {    // fix the element now    fixElementHeight(el);      // update the height on resize    window.addEventListener('resize', function () {      fixElementHeight(el);    });  }
.half-screen {    display:-ms-flexbox;    display: flex;    min-height: 50vh;      padding: 10px;    background: #97cef0;  }      .content {    padding: 10px;    background: #b5daf0;  }
The inner box should fill the outer box vertically, even if the browser is buggy.  <div class="half-screen" id="flex">    <div class="content" id="output">      Text    </div>  </div>
like image 92
fregante Avatar answered Sep 21 '22 08:09

fregante