保持页脚在底部:Flexbox 方案与 Grid 方案的比较

93 阅读4分钟

原文:Keep the Footer at the Bottom: Flexbox vs. Grid

作者:Stephanie Eckles

多年来,我一直在参考 Matthew James Taylor 的文章来解决一个问题:无论主内容的长度如何,都能将网页页脚保持在页面底部。这种方法需要为页脚设置明确的高度,虽然不具有可伸缩性,但在 Flexbox 出现之前是一个非常好的解决方案。

如果你主要从事 SPA 开发,你可能会对这个问题仍然存在感到困惑,但在以下情况下,你仍然有可能发现页脚浮起来了:

  • 登录页面
  • 博客/新闻文章(没有广告...)
  • 流程的中间页面,如确认操作
  • 产品列表页面
  • 日历事件详情页面

译注:SPA 是单页 Web 应用(single page web application)的英文缩写。

现代 CSS 中有两种方法可以解决这个问题:flexbox 和 grid。

下面的演示默认是使用 flexbox 实现的。你可以尝试将 $method 变量的值切换成 grid 看一下另一种方案的效果。

Flexbox 方案

这种方案是使用下面的样式定义实现的:

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

footer {
  margin-top: auto;
}

/* 可选 */
main {
  margin: 0 auto;
  /* 或: align-self: center */
  max-width: 80ch;
}

工作原理

首先,我们设置 min-height: 100vh 确保 body 元素的高度至少为屏幕高度。如果内容较短,这是不会有溢出的(例外:某些移动浏览器),并且这使得高度可以随内容拉升。

设置 flex-direction: column 可以保持正常文档流的行为,即在保持堆叠块级元素(这里假设 body 的直接子元素都是块元素)。

译注:这里是说,未设置 display: flex; 时的文档流行为是 body 的直接子元素会按照它们在源代码中的顺序垂直堆叠(假设都为块元素),设置 flex-direction: column 内保持这种行为。

flexbox 的优势在于利用 margin: auto 的行为。这个奇怪的技巧使得外边距会填充元素与其临近兄弟元素间的空间。设置 margin-top: auto 有效地将页脚推到屏幕的底部。

陷阱

在演示中,我给 main 元素添加了轮廓,以说明使用 flexbox 方案时,main元素不会填充高度。这就是我们必须设置 margin-top: auto 的原因。这对你来说可能不重要,但如果你觉得这重要,请参阅 grid 方案,它会拉伸 main 元素以填充可用空间。

Grid 方案

此方案通过设置以下样式来实现:

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

/* 可选 */
main {
  margin: 0 auto;
  max-width: 80ch;
}

工作原理

在这个方案中,我保留了 min-height: 100vh,但之后我们使用 grid-template-rows 设置了正确的排列方式。

此方案的技巧在于使用特殊的网格单位 frfr 表示 “fraction”,使用它请求浏览器计算可用于该行或该列的空间“分数”。在本例中,它会填充页眉和页脚之间的所有可用空间,这就解决了 flexbox 方案中的“陷阱”。

哪种方案更好?

看过 grid 方案,你可能会有一瞬间认为它显然更更好。然而,如果你需要在页眉和页脚之间添加了更多元素,你就得更新的模板(或确保总是有一个包装元素,如 div,以不影响任何嵌套的语义/层次结构)。

译注:更新模板是说:添加元素之后就不只是三行了,grid-template-rows: auto 1fr auto; 自然不起作用,你需要更新模板设置新添加元素得行高。或者说保持行数为三不变,只是页眉和页脚之间的元素使用 div 一类的元素包裹。

另一方面,flexbox 方法可用于具有多个块元素的多个模板的中间部分: 例如,一系列 <article> 元素,而不是单个 <main> 元素用于存档页面。

译注:这是说,对于需要多个块元素时,如一系列 <article> 元素,使用 flexbox 是方便的,使用 grid 可能需要更多的设置。

因此,与所有技术一样,哪种方案更好取决于项目:) 但我们都可以同意,拥有这些现代 CSS 布局方法真是 amazing!