sticky footer – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Wed, 17 Nov 2021 15:42:53 +0000 en-US hourly 1 https://wordpress.org/?v=6.2.2 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 sticky footer – CSS-Tricks https://css-tricks.com 32 32 45537868 A Clever Sticky Footer Technique https://css-tricks.com/a-clever-sticky-footer-technique/ https://css-tricks.com/a-clever-sticky-footer-technique/#comments Wed, 17 Nov 2021 00:49:00 +0000 https://css-tricks.com/?p=357053 Upon hearing “sticky footer” these days, I would think most people imagine a position: sticky situation where a footer element appears fixed on the screen while in the scrolling context of some parent element.

That’s not quite what I’m talking …


A Clever Sticky Footer Technique originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Upon hearing “sticky footer” these days, I would think most people imagine a position: sticky situation where a footer element appears fixed on the screen while in the scrolling context of some parent element.

That’s not quite what I’m talking about here. “Sticky footers” were a UI concept before position: sticky existed and they mean something slightly different. The idea is that they stick to the bottom of the screen, even when the content of the page isn’t enough to push them there. But if there is enough content, they are happily pushed down.

We covered five ways to do this in years past, which included techniques that are somewhat modern, including calc(), flexbox, and CSS Grid.

Enter a sixth challenger! Reader Sílvio Rosa wrote in with this:

(Probably easiest to check out on a medium-sized desktop screen, which is kinda where sticky footers matter the most anyway.)

It’s pretty much just this:

html, body { height: 100%;}

body > footer {
  position: sticky;
  top: 100vh;
}

What I like about it is that it doesn’t require any special extra wrapper for non-footer content.

It’s also a little brain-bending. When I see top: 100vh; I think well that won’t work because it will push the footer outside the viewable area. But that’s the clever bit. It will do that no matter how big the footer is (no magic numbers), and then the sticky positioning will “suck it back up” to stick along the bottom edge. But it will never overlap content, so it’s happy to be pushed down below content, which is a core tenet of the sticky footer pattern.


A Clever Sticky Footer Technique originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/a-clever-sticky-footer-technique/feed/ 25 357053
How to Use CSS Grid for Sticky Headers and Footers https://css-tricks.com/how-to-use-css-grid-for-sticky-headers-and-footers/ https://css-tricks.com/how-to-use-css-grid-for-sticky-headers-and-footers/#comments Wed, 02 Sep 2020 14:36:53 +0000 https://css-tricks.com/?p=319886 CSS Grid is a collection of properties designed to make layout easier than it’s ever been. Like anything, there’s a bit of a learning curve, but Grid is honestly fun to work with once you get the hang of it. …


How to Use CSS Grid for Sticky Headers and Footers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
CSS Grid is a collection of properties designed to make layout easier than it’s ever been. Like anything, there’s a bit of a learning curve, but Grid is honestly fun to work with once you get the hang of it. One area where it shines is dealing with headers and footers. With a little adjustment in our thinking, we can pull off headers and footers that behave like they are fixed, or have that “sticky” treatment (not position: sticky, but the kind of footer that hugs the bottom of the screen even if there isn’t enough content to push it there, and is pushed away with more content). 

Hopefully this sparks further interest in modern layouts, and if it does, I can’t recommend Rachel Andrew’s book The New CSS Layout strongly enough: it covers both of the major modern layout techniques, grid and flexbox.

What we’re making

Let’s implement a fairly classic HTML layout that consist of a header, main content and footer.

We’ll make a truly fixed footer, one that stays at the bottom of the viewport where the main content scrolls within itself, as needed, then later update the footer to be a more traditional sticky footer that starts at the bottom of the viewport, even if the main content is small, but gets pushed down as needed. Further, to broaden our exposure to grid, let’s design our main content holder so that it can either span the whole width of the viewport, or take up a nicely centered strip down the middle.

A fixed footer is slightly unusual. Footers are commonly designed to start at the bottom of the viewport, and get pushed down by main content as needed. But a persistent footer isn’t unheard of. Charles Schwab does it on their homepage. Either way, it’ll be fun to implement!

But before we move on, feel free to actually peek at the fixed footer implemented on the Charles Schwab site. Unsurprisingly, it uses fixed positioning, which means it has a hard-coded size. In fact, if we crack open DevTools, we see that right off the bat:

body #qq0 {
  border-top: 4px solid #133568;
  background-color: #eee;
  left: 0;
  right: 0;
  bottom: 0;
  height: 40px!important;
}

