Are Flexbox and vh height units not compatible in IE11?

蓝咒 提交于 2019-12-02 20:17:43

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>

I came across this same bug yesterday and couldn't solve it by myself either. Unfortunately, seems nothing can be done about it, at the moment, because it's IE bug, which have been reported to the Microsoft developers almost a year ago, here:

https://connect.microsoft.com/IE/feedback/details/802625/min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview

The trick I've found to getting sticky footers working in IE11 is to make sure flex-basis is 100% or even 100vh. Please see an example below or a live Codepen example that you can test in IE11.

html {
  display: flex;
  flex-direction: column;
}

body {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  flex-basis: 100%;
  min-height: 100vh;
}

header {
  padding: 32px;
  background-color: seagreen;
}

main {
  flex-grow: 1;
  padding: 32px;
  background-color: rgba(0, 0, 0, 0.05);
}

footer {
  padding: 32px;
  background-color: coral;
}
<header>
  Header
</header>
<main>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
  <p>I will not skateboard in the halls.</p>
</main>
<footer>
  Footer
</footer>

Usually this helps:

html, body {
   height: 100%;
}

.. and you don't have to use vh units.

Full sample:

* {
  margin: 0;
}
html,
body {
  height: 100%;
}
body {
  border: red 1px solid;
  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;
  -webkit-flex: 1;
  flex: 1;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
}
<header>
  <h1>Herons - How they plan to eat your eyes!</h1>
</header>
<main>
  Herons are foul and devious birds.
</main>
<footer>
  <small>© 2014 Institute for the prevention of Herons</small>
</footer>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!