How to make footer stay at bottom of the page with flex-box

On iOS Safari when I create a div is a flex item and also make it a flex container, its height does not stretch to match its contents. However if it is not made a flex container then its height does stretch to match its contents.

To elaborate - I am using css flexbox to place a footer at the bottom of the page. The page body has two divs - "maincontents" and "footer". Even if the "maincontents" div has little or no content, the footer will still stay at the bottom of the window. And if the "maincontents" div has a lot of content, it can push the footer down as required. This idea was easily implemented in flexbox by making the page body a flex container, and setting "maincontents" to "flex:1" and "footer" to "flex:0", so that way "maincontents" takes up all available space while "footer" gets pushed to the bottom of the window. It works well on all modern browsers including iOS safari.

The problem arises if I also make "maincontents" a flexbox itself (using display:flex). On iOS Safari the footer now always stays at the bottom of the window, even if maincontents has a lot of content that should push the footer down further; instead "maincontents" ends up continuing underneath "footer" rather than pushing it down.

I have made a barebones mockup of this on jsfiddle. https://jsfiddle.net/8xs1rocu/

Here is what you would see if you open that fiddle on a window desktop (chrome/ff/ie11) enter image description here

And here is what you would see if you open it on an ipad or iphone (safari). enter image description here

Notice that on iOS safari the footer does not get pushed down by the content, and the content instead ends up going under it. This does NOT happen on Chrome/FF/IE11 on a desktop; on those browsers the footer is pushed down by the contents of "maincontents".

If you remove the "display:flex" line, then it works perfectly on ios safari too, just as it does on other browsers. However I need that "display:flex" line because I will be putting other content inside "maincontents" that needs to be laid out a certain way using css flexbox.

Pasting the jsfiddle snippet code directly here:

html, body {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.maincontents {
  flex: 1;
  display: flex; /* if you remove this line it works on Safari */
}

.footer {
  flex: 0;
  background-color: green;
}
<html>
  <head></head>
  <body>
    <div class="maincontents">
      Main contents1 <br />
      Main contents2 <br />
      Main contents3 <br />
      Main contents4 <br />
      Main contents5 <br /> 
      Main contents6 <br />
      Main contents7 <br />
      Main contents8 <br />
      Main contents9 <br />
      Main contents10 <br />
      Main contents11 <br />
      Main contents12 <br />
    </div>
   
    <div class="footer">
      Footer1 <br />
      Footer2 <br />
      Footer3 <br />
      Footer4 <br />
      Footer5 <br />
      Footer6 <br />
      Footer7 <br />
    </div> 
  </body>
</html>

Just add margin-top: auto; to the footer.

That will cause it to stick to the bottom of its container.

html, body {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.maincontents {
    /* nothing to put here */
}

.footer {
  margin-top: auto;
  background-color: green;
}
<html>
  <head></head>
  <body>
    <div class="maincontents">
      Main contents1 <br />
      Main contents2 <br />
      Main contents3 <br />
      Main contents4 <br />
      Main contents5 <br /> 
      Main contents6 <br />
      Main contents7 <br />
      Main contents8 <br />
      Main contents9 <br />
      Main contents10 <br />
      Main contents11 <br />
      Main contents12 <br />
    </div>
   
    <div class="footer">
      Footer1 <br />
      Footer2 <br />
      Footer3 <br />
      Footer4 <br />
      Footer5 <br />
      Footer6 <br />
      Footer7 <br />
    </div> 
  </body>
</html>

Upon further investigation I have found solution to your problem. With the information I hope you can make the following changes:

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

.maincontents {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.footer {
  flex: 0;
  background-color: green;
}
<html>
<head></head>
<body>
  <div class="maincontents">
    Main contents1 <br />
    Main contents2 <br />
    Main contents3 <br />
    Main contents4 <br />
    Main contents5 <br /> 
    Main contents6 <br />
    Main contents7 <br />
    Main contents8 <br />
    Main contents9 <br />
    Main contents10 <br />
    Main contents11 <br />
    Main contents12 <br />
  </div>

  <div class="footer">
    Footer1 <br />
    Footer2 <br />
    Footer3 <br />
    Footer4 <br />
    Footer5 <br />
    Footer6 <br />
    Footer7 <br />
  </div>
  
</body>
</html>

I have tested on safari and Chrome and works as you expect. The following is a jsfiddle https://jsfiddle.net/1o3904xh/12/

I would highly recommend that anyone looking at this to make the footer stay at the bottom of the page and any content to remain above do it like the following way. This is correct semantics which provide increase SEO and accessibility. With this layout it should put you in a very good position for your web page.

You can read more about the HTML5 elements here

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

article {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

main {
  flex-grow: 1;
}

header, main, footer {
  flex-shrink: 0;
}

.footer {
  background-color: green;
}
<html>
  <body>
    <article>
      <header></header>
      <main>
        <div class="maincontents">
          Main contents1 <br />
          Main contents2 <br />
          Main contents3 <br />
          Main contents4 <br />
          Main contents5 <br />
          Main contents6 <br />
          Main contents7 <br />
          Main contents8 <br />
          Main contents9 <br />
          Main contents10 <br />
          Main contents11 <br />
          Main contents12 <br />
          Main contents13 <br />
          Main contents14 <br />
          Main contents15 <br />
          Main contents16 <br />
        </div>
      </main>
      <footer>
        <div class="footer">
          Footer1 <br />
          Footer2 <br />
          Footer3 <br />
        </div>
      </footer>
    </article>
  </body>
</html>

Hope this helps you.