Not only that, but there’s the balance of making sure the main content doesn’t get hidden behind that fixed footer, which it does by setting hard-coded paddings (including 15px on the bottom of the <footer> element), margins (including 20px on <ul> in the footer), and even line breaks.

Let’s try to pull this off without any of these restrictions.  

Our baseline styles

Let’s sketch out a bare minimum UI to get us started, then enhance our grid to match our goals. There’s a CodeSandbox below, plus additional ones for the subsequent steps that get us to the end result.

First, let’s do some prep work. We’ll make sure we’re using the whole height of the viewport, so when we add our grid, it’ll be easy to put the footer at the bottom (and keep it there).  There’s only going to be one element inside the document’s <body> with an ID of #app, which will hold the <header, <main> and <footer> elements.

body {
  margin: 0; /* prevents scrollbars */
}


#app {
  height: 100vh;
}

Next, let’s set up our header, main, and footer sections, as well as the grid they’ll all sit in. To be clear, this will not work the way we want right out of the gate. It’s just to get us started, with a base to build from.

body {
  margin: 0;
}


#app {
  height: 100vh;
  
  /* grid container settings */
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas: 
    'header'
    'main'
    'footer';
}


#app > header {
  grid-area: header;
}


#app > main {
  grid-area: main;
  padding: 15px 5px 10px 5px;
}


#app > footer {
  grid-area: footer;
}

We’ve created a simple one-column layout, with a width of 1fr. If that 1fr is new to you, it essentially means “take the remaining space” which, in this case, is the entire width of the grid container, #app.

We’ve also defined three rows:

#app {
  /* etc. */
  grid-template-rows: auto 1fr auto;
  /* etc. */
}

The first and third rows, which will be our header and footer, respectively, are sized with auto, which means they’ll take up as much space as needed. In other words: no need for hard-coded sizes! This is a super important detail and a perfect example of how we benefit from using CSS Grid.

The middle row is where we’ll put our content. We’ve assigned it a size of 1fr which, again, just means it takes up all of the remaining space that’s left over from the other two rows. If you’re wondering why we aren’t making it auto as well, it’s because the entire grid spans the viewport’s whole height, so we need one section to grow and fill up any unused space. Note that we do not have, nor will we ever need at any point, any fixed heights, margins, paddings — or even line breaks! — to push things into place. Such is the good life when working with grid!

Shall we try some content?

You’ll notice in the Sandbox that I used React to build this demo, but since this isn’t a post about React, I won’t belabor those details; React has absolutely nothing to do with any of the CSS Grid work in this post. I’m only using it as an easy way to navigate between different chunks of markup. If you hate React, that’s fine: hopefully you can ignore it in this post.

We have Header, Main and Footer components that render the expected <header> , <main>  and <footer> elements, respectively. And, of course, this all sits inside our #app container. Yes, in theory, #app should be an <article> element, semantically speaking, but that’s always looked weird to me. I just wanted to covey these details so we’re all one the same page as we plow ahead.

For the actual content, I have Billing and Settings sections that you can navigate between in the header. They both render fake, static content, and are only meant to show our layout in action. The Settings section will be the content that we put in a centered strip on our page, Billing will be the one that spans our whole page.

Here’s the Sandbox with what we have so far.

The Billing section looks good, but the Settings section pushes our footer off screen. Not only that, but if we scroll, the entire page scrolls, causing us to lose our header. That may be desirable in some cases, but we want both the header and footer to stay in view, so let’s fix that.

When we initially set up our grid, we gave it a height of 100vh, which is the entire height of the viewport. We then assigned the rows for the header and footer an auto height, and the main a height of 1fr to take up the remaining space. Unfortunately, when content exceeds the space available, it expanded beyond the viewport bounds, pushing our footer down and out of view.

The fix here is trivial: adding overflow: auto will cause our <main> element to scroll, while keeping our <header> and <footer> elements in place.

#app > main {
  grid-area: main;
  overflow: auto;
  padding: 15px 5px 10px 5px;
}

Here’s the updated demo that puts this to use.

Adjustable width main section

We want our <main> element to either span the whole width of the viewport, or be centered in a 600px space. You might think we could simply make <main> a 600px fixed width, with an auto margins on either side. But since this is a post about grid, let’s use moar grid. (Plus, as we’ll see later, a fixed width won’t work anyway).

To achieve our centered 600px element, we’ll actually make the <main> element a grid container. That’s right, a grid within a grid! Nesting grids is a totally legit approach, and will even get easier in the future when subgrid is officially supported across browsers. In this scenario, we’ll make <main> a grid with three column tracks of 1fr 600px 1fr or, stated simply, 600px in the middle, with the remaining space equally divided on the sides.

