CSS秘密花園: Sticky footers
《 CSS Secrets 》是 @Lea Verou 最新著作,這本書講解了有關于CSS中一些小秘密。是一本CSSer值得一讀的一本書,經過一段時間的閱讀,我、@南北和@彥子一起將在W3cplus發布一系列相關的讀后感,與大家一起分享。
問題
在網頁設計中,Sticky footers設計是最古老和最常見的效果之一,大多數人都曾經經歷過。它可以概括如下:如果頁面內容不夠長的時候,頁腳塊粘貼在視窗底部;如果內容足夠長時,頁腳塊會被內容向下推送。
這種效果不僅是無處不在,很受歡迎,而且實現起來看上去也非常容易。但實際上實現起來要比預期花的時間更多。此外,在CSS2.1中的解決方案中幾乎都要給頁腳設置一個固定高度。這是很脆弱的,很少是可行的。實際上實現這個效果過于復雜,而且還需要增加特定的標記和一些Hack手段。在CSS2.1中受到一些限制,但使用現代CSS,我們能把這個效果做得更好,那要如何做呢?
如果你從未看過這樣的效果或者對這個問題的相關資料感興趣的話,這里有一些受歡迎的文章,提供了許多Web開發人員的構思和解決方案:
- CSS Sticky Footer Layout
- Ryan Fait's CSS Sticky Footer
- Sticky Footer
- Sticky CSS footers: The flexible way
- Modern Clean CSS “Sticky Footer”
最后兩個是最簡潔的實現方案,但仍然有其自己的局限性。
固定高度的解決方案
我們在 <body> 元素下使用一些常用的HTML標簽元素:
<header>
<h1>Site name</h1>
</header>
<main>
<p>Bacon Ipsum dolor sit amet...
<!-- Filler text from baconipsum.com --></p>
</main>
<footer>
<p>? 2015 No rights reserved.</p>
<p>Made with ? by an anonymous pastafarian.</p>
</footer>
給頁面寫一些基本樣式。看到的效果如下圖所示:
現在,我們來減少一些內容。你可以看看會發生什么,如下圖所示:
太好了,問題出現了,但我們要如何解決這個問題呢?
如果我們假定頁腳文本不會溢出容器,我們可以為容器推算出其高度:
2行 * 行高 + 3 x 段落的margin + 垂直的padding = 2 x 1.5em + 3 x 1em + 1em = 7em
同樣,頁頭的高度是 2.5em 。因此,通過使用視窗相對單位和 calc() ,使用一行CSS代碼,可以實現Sticky footers效果:
main {
min-height: calc(100vh - 2.5em - 7em);
/* Avoid padding/borders screwing up our height: */
box-sizing: border-box;
}
或者,我們可以使用一個容器將 <header> 和 <main> 元素包裹起來,這樣我們只需要計算頁腳的高度:
#wrapper {
min-height: calc(100vh - 7em);
}
這似乎略優于現有的固定高度的解決方案,主要是由于其簡單。然而,除了簡單的布局,但這是不切合實際。它要求我們每次都要計算包裹頁腳文本容器的高度,這樣我們需要每次計算容器的 min-height 。除非我們愿意添加HTML容器來包裹我們的標題和內容,不過同意也要計算。當然,在這個時代,我們可以做得更好,對嗎?
Flexbox解決方案
解決這類問題,Flexbox是最完美的方案。我們只需要幾行CSS代碼就可以完美的實現,而且不需要一些奇怪的計算或添加額外的HTML元素。首先,我們需要在 <body> 元素上設置 display:flex 。如果父元素( <body> )的三個塊元素,使用Flexbox切換布局,還需要設置 flex-flow:column ,否則這三個塊會排成一行。如下圖所示:
body {
display: flex;
flex-flow: column;
}
在這一點上,我們的頁面看起來和之前一樣,因為每個元素所占視窗高度是由其內容決定。如此一來,我們可以說還沒有真正的利用上Flexbox。
從實際出發,需要給 <body> 設置 min-height 值為 100vh ,讓 <body> 內容不足視窗高度時也能占據整個視窗。雖然這樣做了,效果看起來,還是如下圖所示:
即使給 <body> 指定了最小高度,但每個盒子的高度仍取決于其內容大小。
這里我們需要在頁頭和頁腳設置高度,但其內容的高度自動伸縮的來適配剩余空間。我們可以在 <main> 上設置 flex 值大于 0 (常用的是 1 ):
body {
display: flex;
flex-flow: column;
min-height: 100vh;
}
main { flex: 1; }
flex 屬性是 flex-grow 、 flex-shrink 和 flex-basis 三個屬性縮寫。任何元素設置了 flex 大于 0 ,元素就會靈活的控制自己的尺寸,來適配容器的剩余空間。例如,如果 <main> 設置了 flex:2 , <footer> 設置了 flex:1 ,那么頁腳的高度是主內容高度的二分之一,同樣的,如果值設置的是 4 和 2 而不是 2 和 1 ,他們效果是一樣的,因為他們的倍數比例值一樣。
就這樣,不需要更多的代碼!就能實現如下圖所示的Sticky footers效果:
僅僅用了四行代碼,是不是覺得Flexbox很強大,很完美呀。
來自: http://www.w3cplus.com/css3/css-secrets/sticky-footers.html