How can a variable-height sticky footer be defined in pure CSS?
Asked Answered
S

3

49

The key to note here is the height of the footer is not going to be fixed, but will vary with its content.

When I say “sticky footer,” I use it in what I understand to be the common definition of “a footer that is never higher than the bottom of the viewport, but if there is enough content, it will be hidden until the user scrolls down far enough to see it.”

Note also I don’t need to support legacy browsers. If CSS display: table & related properties help here, they are fair game.

Stertorous answered 31/5, 2012 at 0:4 Comment(0)
P
103

All other solutions here are out of date and either use JavaScript, or table hacks.

With the advent of the CSS flex model, solving the variable-height sticky footer problem becomes very, very easy: while mostly known for laying out content in the horizontal direction, Flexbox actually works just as well for vertical layout problems. All you have to do is wrap the vertical sections in a flex container and choose which ones you want to expand. They'll automatically take up all the available space in their container.

Note how simple the markup and the CSS are. No table hacks or anything.

The flex model is supported by 96%+ of the browsers in use today.

html, body {
  height: 100%;
  margin: 0; padding: 0;  /* to avoid scrollbars */
}

#wrapper {
  display: flex;  /* use the flex model */
  min-height: 100%;
  flex-direction: column;  /* learn more: http://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ */
}

#header {
  background: yellow;
  height: 100px;  /* can be variable as well */
}

#body {
  flex: 1;
  border: 1px solid red;
}

#footer{
  background: lime;
}
<div id="wrapper">
  <div id="header">Title</div>
  <div id="body">Body</div>
  <div id="footer">
    Footer<br/>
    of<br/>
    variable<br/>
    height<br/>
  </div>
</div>
Policyholder answered 25/10, 2014 at 0:18 Comment(6)
The problem in IE10 & IE11 is related to min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview.Geognosy
I also see a problem with the min-height: 100% instead of height: 100% in the #wrapper, in Chrome on Linux. It scrolls the whole page with min-height and only the body with height.Seline
Best solution after hours of searchingAssembler
Great solution! I've first been wondering why you assigned flex=1 to the body – until I saw that it refers to the div (id#body) with the same name. It might be clearer if you renamed it to #main or #content. By the way, is the wrapper div necessary, or could the display:flex simply be assigned to the "real" body?Federalism
If you don't want to set 100% all the way down from html, use min-height: 100vhLindsylindy
For the header and footer to always be on-screen, use this answer, plus the wrapper height set to 100vh, header and footer positions set to sticky, and body flex-direction set to column.Propaedeutic
N
18

You can absolutely do this in pure CSS. Clicky the linky.

This concept uses display: table-cell organize your page sections rather than the normal display: block.

HTML

<body class="Frame">
    <header class="Row"><h1>Catchy header</h1></header>
    <section class="Row Expand"><h2>Awesome content</h2></section>
    <footer class="Row"><h3>Sticky footer</h3></footer>
</body>

CSS

.Frame {
    display: table;
    table-layout: fixed;
    height: 100%;
    width: 100%;
}
.Row {
    display: table-row;
    height: 1px;
}
.Row.Expand {
    height: auto;
}
Nietzsche answered 4/9, 2012 at 1:21 Comment(5)
While the example code is missing something, yes, it’s possible with this technique.Stertorous
You're right! I've made my edits to correct this, glad it worked for you!Nietzsche
There's no table-cell in the example. Did you mean table-row? Anyway, the modern way to do this is to use the CSS flexbox model.Policyholder
You should add table-layout: fixed; to class Frame. Without that I had some width issues in IE. The content was overflowing regardless of the maximum width.Leaflet
@Nietzsche This solved the problem. Thank you. My man ✌Alie
H
-1

You can stick the footer to the bottom of the viewport just with:

position: fixed;
bottom: 0;

However that will make it appear even if there's content.

To prevent this, you will need some JavaScript:

(window.onscroll = function() {
    var foot = document.getElementById('footer');
    foot.style.position = "static";
    if( foot.offsetTop < document.documentElement.scrollTop + document.body.scrollTop + document.documentElement.offsetHeight - foot.offsetHeight)
        foot.style.position = "fixed";
})();

(The (...)(); wrapper makes the onscroll function get called once when the page loads, since that's needed too)
(The above function is untested, but should work - if it doesn't, let me know and I'll make an actual test page)

Heldentenor answered 31/5, 2012 at 0:10 Comment(5)
(...)(); is just a self executing fn is it not?Huey
Yes - this basically makes the function be called once without needing a scroll, and then again every time an onscroll event is fired.Heldentenor
So this isn't correct? "(The (...)(); wrapper makes the onscroll function get called once when the page loads, since that's needed too)"Huey
I'm repeating myself, but badly XD Sorry for any confusion.Heldentenor
I follow you now. I did get a little confused but that's a pretty neat way of doing that.Huey

© 2022 - 2024 — McMap. All rights reserved.