#app > main {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr 600px 1fr;
}

Now let’s position our the content in the grid. Our different modules all render in a <section> child. Let’s say that by default, content will occupy the middle section, unless it has a .full class, in which case it will span the entire grid width. We won’t use named areas here, and instead specify precise grid coordinates of the form [row-start] / [col-start] / [row-end] / [col-end]:

#app > section {
  grid-area: 1 / 2 / 1 / 3;
}


#app > section.full {
  grid-area: 1 / 1 / 1 / 4
}

You might be surprised to see a col-end value of 4, given that there’s only three columns. This is because the column and row values are column and row grid lines. It takes four grid lines to draw three grid columns. 

Our <section> will always be in the first row, which is the only row. By default it’ll span column lines 2 through 3, which is the middle column, unless the section has a full class on it, in which case it’ll span column lines 1 through 4, which is all three columns.

Here’s an updated demo with this code. It’ll probably look good, depending on your CodeSandbox layout, but there’s still a problem. If you shrink the display to smaller than 600px, the content is abruptly truncated. We don’t really want a fixed 600px width in the middle. We want a width of up to 600px. It turns out grid has just the tool for us: the minmax() function. We specify a minimum width and a maximum width, and the grid will compute a value that falls in that range. That’s how we prevent the content from blowing out of the grid.

All we need to do is swap out that 600px value with minmax(0, 600px):

main {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr minmax(0, 600px) 1fr;
}

Here’s the demo for the finished code.

Earlier, we decided to prevent the footer from being pushed off the screen and did that by setting the <main> element’s overflow property to auto.

But, as we briefly called out, that might be a desirable effect. In fact, it’s more of a classic “sticky” footer that solves that annoying issue, and places the footer on the bottom edge of the viewport when the content is super short.

Hey, get back to the bottom!

How could we keep all of our existing work, but allow the footer to get pushed down, instead of fixing itself to the bottom in persistent view?

Right now our content is in a grid with this HTML structure:

<div id="app">
  <header />
  <main>
    <section />
  </main>
  <footer />
</div>

…where <main> is a grid container nested within the #app grid container, that contains one row and three columns that we use to position our module’s contents, which go in the <section> tag.

 Let’s change it to this:

<div id="app">
  <header />
  <main>
    <section />
    <footer />
  </main>
</div>

…and incorporate <footer> into the <main> element’s grid. We’ll start by updating our parent #app grid so that it now consists of two rows instead of three:

#app {
  /* same as before */


  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr;
  grid-template-areas: 
    'header'
    'main';
}

Just two rows, one for the header, and the other for everything else. Now let’s update the grid inside our <main> element:

#app > main {
  display: grid;
  grid-template-rows: 1fr auto;
  grid-template-columns: 1fr minmax(0, 600px) 1fr;
}

We’ve introduced a new auto-sized row. That means we now have a 1fr row for our content, that holds our <section>, and an auto row for the footer.

Now we position our <footer> inside this grid, instead of directly in #app:

#app > footer {
  grid-area: 2 / 1 / 3 / 4;
}

Since <main> is the element that has scrolling, and since this element now has our footer, we’ve achieved the sticky footer we want! This way, if <main> has content that exceeds the viewport, the whole thing will scroll, and that scrolling content will now include our footer, which sits at the very bottom of the screen as we’d expect.

Here’s an updated demo. Note that the footer will be at the bottom of the screen if possible; otherwise it’ll scroll as needed. 

I made a few other small changes, like minor adjustments to paddings here and there; we can’t have any left or right paddings on <main>, because the <footer> would no longer go edge-to-edge.

I also made a last-minute adjustment during final edits to the <section> element—the one we enabled adjustable width content on. Specifically, I set its display to flex, its width to 100%, and its immediate descendant to overflow: auto. I did this so the <section> element’s content can scroll horizontally, within itself, if it exceeds our grid column boundary, but without allowing any vertical scrolling.

Without this change, the work we did would amount to the fixed footer approach we covered earlier. Making section> a flex container forces its immediate child — the <div> that contains the content — to take up all of the available vertical space. And, of course, setting that child div to overflow: auto enables scrolling. If you’re wondering why I didn’t just set the section’s overflow-x to auto, and overflow-y to visible, well, it turns out that’s not possible.

Parting thoughts

We haven’t done anything revolutionary in this post, and certainly nothing that couldn’t be accomplished before CSS Grid. Our fixed width <main> container could have been a block element with a max-width value of 600px, and auto margins on the left and right. Our fixed footer could have been made with position: fixed (just make sure the main content doesn’t overlap with it). And, of course, there are various ways to get a more traditional “sticky footer.”

