The purpose of a sticky footer is that it “sticks” to the bottom of the browser window. But not always, if there is enough content on the page to push the footer lower, it still does that. But if the content on the page is short, a sticky footer will still hang to the bottom of the browser window.
Note that “sticky” here is exactly as described above. It’s not to be confused with position: fixed;
which can be used to “stick” an element in place even if the page scrolls. Or, even more confusingly, it’s not position: sticky;
either, which is liked fixed positioning inside of containers sort of.
There is negative bottom margins on wrappers
There was a wrapping element that held everything except the footer. It had a negative margin equal to the height of the footer. That was the basis of this one.
<body>
<div class="wrapper">
content
<div class="push"></div>
</div>
<footer class="footer"></footer>
</body>
html, body {
height: 100%;
margin: 0;
}
.wrapper {
min-height: 100%;
/* Equal to height of footer */
/* But also accounting for potential margin-bottom of last child */
margin-bottom: -50px;
}
.footer,
.push {
height: 50px;
}
See the Pen Sticky Footer with calc(); by Chris Coyier (@chriscoyier) on CodePen.
This one required an extra element inside the content area (the “.push
“), to ensure that the negative margin didn’t pull the footer up and cover any content. The push was also clever because it very likely didn’t have any bottom margin of it’s own. If it did, that would have to be factored into the negative margins, and having those two numbers not in sync doesn’t look quite as nice.
There is negative top margins on footers
This technique did not require a push element, but instead, required an extra wrapping element around the content in which to apply matching bottom padding to. Again to prevent negative margin from lifting the footer above any content.
<body>
<div class="content">
<div class="content-inside">
content
</div>
</div>
<footer class="footer"></footer>
</body>
html, body {
height: 100%;
margin: 0;
}
.content {
min-height: 100%;
}
.content-inside {
padding: 20px;
padding-bottom: 50px;
}
.footer {
height: 50px;
margin-top: -50px;
}
See the Pen Sticky Footer with Negative Margins 2 by Chris Coyier (@chriscoyier) on CodePen.
Kind of a wash between this technique and the previous one, as they both require extra otherwise unnecessary HTML elements.
There is calc() reduced height wrappers
One way to not need any extra elements is to adjust the wrappers height with calc(). Then there is not any overlapping going on, just two elements stacked on top of each other totaling 100% height.
<body>
<div class="content">
content
</div>
<footer class="footer"></footer>
</body>
.content {
min-height: calc(100vh - 70px);
}
.footer {
height: 50px;
}
See the Pen Sticky Footer with calc(); by Chris Coyier (@chriscoyier) on CodePen.
Notice the 70px in the calc() vs. the 50px fixed height of the footer. That’s making an assumption. An assumption that the last item in the content has a bottom margin of 20px. It’s that bottom margin plus the height of the footer that need to be added together to subtract from the viewport height. And yeah, we’re using viewport units here as another little trick to avoid having to set 100% body height before you can set 100% wrapper height.
There is flexbox
The big problem with the above three techniques is that they require fixed height footers. Fixed heights are generally a bummer in web design. Content can change. Things are flexible. Fixed heights are usually red flag territory. Using flexbox for a sticky footer not only doesn’t require any extra elements, but allows for a variable height footer.
<body>
<div class="content">
content
</div>
<footer class="footer"></footer>
</body>
html, body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
.content {
flex: 1 0 auto;
}
.footer {
flex-shrink: 0;
}
See the Pen Sticky Footer with Flexbox by Chris Coyier (@chriscoyier) on CodePen.
You could even add a header above that or more stuff below. The trick with flexbox is either:
flex: 1
on the child you want to grow to fill the space (the content, in our case).- or,
margin-top: auto
to push the child away as far as it will go from the neighbor (or whichever direction margin is needed).
Remember we have a complete guide for all this flexbox stuff.
There is grid
Grid layout is even newer (and less widely supported) than flexbox. We have a complete guide for it too. You can also fairly easily use it for a sticky footer.
<body>
<div class="content">
content
</div>
<footer class="footer"></footer>
</body>
html {
height: 100%;
}
body {
min-height: 100%;
display: grid;
grid-template-rows: 1fr auto;
}
.footer {
grid-row-start: 2;
grid-row-end: 3;
}
This demo should work in Chrome Canary or Firefox Developer Edition, and can probably be backported to the older version of grid layout for Edge:
See the Pen Sticky Footer with Grid by Chris Coyier (@chriscoyier) on CodePen.
This always worked for me. The position relative on body is required to make it work.
The issue here is that it requires a fixed height to work. If content wraps when the browser resizes or if the content is dynamically added (possibly different content depending on the page), the fixed values won’t work.
For the Flexbox example, you can also use vh units which is ever-so-slightly less code:
http://codepen.io/acordova/pen/WxepQb
This, naturally, depends on your level of browser support. But it’s another option! (Note that if for whatever reason you have a content wrapper you can’t get rid of—something I just ran into while working in an Ember app—the
body
code should be on that wrapper.)I think the vw & vh units will not work on early Android os – not sure about newer ones, or how big a problem this is.
vh
andvw
don’t take scrollbars into account, nor do they account for the sliding address bar on mobile safari. I recommend avoiding them.Long before Flexbox, there was also a way to make sticky footer with
display:table
anddisplay: table-footer-group
: http://codepen.io/SelenIT/pen/QELpww. It has some drawbacks (e.g. needs extra wrappers just to add paddings), but it is supported back to IE8. Should it be also mentioned here?Wow… I’ve never thought of this one. Seems pretty bullet-proof. Sucks that you have to have the wrappers, but I like it!
This is what I used up until I switched to Flexbox. For browsers that don’t support Flexbox, I am not fussed about the stickiness of the footer.
I think we can do it without extra element (without “push” nor “content-inside”):
http://codepen.io/thierry/pen/zBOZvz
Sticky footer via display table-cell is missing: https://gist.github.com/goldsky/7322156
Yes! display: table-cell; has proven to be a very effective technique for most situations in my work. I’m sure in time I’ll lean on modern feature as we get further away from legacy. Flexbox is really powerful and can be used in many ways– It’s astounding. In any case, this post is a great collection of methods!
i prefer the flexbox approach, but just wanted to throw one more option into the mix…
sticky footer with
display: table-row
http://codepen.io/puglyfe/pen/QELpGy
I’ve been using a jQuery function to add a ‘fixed’ class to the footer if the content-height is less than the page-height. Just drop it into the JS functions and no extra work.
As much as I like a css-only solution, it depends on either extra markup or the page content being (window-height – footer-height) and sometimes the content-height is much shorter.
That solution is a nightmare, when content changes dynamically.
Don’t forget position sticky! It would be a pretty terrible thing to use in the wild for this purpose, but it does (kinda) work – something to add to the list.
(Demo will only work in Firefox or Safari)
http://codepen.io/basement31/pen/bebqRd
I like the flex box approach. Just an FYI. On a recent project I tried to set the height of the container to calc (100vh – 50px) and while it works for android and all desktop browsers, it doesn’t work on iOS devices. The vh inside the calc specifically. Very annoying. So thanks for showing the flex: 1; so helpful.
Be careful using the flex shorthand, different browsers (working to different specs at time of shipment) have different default values https://github.com/philipwalton/flexbugs#6-the-default-flex-value-has-changed – It may be safer to avoid shorthand for now (or build a mixin that does it for you)
This is also a great resource for some crossbrowser flexbox issues, most of which have fairly trivial workarounds
https://github.com/philipwalton/flexbugs
Not safari unfortunately (flex method)
Great overview – but the flex method shown here doesn’t work as expected across browsers. That just bit me when I opened my recent project in IE11. There’s an improved, only slightly more complex version from Phillip Walton which worked out great for me so far, I recommend updating the example here as well (code at the very bottom): http://philipwalton.com/articles/normalizing-cross-browser-flexbox-bugs/
Extrapolated from the Philip article that Kriesse linked to here:
I read through these comments just to see if someone else had posted about this. Thank you! We solved this issue in our project after trying to simply use
flex: 1;
and found issues in IE; the solution here was what we went with and it works perfectly.The grid version works for me in Firefox Developer Edition but not in Chrome Canary unless I turn on the experimental web platform features flag.
I’ve used this solution: http://blog.karenmenezes.com/2014/jan/14/ryan-faits-sticky-footer-responsive/
It takes into account that the footer’s height may change, based on the width of the page. Useful for responsive layouts and when you can’t use flexbox.
I also used Ms. Menezes’ solution, although I did modify her code to not require jQuery. I switched last year to a responsive layout, but I wanted to provide a reasonable experience to older IE browsers, so I couldn’t use flex.
I set the negative bottom margin on the wrapper and the height of the pusher in CSS to the normal height of the footer to avoid a big change in the height most of the time, and I use the window.onload to set the heights the first time to wait for images to load.
If you just need a “visual” bottom-footer than give the BODY the background color of the FOOTER and the content the background color of the page. http://codepen.io/herrfischer/pen/VjwVrP
In most cases this is the best way … for me.
Example with flexbox doesn’t work in IE11 (windows 7).
This reminds me when I once wanted a sticky footer that didn’t overlapped content: http://stackoverflow.com/questions/30470296/how-to-avoid-an-unknown-height-sticky-footer-to-overlap-content-with-css-only
For modern browsers the
flex
solution is the way to go, for older browser support use thetable
solution.incase u dont know the exact height of the footer, u can use a simple js like