Keep your footer at the bottom of the page


项目里遇到的问题,让 footer 总是显示在页面最下方。(这里讨论的不是让 footer 固定在 viewport(或浏览器窗口)的底部)。

背景:还没有对 <html><body><footer> 这些元素的 positionheight 属性做任何改动。

问题描述

  1. long page

    简单来说,当页面包含大量内容,并且 footer 被自然地 pushed down off the viewpor,此时,你滚动页面到最下方,自然会看到页面结束在 footer。你不会注意到 footer 有什么不妥的地方。

  2. short page

    然而当页面只有少量内容(实际内容不足以占满整个窗口高度)的时候,你会看到 footer 跟着页面实际内容出现在半路,距离 viewport 底部有一大片空白。发现问题!

尝试解决

本以为简单地设置 footer 的位置就ok的,如下:

footer {  
  position: absolute;  
  bottom: 0;  
  width: 100%;  
}

然而这样写,可以解决 short page 页脚的问题。

对于 long page 乍一看 footer 放置在了浏览器的底部,遮住了页面靠近浏览器底部的内容(所以记得给 body 内容区域设置 padding-bottom)。当你向下滚动页面时,会看到 footer 一直被定在那个“初始”位置。

本来没问题的 long page 现在出现问题了😔

<html> vs. <body>

参考此文章中的观点,盗个图。

html vs. body in browser

中文翻译重点:

  • <html><body> 元素是不同的块级元素,是父/子元素的关系
  • html 元素的宽和高由浏览器窗口决定
  • <html> 元素默认 overflow 属性值为 auto,当需要时自动出现 scrollbar
  • 大部分浏览器内置的页面边距应用在 <body>margin 上,而不是 <html>padding
  • 块级元素如果不指定高度,会根据其包裹的内容自动增长高度;如果为其指定高度,接下来发生的事就要取决于 overflow 这个属性的值了。

解决问题

现在再来分析下之前页面出现问题的原因。此时 footer 的位置是相对于 <html> 而言(因为它的最近的父元素 <body> 此时 position 还是 static 的)。

当你不向下滚动页面,只改变浏览器窗口的高度,会看到 footer 随着窗口底部移动,效果同 position: fixed; bottom: 0;

区别是:当你向下滚动页面,不改变浏览器窗口的高度,设为 fixed 的页脚始终可见,而如上设置 absolute 的页脚,滚着滚着就滚上去看不见了(因为 <html> 的高是当前的 window 的高,页脚是定在这个高度的底部)。

添加以下代码:

body {
  position: relative;  
}

这样 footer 的相对放置位置变为 <body> 元素,在 long page 页脚就自然而然放置在页面结尾处,long page 问题解决。

但已经改好的 short page 又有问题了🙀

页面高度问题

许多人认为 html、body 这些元素总是有至少和浏览器窗口一样的高度,事实上,<html><body> 元素会收缩以占据尽可能小的高度。即,实际内容撑起高度。

因此,对于 short page 只有 <body> 元素高度至少为窗口高度的 100% 时,footer 才可能被放在底部。

添加以下代码

html {
  height: 100%;
}
body {
  min-height: 100%;  
}

这个添加改动对于 long page 是没有明显影响的。

最后,记得给长页面可视区域父元素设置底部内边距

Other

在短页面的实际内容之下是一片空区域,只能设置 <body> 元素的 background 属性,任何其他元素都不能占据这块空间或被 styled.