But CSS Grid provides a single, uniform layout mechanism to accomplish all of this, and it’s fun to work with — honestly fun. In fact, the idea of moving the footer from fixed to sticky wasn’t even something I planned at first. I threw it in at the last minute because I thought the post was a bit too light without it. It was trivial to accomplish, basically moving grid rows around, not unlike putting lego blocks together. And again, these UIs were trivial. Imagine how brightly grid will shine with more ambitious designs!


How to Use CSS Grid for Sticky Headers and Footers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/how-to-use-css-grid-for-sticky-headers-and-footers/feed/ 18 319886
Creating sliding effects using sticky positioning https://css-tricks.com/creating-sliding-effects-using-sticky-positioning/ https://css-tricks.com/creating-sliding-effects-using-sticky-positioning/#comments Mon, 10 Sep 2018 14:06:43 +0000 http://css-tricks.com/?p=275805 Sticky elements are predominantly used for keeping something shown on the screen throughout scrolling. As cool as that is, we can also hide elements in the same way!

Here’s a typical (um) sticky situation:

See the Pen position:sticky (CSS) by …


Creating sliding effects using sticky positioning originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Sticky elements are predominantly used for keeping something shown on the screen throughout scrolling. As cool as that is, we can also hide elements in the same way!

Here’s a typical (um) sticky situation:

See the Pen position:sticky (CSS) by Preethi Sam (@rpsthecoder) on CodePen.

Sticky elements (position: sticky;) are very similar to fixed elements ( position: fixed;) in that they both maintain their position on the screen, even as the user scrolls up or down the page. The difference? A sticky element remains confined to the parent container it is in. Compare sticky example above with this one that uses the same concept using a fixed element instead:

See the Pen position:sticky (CSS) by CSS-Tricks (@css-tricks) on CodePen.

Say we want to create an effect where elements either slide in or out of view on scroll — sort of like parallax. For example, a header that slides out and a footer that slides in:

Well, guess what? We can do that with sticky elements!

See the Pen Slide In and Out Effect using “position:sticky” by Preethi Sam (@rpsthecoder) on CodePen.

How do we do that? Glad you asked. Let’s break it down.

HTML setup

There are three sticky elements in our example:

  • The first one is the category header that slides under the body of the article once it reaches the top of the screen.
  • The second is the title of the article and it stays visible at the top of the screen, while the body of the content disappears behind it on scroll (which is the typical sticky element behavior).
  • The third element is a footer that slides out of the article and is revealed when the article is scrolled above a certain threshold.

Let’s see how it’s done. Here’s the HTML we’re working with… basically two articles:

<article>
  <div class="category">Category Header</div>
  <h1 class="title">Article 1 Title</h1>
  <p>Body content would go here.</p>
  <!-- More content -->
  <div class="footer">
    <p>Article 1 Footer</p>
  </div>
</article>

<article>
  <div class="category">Category Header</div>
  <h1 class="title">Article 2 Title</h1>
  <p>Body content would go here.</p>
  <!-- More content -->
  <div class="footer">
    <p>Article 2 Footer</p>
  </div>
</article>

The sticky CSS

The .category, .title, and .footer elements will get position:sticky; along with a placement property saying where on the screen they’ll start “sticking” when scrolled.

.category,
.title,
.footer {
  position: -webkit-sticky; /* Required for Safari */
  position: sticky;
  height: 50px;
}

.category {
  top: 0;
}

.title {
  top: 0;
}

.footer {
  bottom: 100px;
  z-index: -1;
}

I’m not doing much to the sticky elements, except styling them. They’re already doing what they need to do: stick to the screen. All that’s left is to create a cover and some space for the elements to come in and leave as the page scrolls.

There are probably a bunch of ways we can create a cover on the article that sticky elements can pass and hide under on a page — I went with a background-image.

article {
  background-image: linear-gradient(
    to bottom,
    transparent 50px,
    #F5A623 50px,
    #F5A623 calc(100% - 50px),
    transparent 0
  );
  margin: auto auto 50px auto;
}

The background linear gradient is applied to the article and runs from top to bottom, starting with 50px of transparency and a color change with a hard stop at 50px. The calc stuff? That’s how I’m telling the color to continue but leave 50px at the bottom. Then we go transparent again. That means we have two 50px transparent stripes, one at the top and one at the bottom with equal heights matching the heights of the category heading and the footer.

The category header and the article footer are the elements that slide in and out of the text, so their heights are the ones that determine how long the transparent stripes will be at the top and bottom of the gradient.

