Search code examples
htmlcssflexboxsticky-footer

How to do a sticky footer and still be able to do scrollable flexbox content?


I'm trying to achieve the sticky footer (flexbox version). However, I'm unable to find a working solution if I also want the ability to have scrollable content inside a flex: 1 div (which requires parents to have height: 100%).

Here's a fiddle to demonstrate the problem: https://jsfiddle.net/gfaqLh42/6/

enter image description here

As you can see, the red area is scrollable (with a min-height: 300px). Notice the footer is offscreen even though the viewport is not less than the red area's min-height + blue area.

Is there a way to do a sticky footer and still use flexbox flex: 1 with scrollable content?

Update

Here's another picture to represent the other big problem I face in trying to make this work:

enter image description here


Solution

  • Is there a way to do a sticky footer and still use flexbox flex: 1 with scrollable content?

    Yes, and what you need is to use Flexbox all the way.

    So instead of using min-height/height on article-1/card, change their CSS to this:

    .article-1 {
      flex: 1;
      display: flex;
      min-height: 0;                     /*  added, i.a Firefox need this  */
    }
    
    .card {
      overflow: auto;
    }
    

    Note, I also remove some properties not needed, mainly as they were set to their defaults, and added some. And why the need of min-width, is well explained here:

    Updated fiddle

    Stack snippet

    html, body{
      height: 100%;
      margin: 0;
      font-weight: bold;
    }
    
    .header {
      position: absolute;
      height: 40px;
      background-color: grey;
      z-index: 1;
      width: 100%;
    }
    
    .content {
      display: flex;
      flex-direction: column;
      height: 100%;  
      padding-top: 40px;
      box-sizing: border-box;            /*  added  */
    }
    
    .wrap {
      flex: 1;
      display: flex;
      flex-direction: column;
      min-height: 0;                     /*  added, i.a Firefox need this  */
    }
    
    .container {
      flex: 1;
      padding: 10px;
      box-sizing: border-box;            /*  added  */
      display: flex;
      flex-direction: column;
      min-height: 0;                     /*  added, i.a Firefox need this  */
    }
    
    .article-1 {
      flex: 1;
      display: flex;
      min-height: 0;                     /*  added, i.a Firefox need this  */
    }
    
    .card {
      overflow: auto;
    }
    
    .card-text {
      height: 2000px;
      width: 2000px;
      background-color: red;
    }
    
    .article-2 {
      flex: none;
      height: 40px;
      background-color: blue;
    }
    
    .footer {
      position: relative;
      height: 40px;
      background-color: grey;
    }
    <div class="header">Header</div>
    <div class="content">
    
      <div class="wrap">
        <div class="container">
          <div class="article-1">
            <div class="card">
              <div class="card-text">
                scrollable flex: 1 div<br>
                1. scrollable<br>
                2. scrollable<br>
                3. scrollable<br>
                4. etc...
              </div>
            </div>
          </div>
          <div class="article-2">
            flex: none div
          </div>
        </div>
      </div>
    
      <div class="footer">Footer</div>
    </div>


    Updated based on a comment

    If there is a need for the article-1 to have a minimum height, and to avoid absolute positioning on it, a minimum height could be set on content as well, to push the footer further down on smaller screens.

    Updated fiddle 2

    Stack snippet

    html, body{
      height: 100%;
      margin: 0;
      font-weight: bold;
    }
    
    .header {
      position: absolute;
      height: 40px;
      background-color: grey;
      z-index: 1;
      width: 100%;
    }
    
    .content {
      display: flex;
      flex-direction: column;
      height: 100%;  
      min-height: 450px;                 /*  added  */
      padding-top: 40px;
      box-sizing: border-box;            /*  added  */
    }
    
    .wrap {
      flex: 1;
      display: flex;
      flex-direction: column;
      min-height: 0;                     /*  i.a Firefox need this  */
    }
    
    .container {
      flex: 1;
      padding: 10px;
      box-sizing: border-box;            /*  added  */
      display: flex;
      flex-direction: column;
      min-height: 0;                     /*  i.a Firefox need this  */
    }
    
    .article-1 {
      flex: 1;
      display: flex;
      min-height: 300px;                 /*  changed  */
    }
    
    .card {
      overflow: auto;
    }
    
    .card-text {
      height: 2000px;
      width: 2000px;
      background-color: red;
    }
    
    .article-2 {
      flex: none;
      height: 40px;
      background-color: blue;
    }
    
    .footer {
      position: relative;
      height: 40px;
      background-color: grey;
    }
    <div class="header">Header</div>
    <div class="content">
    
      <div class="wrap">
        <div class="container">
          <div class="article-1">
            <div class="card">
              <div class="card-text">
                scrollable flex: 1 div<br>
                1. scrollable<br>
                2. scrollable<br>
                3. scrollable<br>
                4. etc...
              </div>
            </div>
          </div>
          <div class="article-2">
            flex: none div
          </div>
        </div>
      </div>
    
      <div class="footer">Footer</div>
    </div>