How can I have a sticky footer with my CSS Grid layout?
Asked Answered
S

5

19

I found this CodePen solution for a sticky footer in a CSS Grid layout, but it has two problems for me:

  1. It is kinda ugly with min-height: 100% and height: 100%
  2. It only works with two elements in the body (a div and a footer)

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>
Shrum answered 11/9, 2017 at 15:5 Comment(0)
S
22

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>
Stinkhorn answered 13/11, 2017 at 8:1 Comment(1)
This is a good one and has helped me a ton. Thanks for putting it out!Rigadoon
J
6

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:

  • Forcing header/footer to fixed pixel dimensions.
  • Using grid areas instead of a simpler grid definition. There are bonus points for combining grid-template-rows and grid-template-columns into a one-liner.
  • Extensive 'width/height/min-height: 100%' definitions everywhere on html and body tags. This might have made sense when IE6 ruled the roost but is not needed with modern browsers.
  • Using flexbox layout. This is not the layout engine of the future. CSS grid will be what I want to maintain in five years time.
  • Using pixels and percentages. What is a pixel? Who knows when there are retina screens and high-res phone screens. I used to like pixels but there are other units that make more sense, 'vw/vh/vmin/vmax' plus 'em/rem'. The percentage measurement is on its way out too for CSS grid so best to get out of the habit.
Jasen answered 11/1, 2019 at 1:1 Comment(1)
There is a known problem with 100vh layouts on mobile: #37112718Swinson
B
4

Sticky footer is achieved with a single line of CSS, namely: min-height: 100vh.

Example below:

body {
    width: 100%;
    height: 100%;
    margin: 0;
    display: grid;
    grid-template-columns: [column-line-1] minmax(128px, 256px) [column-line-2] auto [column-line-3] minmax(128px, 256px) [column-line-4];
    grid-template-rows: [row-line-1] 48px [row-line-2] auto [row-line-3] auto [row-line-4] auto [row-line-5] auto [row-line-6];
    background:#fafafa;
    /*Below provides sticky footer*/
    min-height: 100vh;
}

body > aside {
    background:#9e9e9e;
}

body > aside > section {
    margin: 0px 12px 0px 12px;
}

body > header {
    display: flex;
    flex-flow: row wrap;
    justify-content: center;
    align-content: center;
    align-items: flex-start;
}

body > header > section {
    flex: 1 1 auto;
    align-self: center;
    min-width: 100%;
    min-height:48px;    
}

body > header > nav {
    flex: 0 1 auto;
    align-self: auto;
    min-width: 100%;
    min-height:48px;
    
    display: flex;
    flex-flow: row nowrap;
    align-content: center;
    align-items: center;
    
    margin-left:12px;
    margin-right:12px;
}

body > header > nav > section {
    flex: 1 1 auto;
    align-self: center;
    
    display: flex;
    flex-flow: row nowrap;    
    align-content: center;
    align-items: center;
    
    height:auto;
    width:50%;
}

body > header > nav > section:nth-of-type(1) {
    justify-content: flex-start;
}

body > header > nav > section:nth-of-type(2) {
    justify-content: flex-end;
}

body > header > nav > section > div {
    flex: 0 1 auto;
    align-self:center;
    
    display: flex;
    flex-flow: row nowrap;    
    align-content: center;
    align-items: center;  
    justify-content: center;
    
    margin: 0px 12px 0px 12px;
}

body > main {
    background:#e3f2fd;
    
}

body > main > section {
    margin: 0px 12px 0px 12px;
}

body > nav {
    
    background:#e0e0e0;
}
body > nav > section {
    display: grid;
    margin: 0px 12px 0px 12px;
}

body > footer {
    grid-column-start: column-line-1;
    grid-column-end: column-line-4;
    grid-row: row-line-5;
    background:#eeeeee;

}

body > footer > section {
    margin: 0px 12px 0px 12px;
}


@media screen and (max-width: 479px) {
    header {
        grid-column-start: column-line-1;
        grid-column-end: column-line-4;
    }
    main {
        grid-column-start: column-line-1;
        grid-column-end: column-line-4;
        grid-row: row-line-2;
    }
    aside {
        grid-column-start: column-line-1;
        grid-column-end: column-line-4;
        grid-row: row-line-3;
    }
    nav {
        grid-column-start: column-line-1;
        grid-column-end: column-line-4;
        grid-row: row-line-4;
    }
}

@media screen and (min-width: 480px) and (max-width: 639px) {
    nav {
        grid-column: column-line-1;
        grid-row: row-line-2;
    }
    aside {
        grid-column: column-line-1;
        grid-row-start: row-line-3;
        grid-row-end: row-line-5;
    }
    main {
        grid-column: column-line-2 / column-line-4;
        grid-row-start: row-line-1;
        grid-row-end: row-line-5;
    }
}

