2

The following Grid layout works fine in the latest versions of Chrome, Firefox, Opera, IE 10/11 and Edge. The only issue at hand, is that for the three Microsoft browsers mentioned the footer doesn't start to scroll when content grows beyond the screen size, but stays fixed in the middle of the page. In the other words, longer content overwrites the footer.

I've been doing a fair amount of research over the passed days. Unfortunately to no avail. Many of the proposed solutions work by moving the footer outside of the wrapper, however, I am looking for a technique that fits into the given markup of the page.

It's most likely some height issue I suppose, but since I ran out of ideas to try, I've decided to take things to this list. Maybe one of you all can give me a spark.

Any pointers on how to approach this one are appreciated.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  width: 100%;
  height: 100%;
}

body {
  min-height: 100%;
  height: 100%;
}

/* main grid layout start */
.wrapper {
  height: 100vh;
  display: grid;
  display: -ms-grid;
  grid-template-columns: 10% 80% 10%;
  grid-template-rows: 45px 50px 1fr 50px;
  grid-template-areas: "header header header" "navigation navigation navigation" "column-left column-center column-right" "footer footer footer";
  min-height: 100vh;
  -ms-grid-columns: 10% 80% 10%;
  -ms-grid-rows: 45px 50px 1fr 50px;
}

.item-header {
  background-color: pink;
  grid-area: header;
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
}

.item-nav {
  background-color: silver;
  grid-area: navigation;
  -ms-grid-row: 2;
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
}

.item-leftcol {
  background-color: skyblue;
  grid-area: column-left;
  -ms-grid-row: 3;
  -ms-grid-column: 1;
}

.item-centercol {
  grid-area: column-center;
  -ms-grid-row: 3;
  -ms-grid-column: 2;
}

.item-rightcol {
  background-color: tomato;
  grid-area: column-right;
  -ms-grid-row: 3;
  -ms-grid-column: 3;
}

.item-footer {
  background-color: green;
  text-align: center;
  padding: 10px;
  grid-area: footer;
  -ms-grid-row: 4;
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
  display: flex;
  display: -ms-flexbox;
  /* only IE10 */
}

/* flex layout for footer start */
.fc1 {
  background-color: red;
  text-align: left;
  flex-grow: 1;
  flex-basis: 0;
  -ms-flex-positive: 1; // flex-grow
  -ms-flex-preferred-size: 0; // flex-basis
}

.fc2 {
  background-color: red;
  text-align: center;
  flex-grow: 1;
  flex-basis: 0;
  -ms-flex-positive: 1; // flex-grow
  -ms-flex-preferred-size: 0; // flex-basis
}

.fc3 {
  background-color: red;
  text-align: right;
  flex-grow: 1;
  flex-basis: 0;
  -ms-flex-positive: 1; // flex-grow
  -ms-flex-preferred-size: 0; // flex-basis
}
/* flex layout for footer end */
<div class="wrapper">
  <div class="item-header">header</div>
  <div class="item-nav">nav</div>
  <div class="item-leftcol">left</div>
  <div class="item-centercol">center</div>
  <div class="item-rightcol">right</div>
  <div class="item-footer">
    <div class="fc1">footer</div>
    <!-- just added this -->
    <div class="fc2">footer</div>
    <!-- just added this -->
    <div class="fc3">footer</div>
    <!-- just added this -->
  </div>
</div>
Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
nightowl
  • 43
  • 5

2 Answers2

4

Using min-height with Flexbox, IE has a min-height bug, and it appears so does CSS Grid.

As the wrapper need a min-height to both fill remaining space and push the footer downwards when content grows, and to make IE play along, make the wrappers parent, in this case the body, a flex column container.

Note, also remove the height: 100% on html/body and the height: 100vh on the wrapper.

Stack snippet

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {}

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


/* main grid layout start */

.wrapper {
  display: grid;
  display: -ms-grid;
  grid-template-columns: 10% 80% 10%;
  grid-template-rows: 45px 50px 1fr 50px;
  grid-template-areas: "header header header" "navigation navigation navigation" "column-left column-center column-right" "footer footer footer";
  min-height: 100vh;
  -ms-grid-columns: 10% 80% 10%;
  -ms-grid-rows: 45px 50px 1fr 50px;
}

.item-header {
  background-color: pink;
  grid-area: header;
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
}

.item-nav {
  background-color: silver;
  grid-area: navigation;
  -ms-grid-row: 2;
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
}

.item-leftcol {
  background-color: skyblue;
  grid-area: column-left;
  -ms-grid-row: 3;
  -ms-grid-column: 1;
}

.item-centercol {
  grid-area: column-center;
  -ms-grid-row: 3;
  -ms-grid-column: 2;
}

.item-rightcol {
  background-color: tomato;
  grid-area: column-right;
  -ms-grid-row: 3;
  -ms-grid-column: 3;
}

.item-footer {
  background-color: green;
  text-align: center;
  padding: 10px;
  grid-area: footer;
  -ms-grid-row: 4;
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
  display: flex;
  display: -ms-flexbox;
  /* only IE10 */
}


/* flex layout for footer start */

