At some point in a project, one gets annoyed by the footer hovering right under the header, because there is no content yet to fill up the space. There also may be some really short pages (like the 404), which might not be long enough to fill the whole browser.
Keeping the footer at the browser's bottom just got a little bit easier with CSS-Grid. It's possible to go with some CSS-trickery, Flexbox or JS, but the Grid-solution is the most elegant and simple in my opinion.
Please note that this is only supported in modern browsers, as of this writing. The good thing is, that this method won't break anything for older browsers.
The HTML-Structure will be as follows:
<html>
<body>
<article>
<header>
</header>
<main>
</main>
<footer>
</footer>
</article>
</body>
</html>
This is probably a bit simplified in comparison to some real-world-projects. It's important to keep the main content-area (main) and the footer (footer) in the same parent-element.
html, body {
width: 100%;
height: 100%;
}
article {
min-height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 100%;
}
The important bit is the "grid-template-rows"-property. Here we tell the browser, that we want the first child-element of "article" to be just as high as it naturally is ("auto"). The second should be one fr high, which means it will get as high as possible, since there's no other fr-item in there. The third child will be of natural height. again.
Don't forget to set the html- and body-elements to be of 100% height, or else your grid-container won't fill up the entire browser.
Here's the working example on CodePen.
In case you didn't know: CSS-Grid is now supported on every modern browser. It's a convenient way to define page-layouts and so much more. Go check out Wes Bos' free course on the topic.
EDIT:
You can achieve the same thing with Flexbox. If you need the feature today (Jan 2018), this would be a wider supported way. Check out Dominik Weber's article "Keeping the footer at the bottom with CSS Flexbox"
UPDATE:
Firefox 52 supports Grid, but it's buggy, especially for this case. The elements are not keeping their natural heights. So if you need to support FF52, use the Flexbox-Solution.
Top comments (32)
THE POST I'VE BEEN WAITING FOR!! At a site I frequent, at that. And Wes Bos's course is incredible! He makes some really great courses.
Thanks, this is really helpful. I'm sure every beginner dev has had this exact frustrating experience with battling the CSS to make the footer stay put. Really handy.
"Wow look at all CSS can do!"
couple minutes later while the high is still kicking
"Err... is this right? Should it be hard to put the footer at the bottom? Lets search Google."
metric boatload of stackoverflow/w3/css-tricks of tutorials
"Oh."
I actually spent 3 hours trying to put the footer down (ha) once...
Nice guide!
Yea it can get really messy. Since flexbox it's kind-of solved, before that you either had to give the main a min-height, or fix the footer-height in px...
If you’re going to use grid you would probably put that inside of an @supports query.
This means you can also remove the html,body statement and switch min-height:100% for min-height:100vh which takes care of all that in one statement. Cleans up even better 🙂
Grid fails pretty gracefully, so "supports" is not necessarily needed. but the 100vh thing is nice, you can omit the height in body and html that way. thanks!
In this case it does yeah. But two-dimensional grids can really destroy a page when it isn’t supported. That was the case I was thinking about. I’ve seen it on “forward thinking” sites where there was no progressive enhancement whatsoever
My understanding was that css-grid is recommended when you need to align in two dimensions, whereas flexbox is pretty fine to deal with one dimension.
Browser support is also slightly better for flexbox, not sure about performances.
You can add more columns, of course, e.g. for a sidebar. That's the advantage over flexbox. Grid is great for whole-page-layouts, Flexbox' strength lies more in the smaller scope, like Navs or Lists.
Still would see it as a bit of an overkill for this specific use case and, really, nothing prevents you from using flexbox also in the larger scope of the page.
Of course not. I was not stating that.
Hi,
Thanks for that solution!
Here is a fork of that pen using min-height and positioning, that I usually use : codepen.io/lehollandaisvolant/pen/...
It has the same global behaviour.
Good stuff! I found that I only had to use:
.wrapper {
min-height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
}
to get this to work for me. The styles for html and body weren't necessary for some reason.
ETA:
I found that if I put in <!DOCTYPE html> at the top, I then had to do:
html, body {
height: 100%;
}
to get this to work. But even then the scrollbars showed up because the footer was then a bit below the page. So, setting the height in the html, body bracket to 99% seemed to do the trick.
If using a single page application like ReactJS, remember to add width: 100% and height: 100% to the #root too.
If you're using Gatsby, you'll have to set #gatsby-focus-wrapper and #___gatsby to 100% height and 100% width as well.
Thanks for this post!
hey,
what does that mean exactly. I get the TypeError: when trying to access the project page on the porfolio.
I have not added gatsby-focus-wrapper anywhere in my code
If you’re getting a TypeError then I’m assuming you’re putting this in a .js file. It needs to go inside your .css, unless you’re using a library like styled-components to write css inside a .js file.
This is what you need inside your css:
html,
body,
#gatsby-focus-wrapper,
#___gatsby {
}
#gatsby-focus-wrapper and #___gatsby are hidden divs that gatsby injects into the DOM in between the html and body tags.
Think of it like a chain. The chain links include the html, gatsby-focus-wrapper, ___gatsby, and body tags. If you don’t add the height and width properties to all of them (inside your css file), the chain would look incomplete and your footer won’t stay at the bottom.
I hope this wasn’t too confusing!
PS - this site’s auto-markdown syntax is turning everything next to the div id sign “#” into a huge header. Out of my control lol
Thank you for the reply,
I've added the IDs in my main .scss file on the root.
However Im still getting a weird TypeError when trying to navigate to the portfolio item, that is a component in my GatsbyJS site.
dev-to-uploads.s3.amazonaws.com/i/...
It not a weird TypeError. It’s saying “you want me to select the h1 inside of the gatsby-focus-wrapper div but there isn’t one.”
Here’s an example of how the structure should look. See how there’s no h1 anywhere to be seen. My theory without seeing your code is that you’re trying to access an h1 that doesn’t exist.
dev-to-uploads.s3.amazonaws.com/i/...
Thank you,will try this out when time will allow.
Great article, doing it with CSS Grid is a really elegant solution.
While reading it, I somehow got the feeling that doing the same with flexbox is complicated. Which it is not.
So I've wrote a kind of answer article, Keeping the footer at the bottom with CSS Flexbox, to explain how it is done with flexbox.
Please don't take this as disrespectful, I just want to show people who cannot use CSS Grid how it is possible to achieve the same with flexbox.
No that's great, I'll link to your article.
Flexbox works great. If I'd need to support more browsers, that's the way to go! (Not looking forward to debugging IE, still...)
I think I skipped that method in prod, because my last two projects (since Flex became widely available) had such ginormous footers that they were bigger than any browser-height anyways ¯_(ツ)_/¯