如何在我的 CSS 网格布局中设置粘性页脚?

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

我发现 this CodePen solution 在 CSS 网格布局中有一个粘性页脚,但它对我来说有两个问题:

  1. min-height: 100%height: 100%
  2. 有点难看
  3. 它只适用于正文中的两个元素(一个 div 和一个页脚)

我需要一些与此 HTML 结构兼容的东西:

<body>
    <nav>Some navigation buttons</nav>
    <main>The content</main>
    <footer>Copyrights and stuff</footer>
</body>

我真的不想将 <nav><main> 打包成 <div>,我很想在 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>

CSS 网格是组合复杂布局的绝佳工具。

但是您正在寻找一个简单的单列网格,三行,并且页脚固定在容器的底部。

在这种情况下,我建议 flexbox 是一种更简单、更有效的解决方案。 (您始终可以在每个弹性项目中使用网格。)

// 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

有关弹性自动边距的详细信息,请参阅此 post:

粘性页脚是用一行CSS实现的,即:min-height: 100vh.

示例如下:

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>

这是一个 CSS 网格解决方案,但使用 class 作为目标要好得多。
使用网格区域这将非常简单:

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>

诀窍是使用:

min-height: 100vh; grid-template-rows: auto auto 1fr; 与...

align-self: end; 用于页脚。

如果我们添加 left/right 个边距,将 <nav> 放在页眉中,为页脚内容添加一个边距,并为主要内容假设另一个网格:

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>

这具有以前解决方案所缺乏的简洁性。

使用 常青浏览器 没有必要使事情复杂化。

以前的答案不太容易维护。陷阱包括:

  • 强制 header/footer 固定像素尺寸。
  • 使用网格区域而不是更简单的网格定义。将 grid-template-rows 和 grid-template-columns 组合成一行有加分。
  • 广泛的 'width/height/min-height: 100%' 定义在 html 和正文标签上无处不在。这在 IE6 盛行但现代浏览器不需要时可能有意义。
  • 使用 flexbox 布局。这不是未来的布局引擎。 CSS 网格将是我五年后要维护的。
  • 使用像素和百分比。什么是像素?谁知道什么时候有视网膜屏幕和高分辨率 phone 屏幕。我以前喜欢像素,但还有其他更有意义的单位,'vw/vh/vmin/vmax' 加上 'em/rem'。 CSS 网格的百分比测量也即将结束,因此最好改掉这个习惯。

使用 CSS 网格布局实现粘性页脚的另一个最小起点是使用以下 CSS:

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

设置为 grid-template-rows 的行数是三 (3),因此 <body> 节点中的子元素数必须与该数字匹配。 (根据 OP 问题中列出的 HTML):

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

OP 引用的原始 CodePen 在 <body> 元素的 CSS 规则中使用相同的属性。它为 .footer 添加了 属性 设置,但这些设置是不必要的。

正如@Ronnie Royston 在他的回答中指出的那样,min-height: 100vh<body> 元素伸展到客户端浏览器视口的完整尺寸所必需的。

margin: 0; 删除了大多数浏览器设置的默认边距间距。

如果未设置 grid-template-columns CSS 网格布局默认为一列,因此无需在样式规则中设置 属性。

grid-template-rowsauto 1fr auto 设置三行。 auto 的值意味着行的高度将匹配元素内内容的大小。 1fr的值表示为应用了auto的两行之间的元素占用剩余的space。

这允许在浏览器中应用背景颜色的页眉和页脚 window 而 @Henry 的 Cat 添加三列,中间列包含内容。然而,正如他指出的那样,避免在网格布局元素的任何大小和间距中使用像素。在页眉或页脚的内容周围使用 em/remvw/vh 单位的填充来增加页眉和页脚的高度。

<!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>