.fc1 {
  background-color: red;
  text-align: left;
  flex-grow: 1;
  flex-basis: 0;
  -ms-flex-positive: 1; // flex-grow
  -ms-flex-preferred-size: 0; // flex-basis
}

.fc2 {
  background-color: red;
  text-align: center;
  flex-grow: 1;
  flex-basis: 0;
  -ms-flex-positive: 1; // flex-grow
  -ms-flex-preferred-size: 0; // flex-basis
}

.fc3 {
  background-color: red;
  text-align: right;
  flex-grow: 1;
  flex-basis: 0;
  -ms-flex-positive: 1; // flex-grow
  -ms-flex-preferred-size: 0; // flex-basis
}


/* flex layout for footer end */
<div class="wrapper">
  <div class="item-header">header</div>
  <div class="item-nav">nav</div>
  <div class="item-leftcol">left</div>
  <div class="item-centercol">center</div>
  <div class="item-rightcol">right</div>
  <div class="item-footer">
    <div class="fc1">footer</div>
    <!-- just added this -->
    <div class="fc2">footer</div>
    <!-- just added this -->
    <div class="fc3">footer</div>
    <!-- just added this -->
  </div>
</div>

It appears to work with the same trick using display: grid

Stack snippet

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {}

body {
  display: -ms-grid;
  -ms-grid-columns: 100%;
}


/* main grid layout start */

.wrapper {
 display: grid;
 display: -ms-grid;
 grid-template-columns: 10% 80% 10%;
 grid-template-rows: 45px 50px 1fr 50px;
 grid-template-areas:
  "header header header"
 "navigation navigation navigation"
 "column-left column-center column-right"
 "footer footer footer";

 min-height: 100vh;
 -ms-grid-columns: 10% 80% 10%;
 -ms-grid-rows: 45px 50px 1fr 50px;
}

.item-header {
 background-color: pink;
 grid-area: header;
 -ms-grid-row: 1;
 -ms-grid-column: 1;
 -ms-grid-column-span: 3;
}

.item-nav {
 background-color: silver;
 grid-area: navigation;
 -ms-grid-row: 2;
 -ms-grid-column: 1;
 -ms-grid-column-span: 3;
}

.item-leftcol {
 background-color: skyblue;
 grid-area: column-left;
 -ms-grid-row: 3;
 -ms-grid-column: 1;
}

.item-centercol {
 grid-area: column-center;
 -ms-grid-row: 3;
 -ms-grid-column: 2;
}

.item-rightcol {
 background-color: tomato;
 grid-area: column-right;
 -ms-grid-row: 3;
 -ms-grid-column: 3;
}

.item-footer {
 background-color: green;
  text-align: center;
 padding: 10px;
 grid-area: footer;
 -ms-grid-row: 4;
 -ms-grid-column: 1;
 -ms-grid-column-span: 3;
display: flex;
 display: -ms-flexbox; /* only IE10 */

}

/* flex layout for footer start */

.fc1 {
 background-color: red;
 text-align: left;
 flex-grow: 1;
 flex-basis: 0;
 -ms-flex-positive: 1;  // flex-grow
 -ms-flex-preferred-size: 0; // flex-basis
}

.fc2 {
 background-color: red;
 text-align: center;
 flex-grow: 1;
 flex-basis: 0;
 -ms-flex-positive: 1;  // flex-grow
 -ms-flex-preferred-size: 0; // flex-basis
}

.fc3 {
 background-color: red;
 text-align: right;
 flex-grow: 1;
 flex-basis: 0;
 -ms-flex-positive: 1;  // flex-grow
 -ms-flex-preferred-size: 0; // flex-basis
}


    /* flex layout for footer end */
    
    
<div class="wrapper">
  <div class="item-header">header</div>
  <div class="item-nav">nav</div>
  <div class="item-leftcol">left</div>
  <div class="item-centercol">center</div>
  <div class="item-rightcol">right</div>
  <div class="item-footer">
    <div class="fc1">footer</div>
    <!-- just added this -->
    <div class="fc2">footer</div>
    <!-- just added this -->
    <div class="fc3">footer</div>
    <!-- just added this -->
  </div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • Thanks for your answer. The flexbox approach doesn't solve the issue either. In Firefox and Chrome, this ends up blocking my header div from being displayed, while in IE header, nav and footer divs show up heavily inflated when content is larger than the viewport. – nightowl Feb 15 '18 at 18:29
  • @nightowl I just added a solution using `display: grid`. Does that one work for you? – Asons Feb 15 '18 at 18:31
  • @nightowl Do note, I just tried both the Flexbox and Grid versions in Firefox/Chrome/Edge/IE11, and they both render the exact same result everywhere. Are you saying the above snippets doesn't work for you? ... In this fiddle I also added content to `item-centercol`, and it as well works just fine everywhere: https://jsfiddle.net/8r7fde36/ – Asons Feb 15 '18 at 18:35
  • Unfortunately no, this mangles up sizes and proportions of the entire viewport in IE big time and this time around inflates header, nav and footer divs in FF. – nightowl Feb 15 '18 at 18:40
  • @nightowl I have tested the above snippets + this fiddle https://jsfiddle.net/8r7fde36/ in Firefox/Chrome/Edge/IE11 and it works perfectly fine, so I can't really understand what you say. – Asons Feb 15 '18 at 18:42
  • I have seasoned the footer with a little bit of flexbox, which doesn't show in the original post. Maybe this is causing the trouble on my end here..? I'll see to it, that I'll edit my original question, to reflect those changes. – nightowl Feb 15 '18 at 18:45
  • @nightowl It has to be that then, as the posted code works just fine. – Asons Feb 15 '18 at 18:50
  • Just added the flexbox design inside the footer. – nightowl Feb 15 '18 at 18:56
  • @nightowl That one works just fine too, if you **add my changes** to it, which I did in this fiddle: https://jsfiddle.net/8r7fde36/4/ – Asons Feb 15 '18 at 18:59
  • @nightowl I also updated my answer with the changed code after your question edit. – Asons Feb 15 '18 at 19:07
  • I amended my code as per your suggestions but it didn't really solve my situation, even though other users may have successfully made use of the flexbox approach. It may work in jsfiddle, but in my VirtualBox guests it inflated divs or ripped pages apart. I gave your answer an upvote. Below you can find my solution to things involving some Javascript. – nightowl Feb 18 '18 at 16:13
  • @nightowl Posted a comment at your answer. – Asons Feb 18 '18 at 16:23
