I found this CodePen solution for a sticky footer in a CSS Grid layout, but it has two problems for me:
min-height: 100%
and height: 100%
I need something that works with this HTML structure:
<body>
<nav>Some navigation buttons</nav>
<main>The content</main>
<footer>Copyrights and stuff</footer>
</body>
I don't really want to pack the <nav>
and the <main>
into a <div>
, and I would love to do this in pure CSS.
// Not required!
// This is just to demo functionality.
$("#add").on("click", function() {
$("<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>").appendTo(".content");
});
html {
height: 100%;
}
body {
min-height: 100%;
display: grid;
grid-template-rows: 1fr auto;
}
.content {
padding: 20px;
}
.footer {
grid-row-start: 2;
grid-row-end: 3;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font: 16px Sans-Serif;
}
h1 {
margin: 0 0 20px 0;
}
p {
margin: 0 0 20px 0;
}
.footer {
background: #42A5F5;
color: white;
padding: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<h1>Sticky Footer with Grid</h1>
<p><button id="add">Add Content</button></p>
</div>
<footer class="footer">
Footer
</footer>
If you've ever tried to put a sticky item in a grid layout and watched the item scroll away with the rest of the content, you might have come to the conclusion that position: sticky doesn't work with CSS Grid.
You need to use align-self: start on the thing you want to be sticky . Delete the background: grey from main and see the side effect of your solution: no more equal-height columns, a quite important benefit of CSS Grid. It's an alternate solution, but you're right.
Here is a CSS Grid solution, but it's far better using a class for the target.
Using grid-areas this will be very straight forward:
html, body {
margin: 0;
height: 100%;
}
body {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr;
grid-template-areas: "nav" "main" "footer";
grid-template-rows: 100px 1fr 80px;
}
nav {
background-color: #7E57C2;
grid-area: nav;
}
main {
background-color: #F8BBD0;
grid-area: main;
}
footer {
background-color: #7E57C2;
grid-area: footer;
}
<body>
<nav>Some navigation buttons</nav>
<main>The content</main>
<footer>Copyrights and stuff</footer>
</body>
The trick is to use:
min-height: 100vh; grid-template-rows: auto auto 1fr;
with...
align-self: end;
for the footer.
If we add left/right margins, place the <nav>
in a header, add a margin for the footer content and assume another grid for the main content:
body {
display: grid;
grid-gap: 1em 0;
grid: auto auto 1fr / 10vw 1fr 10vw;
margin: 0;
min-height: 100vh;
}
header {
background-color: #7E57C2;
grid-column: 2;
}
main {
background-color: #F8BBD0;
display: grid;
grid-column: 2;
}
footer {
background-color: #7E57C2;
align-self: end;
grid-column: 2;
margin-bottom: 1em;
}
<body>
<header>Some navigation buttons</header>
<main>The content</main>
<footer>Copyrights and stuff</footer>
</body>
This has elegant simplicity that previous solutions lack.
With evergreen browsers there is no need to complicate matters.
Previous answers are not as maintainable. Pitfalls include:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With