How this all comes together is that both the category header and article title stick to the screen when their tops align with the top of the viewport. The title stacks on top of the category header and, when it starts sticking at the top of the viewport, hides the category header altogether.

As for the footer, it’s already stuck 100px above the bottom of the screen (within the article’s boundary), but you won’t see it since it’s pushed behind the content using z-index:-1. It’ll be visible once we scroll past the beginning of the last transparent stripe of article’s background.

.footer {
  bottom: 100px;
  margin: 50px auto auto auto;
  z-index: -1;
}

Because the category header is just content with nothing to conceal with but the text itself, it’s a good idea to give the last sticky element (the footer) a top margin of 50px (to keep things equal) so that you won’t see it behind the category header while scrolling.

That’s it!

Now, of course, you’ll want to make this your own and change it up, like the dimensions, number of elements, and type of content. The key is to create those covers that allow your sticky elements to hide behind and be revealed as they pass through — again, probably different ways to go about that, but I went with transparent stripes in a gradient.

What, another example? Sure!

Here’s another example with horizontal scrolling (and a horizontal gradient), that might be ideal for applying this concept to mobile devices:

See the Pen Horizontal slide in and out effect using sticky elements by Preethi Sam (@rpsthecoder) on CodePen.

See how the food gets revealed as one article leaves the viewport and then is hidden when the next article passes over it?

Same sort of HTML setup:

<article>
  <div class="title">Article 1 Title</div>
  <p>Article content goes here.</p>
  <img class="image" src="/path/to/revealed/image.png">
</article>

<article>
  <div class="title">Article 2 Title</div>
  <p>Article content goes here.</p>
  <img class="image" src="/path/to/revealed/image.png">
</article>

I’m going to my linear gradient solution for creating the covers, this time going from left-to-right to account for a horizontal scroll:

article  {
  background-image: linear-gradient(
    to right,
    transparent 50px,
    #F5A623 50px,
    #F5A623 calc(100% - 50px),
    transparent 0
  );
}

.title,
.image  {
  position: sticky;
  position: -webkit-sticky;
  z-index: -1;
  width: 50px;
}

.title  {
  left: 20px;
  margin-right: 52px;
}

.image  {
  left: 150px;
}

Notice again that we’re going with the same two 50px transparent stripes as before — the only difference being that we’re applying it to the width instead of the height.

Both of the sticky elements (the title and image) will slide under and through the article. So, in order to avoid overlapping them during scroll, the title gets a right margin that’s equal to the image’s width, which is 50px (plus an additional 2px for a cleaner line in Chrome).

Here’s what’s going on: as we scroll horizontally, the title sticks 20px from the screen’s left edge and the image sticks 150px from the same. Because they both have z-index: -1;, they’ll disappear under the article (well, the background gradient) — they are hidden as they pass through the solid color of the gradient and are revealed by the transparent stripes.

OK, one more example

Before wrapping up, let me show you one more example that inspired this post. It’s a site footer that reveals itself on scroll. I first saw this design at Ryan Seddon’s website a long time ago.

This design is usually done by using a “fixed” footer that’s given some space at the end of the page to come out to, using margin. I thought if fixed elements can do that for the whole page, then maybe sticky elements can do something similar for individual elements — and hence what I came up with so far.

Consequently, we can accomplish this same effect using the sticky techniques we’ve covered so far.

First, our HTML:

<main>
  <h1>Site Title</h1>
  <p>Site content</p>
</main>
<footer>
  Site Footer
</footer>
html {
  background-color: #fff;
}

body {
  background-image: linear-gradient(
    to top,
    transparent 60px, 
    #fff 60px, 
    #fff 0
  );
}

footer {
  position: -webkit-sticky;
  position: sticky;
  bottom: 0;
  height: 50px;
  padding: 5px 0;
  z-index: -1;
}

See the Pen Page footer slide-out using “position:sticky” by Preethi Sam (@rpsthecoder) on CodePen.

A sticky footer and background gradient on the body does the trick.


Creating sliding effects using sticky positioning originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/creating-sliding-effects-using-sticky-positioning/feed/ 5 275805
Sticky Footer, Five Ways https://css-tricks.com/couple-takes-sticky-footer/ https://css-tricks.com/couple-takes-sticky-footer/#comments Wed, 25 May 2016 15:27:16 +0000 http://css-tricks.com/?p=242097 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 …


Sticky Footer, Five Ways originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
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.


Sticky Footer, Five Ways originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/couple-takes-sticky-footer/feed/ 28 242097