0

Finally solved it. The main "culprit" for my situation was height:100vh; in .wrapper. I noticed, that IE10/IE11 and Edge behave differently with regard to this property. The declaration is not a problem for FF, Chrome or Opera (currently can't speak for Safari here). Therefore, I had to take height:100vh; out of .wrapper and make inclusion decisions based on browser and page height situation.

The IE10/IE11 situation:

When coming to IE10/IE11 the problem is twofold:

If height:100vh; is declared in .wrapper, pages that are not as high as the view port display fine. The footer stays on bottom. When this property is removed however, the footer hangs somewhere in the middle for these type of pages.

On the other hand, for pages that have more overall content than the view port, the header stays fixed at the bottom of the screen at page load time, but stays there once the user starts scrolling. When height:100vh; is removed from .wrapper, for these pages, the footer gets pushed down as it should be.

Therefore, those pages that are smaller than view port need the height:100vh; declaration, whereas those with content larger than view port don't need it.

Solutions for IE10/IE11:

Solution 1: One can set height:100vh; for those pages whose content's height is less than viewport height on a per page basis with:

@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
    .wrapper {
        height: 100vh;
    }
}

This works, but is not necessarily the preferred way of doing it.

Solution 2: Use Javascript to determine the height and include height:100vh; in the page if needed.

This Javascript handles the sitution for IE10/IE11:

function setHeightIETenEleven()
{
    var isIE10 = false;
    var isIE11 = false;

    /* IE10 ? */
    /*@cc_on
        if (/^10/.test(@_jscript_version)) {
            isIE10 = true;
        }
    @*/

    /* not IE10 maybe it's IE11 */
    if(!isIE10) {
        var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
    }

    if(isIE10 || isIE11) {
        var actualHeight = document.body.scrollHeight;
        var clientHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
        if(actualHeight == clientHeight)
            insertCss(".wrapper {height: 100vh;}");
    }
}

function insertCss( code ) {
    var style = document.createElement('style');
    style.type = 'text/css';

    if (style.styleSheet) { // IE
        style.styleSheet.cssText = code;
    } else { // Other browsers
        style.innerHTML = code;
    }

    document.getElementsByTagName("head")[0].appendChild( style );
}

window.onload = setHeightIETenEleven;

To give proper credit here, the insertCss() function was taken from: How do you add CSS with Javascript?

Since it is dynamic, this is the preferred solution

The Edge situation:

Edge initially had the same problem as IE10 and IE11 but the situation displays itself differently. Once the height property got removed, everything worked fine right away, regardless of page height. Therefore no need to make decisions based on page height. To make Edge happy one can use this:

@supports (-ms-ime-align: auto) {
    .wrapper {
        height: unset;
    }
}

For all other browsers one can set:

@supports not (-ms-high-contrast: none) {
    .wrapper {
        height: 100vh;
    }
}

A little more elaborate than I thought it would turn out to be, but it works for me...

nightowl
  • 43
  • 5
  • For some reason you didn't read my answer properly. I already removed the `height: 100vh` and use only `min-height: 100vh`. When done like that you don't need all the clutter you suggest here in this self answer. – Asons Feb 18 '18 at 16:23
  • @LGSon I have read it, but simply removing height: 100vh doesn't make IE10 and IE11 happy. As outlined, some pages actually do need it and some pages don't. Only setting min-height: 100vh doesn't cut it. – nightowl Feb 18 '18 at 16:50
  • Which OS do you use when running IE10/11? – Asons Feb 18 '18 at 17:02
  • IE10 on Win7. IE11 on Win81. – nightowl Feb 18 '18 at 17:25
  • Does the snippet's in my answer work on those 2 browsers? – Asons Feb 18 '18 at 18:32