@media screen and (min-width: 640px) {
    header {
        grid-column-start: column-line-1;
        grid-column-end: column-line-4;
    }
    nav {
        grid-column: column-line-1;
        grid-row-start: row-line-2;
        grid-row-end: row-line-5;
    }
    aside {
        grid-column: column-line-3;
        grid-row-start: row-line-2;
        grid-row-end: row-line-5;
    }
    main {
        grid-column: column-line-2;
        grid-row-start: row-line-2;
        grid-row-end: row-line-5;
    }
}
<!DOCTYPE html>
<html lang="en">
<!-- 
    Created by Ron Royston, https://rack.pub, © 2018 MIT License
    Available online at https://github.com/rhroyston/html5
        
        ⚠ NO COMMENTS ABOVE DOCTYPE declaration.
        
        ⚠ Consider page viewing experience across device types, sometimes called Responsive Web Design, RWD.
        
        ⚐ Mozilla Developer Network HTML ELEMENT REFERENCE
            https://developer.mozilla.org/en-US/docs/Web/HTML/Element
            
        ⚐ Validate HTML with The W3C Markup Validation Service
            https://validator.w3.org/
            
        ⚐ Favicon image displays in browser tab
            http://realfavicongenerator.net/
-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- Mobile viewing enhancement -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- ⚠ Description should be roughly 155 characters, no double quotes, use keywords -->
    <meta name="description" content="CSS Responsive Grid Layout. Simple. Clean. Golden." />
    <!-- ⚠ Format as Primary Keyword - Secondary Keyword | Brand Name, keep under 55 characters -->
    <title>Golden Grid - CSS Responsive Grid Layout. Simple. Clean. Golden.</title>
    
</head>
<body class="mdc-typography">
    <header>
        <nav>
            <section>
                <div>
                    <img src="//intrest.run/media/character.png" height="24px">
                </div>
            </section>
            <section>
                <div>
                    <button>
                        Sign In
                    </button>
                </div>
            </section>
        </nav>
    </header>
    <main>
        <section>
            <h4>Page Name</h4>
        </section>      
        
        <section>
            <p>2 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>    
        </section>
        
        <section>
            <p>3 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>    
        </section>

    </main>
    <nav>
        <section>
            <!--
                This area is normally on the left hand side of page
            -->
            <h3>Navigation</h3>
            <a href="#">Home</a>
            <a href="#">Chapter 1</a>
            <a href="#">Chapter 2</a>
            <a href="#">Chapter 3</a>
            <a href="#">Chapter 4</a>
        </section>
    </nav>
    <aside>
        <!--
            This area is normally on the right hand side of page
        -->
        <section>
            <h3>Sidebar</h3>
            <p>Aside Element. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
        </section>
    </aside>
    <footer>
        <section>
            <h3>Footer</h3>
            <p>Footer Element. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
        </section>
    </footer>
</body>

</html>
Bullfrog answered 13/11, 2017 at 1:50 Comment(0)
F
3

CSS Grid is a great tool for putting together complex layouts.

But you're looking for a simple one-column grid, with three rows, and the footer pinned to the bottom of the container.

I would suggest that flexbox is a simpler and more efficient solution in this case. (You can always use Grid within each flex item.)

// 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("p");
});
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
}

nav {
  flex: 0 0 100px;
  background-color: lightgreen;
}

main {
  background-color: orangered;
}

footer {
  flex: 0 0 100px;
  margin-top: auto; /* pin footer to the bottom; see link below for details */
  background-color: lightgray;
}

nav, main, footer {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>Nav</nav>
<main>
  <p><button id="add">Add Content</button></p>
</main>
<footer>Footer</footer>

revised codepen

For more information about flex auto margins, see this post:

Forland answered 11/9, 2017 at 15:29 Comment(0)
U
0

Another minimal starting point to achieve a sticky footer using CSS Grid Layout is to use the following CSS:

body {
    display: grid;
    grid-template-rows: auto 1fr auto;
    min-height: 100vh;
    margin: 0;
}

The number of rows set to grid-template-rows is three (3) so the number of child elements within the <body> node must match this number. (As per the HTML listed in OP's question):

<body>
    <header>Header</header>
    <main>
        <p>Video provides a powerful way to help you prove your point.</p>
    </main>
    <footer>Footer</footer>
</body>

The original CodePen referenced by the OP uses the same properties in the CSS rule for the <body> element. It adds property settings for .footer but these settings are unnecessary.

As @Ronnie Royston points out in his answer, min-height: 100vh is necessary for the <body> element to stretch to the full size of the viewport of the client browser.

The margin: 0; removes the default margin spacing set by most browsers.

If grid-template-columns is not set CSS Grid Layout defaults to one column so it's unnecessary to set this property in a style rule.

The auto 1fr auto for grid-template-rows sets three rows. The value of auto means that the height of the row will match the size of the content within the element. The value of 1fr means to take up the remaining space for the element between the two rows that have auto applied.

This allows for a header and footer that has a background color applied across the browser window whereas @Henry's Cat adds three columns with the middle column containing the content. As he points out, however, avoid using pixels in any sizing and spacing of Grid Layout elements. Use padding with em/rem or vw/vh units around the content of the header or footer to increase the height of the header and footer.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        body {
            display: grid;
            grid-template-rows: auto 1fr auto;
            min-height: 100vh;
            margin: 0;
        }

        header {
            background-color: #232323;
            color: #fff;
        }

        main {
            background-color: #bbdaf1;
        }

        footer {
            background-color: #8badc6;
        }
    </style>
</head>
<body>
    <header>Header</header>
    <main>
        <p>
            Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.
            To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries.
            Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme.
            Save time in Word with new buttons that show up where you need them. To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign.
            Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device.
        </p>
    </main>
    <footer>Footer</footer>
</body>
</html>
Undermost answered 3/5, 2021 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.