-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[译] [706] [#41] 紧贴底部的页脚 #18
Comments
CSS 2.1下有什么好得解决方案么 |
@xiaobaicaistring |
微博网友 @残阳映枫红 反馈:
|
好期待这本书!
这里是笔误吗?视口高度减去页脚高度 |
@joseph19921003 |
vh, vw在移动短的兼容性好么 |
@macsen110 |
Sticky footers
紧贴底部的页脚
The problem
难题
This is one of the oldest and most common problems in web design, so common that most of us have experienced it at one point or another. It can be summarized as follows: a footer with any block-level styling, such as a background or shadow, works fine when the content is sufficiently long, but breaks on shorter pages (such as error messages). The breakage in this case being that the footer does not “stick” at the bottom of the viewport like we would want it to, but at the bottom of the content.
在网页设计中,存在一个相当古老但又相当常见的问题,它是前端工程师绕不开的坎,躲得了初一逃不过十五。这个问题可以简单地概括如下:有一个具有块级样式的页脚(比如它设置了背景或阴影),当页面内容足够长时,这个页脚一切正常;而当页面较短时(比如错误信息页面)就会出现问题。此时的问题在于,页脚不能像我们所期望的那样 “紧贴” 在视口的最底部,而是紧跟在内容的下方。
It is not only its ubiquity that made it popular, but also how deceptively easy it looks at first. It’s a textbook case of the type of problem that requires significantly more time to solve than expected. In addition, this is still not a solved problem in CSS 2.1: almost all classic solutions require a fixed height for the footer, which is flimsy and rarely feasible. Furthermore, all of them are overly complicated, hacky, and have specific markup requirements. Back then, this was the best we could do, given the limitations of CSS 2.1. But can we do better with modern CSS, and if so, how?
这个问题不仅普遍存在,而且乍看起来确实相当简单。因此,在所有 “隐蔽大坑” 式的难题中,它简直就是教科书般的典型案例。不仅如此,CSS 2.1 基本上拿它没有办法:几乎所有的经典解决方案都需要给页脚设置固定的高度,而这显然是不健壮的,也是不实际的。此外,所有这些解决方案都太过复杂了、太像 hack 了,而且往往还要求网页按照特定的结构来写。在那个年代,受制于 CSS 2.1 有限的能力范围,这已是我们所能达到的最好结果了。不过,在现代 CSS 协助下,我们可以做得更好吗?如果答案是肯定的,又该如何去做?
Fixed height solution
固定高度的解决方案
We will work with an extremely bare-bones page with the following markup inside the
<body>
element:我们手头的这个页面极其简单,
<body>
元素内的结构代码如下所示:We have also applied some basic styling to it, including a background on the footer. You can see how it looks in Figure XX.XX. Now, let’s reduce the content a bit. You can see what happens then, in Figure XX.XX. This is the sticky footer problem in all its glory! Great, we have recreated the problem, but how do we solve it?
然后我们给页面加上一些基本样式,再给页脚加上一层背景。你可以在 图 7.23 中看到它的样子。现在,让我们把页面内容缩短一点儿,然后可以在 图 7.24 中看到结果。此时页脚沉不到底的问题就完全暴露出来了!好吧,我们重现了这个问题,但我们该如何解决这个问题呢?
If we assume that our footer text will never wrap, we can deduce a CSS length for its height:
假设这个页脚的文本永远不可能折行,那我们就可以推算出它实际所占的高度:
2 lines × line height + 3 × paragraph margin + vertical padding =
{-:-}2 行 × 行高 + 3 × 段落的垂直外边距 + 页脚的垂直内边距 =
{-:-}2 ×
1.5em
+ 3 ×1em
+1em
=7em
Similarly, the header height is
2.5em
. Therefore, by using viewport-relative units andcalc()
, we can “stick” our footer to the bottom with essentially one line of CSS:同样,我们可以得出页头的高度是
2.5em
。接下来,借助视口相关的长度单位以及calc()
函数,我们只需一行 CSS 代码就可以表达出这种尺寸关系,从而把页脚 “固定” 到底部:Alternatively, we could apply a wrapper around our
<header>
and<main>
elements so that we only need to calculate the footer height:或者换个方式,我们可以把
<header>
和<main>
元素包在一个容器里,然后在算式中就只需要考虑页脚的高度了:This works (Figure XX.XX) and it seems to be slightly better than the existing fixed height solutions, mainly due to its minimalism. However, except for very simple layouts, this is not practical at all. It requires us to assume that the footer text will never wrap, we need to edit the
min-height
every time we change the footer metrics (i.e., it is not DRY), and unless we’re willing to add a wrapper HTML element around our header and content, we need to do the same calculations and modifications for the header as well. Surely, in this day and age we can do better, right?这个方法是有效的(图 7.25),而且它似乎比已有的那些需要固定高度的方案还要稍稍好一些,主要好在它的代码极其精简。不过,如果页面布局不是这么简单的话,那这个方法就完全不实用了。它不仅要求我们确保页脚内的文本是永远不会折行的,而且每当我们改变了页脚的尺寸时,都需要跟着调整
min-height
值(也就是说,这不够 DRY);此外,除非我们愿意给页头和内容主体套一层额外的 HTML 元素,不然我们还得跟着页头的尺寸改。想必在这个美好的新时代,我们还有更好的办法,对吗?Flexible solution
更灵活的解决方案
Flexbox is perfect for these kinds of problems. We can achieve perfect flexibility with only a few lines of CSS and there is no need for weird calculations or extra HTML elements. First, we need to apply
display: flex
to the<body>
element, as it’s the parent of all three of our main blocks, to toggle Flexible Box Layout (Flexbox) for all three of them. We also need to setflex-flow
tocolumn
, otherwise they will be all laid out horizontally on a single row (Figure XX.XX):Flexbox 对于此类问题同样是完美的选择。我们只需寥寥几行 CSS 代码就可以完美达成十分灵活的布局效果,而且完全不需要复杂的计算,或是添加多余的 HTML 元素等等。首先,我们需要对
<body>
元素设置display: flex
,因为它是这三个主要区块的父元素,当父元素获得这个属性之后,就可以对其子元素触发 “伸缩盒布局模型”。我们还需要把flex-flow
设置为column
,否则子元素会被水平排放在一行上(图 7.26):At this point, our page looks about the same as it did before all the Flexbox stuff, as every element occupies the entire width of the viewport and its size is determined by its contents. Ergo, we haven’t really taken advantage of Flexbox yet.
此时,页面看起来跟没有启用 Flexbox 的情况似乎是一样的,因为所有元素都占据了整个视口的宽度,而它们的高度也都是由它们自身的内容来决定的。也就是说,我们还没有真正发挥 Flexbox 的威力呢。
To make the magic happen, we need to specify a
min-height
of100vh
on<body>
, so that it occupies at least the entire height of the viewport. At this point, the layout still looks exactly like Figure XX.XX, because even though we have specified a minimum height for the entire body element, the heights of each box are still determined by their contents (i.e., they are intrinsically determined, in CSS spec parlance).为了完全释放它的魔力,我们首先要把
<body>
的min-height
属性指定为100vh
,这样它就至少会占据整个视口的高度。不过,现在整个页面的布局仍然跟 图 7.24 无异,原因在于,虽然我们已经为整个body
元素指定了最小高度,但各个子元素的高度仍然是以各自的内容为准的(按照 CSS 规范的说法,它们的高度仍然是由内部因素来决定的)。What we need here is for the height of the header and footer to be intrinsically determined, but the height of the content should flexibly stretch to all the leftover space. We can do that by applying a
flex
value that is larger than0
(1
will work) to the<main>
container:此时我们所期望的是,页头和页脚的高度由其内部因素来决定,而内容区块的高度应该可以自动伸展并占满所有的可用空间。我们只要给
<main>
这个容器的flex
属性指定一个大于0
的值(比如1
即可),就可以实现这个效果了:That’s it, no more code required! The perfect sticky footer (same visual result as in Figure XX.XX), with only four simple lines of code. Isn’t Flexbox beautiful?
这样就可以了!我们只需要四行简单的代码,就完美实现了紧贴底部的页脚(跟 图 7.25 中的效果一致)。Flexbox 是不是相当霸气?
The text was updated successfully, but these errors were encountered: