1. 程式人生 > >CSS: Sticky footers

CSS: Sticky footers

問題

在網頁設計中,Sticky footers設計是最古老和最常見的效果之一,大多數人都曾經經歷過。它可以概括如下:如果頁面內容不夠長的時候,頁尾塊貼上在視窗底部;如果內容足夠長時,頁尾塊會被內容向下推送。

這種效果不僅是無處不在,很受歡迎,而且實現起來看上去也非常容易。但實際上實現起來要比預期花的時間更多。此外,在CSS2.1中的解決方案中幾乎都要給頁尾設定一個固定高度。這是很脆弱的,很少是可行的。實際上實現這個效果過於複雜,而且還需要增加特定的標記和一些Hack手段。在CSS2.1中受到一些限制,但使用現代CSS,我們能把這個效果做得更好,那要如何做呢?

如果你從未看過這樣的效果或者對這個問題的相關資料感興趣的話,這裡有一些受歡迎的文章,提供了許多Web開發人員的構思和解決方案:

最後兩個是最簡潔的實現方案,但仍然有其自己的侷限性。

固定高度的解決方案

我們在<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>

給頁面寫一些基本樣式。看到的效果如下圖所示:

Sticky footers

現在,我們來減少一些內容。你可以看看會發生什麼,如下圖所示:

Sticky footers

太好了,問題出現了,但我們要如何解決這個問題呢?

如果我們假定頁尾文字不會溢位容器,我們可以為容器推算出其高度:

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);
}

Sticky footers

這似乎略優於現有的固定高度的解決方案,主要是由於其簡單。然而,除了簡單的佈局,但這是不切合實際。它要求我們每次都要計算包裹頁尾文字容器的高度,這樣我們需要每次計算容器的min-height。除非我們願意新增HTML容器來包裹我們的標題和內容,不過同意也要計算。當然,在這個時代,我們可以做得更好,對嗎?

Flexbox解決方案

解決這類問題,Flexbox是最完美的方案。我們只需要幾行CSS程式碼就可以完美的實現,而且不需要一些奇怪的計算或新增額外的HTML元素。首先,我們需要在<body>元素上設定display:flex。如果父元素(<body>)的三個塊元素,使用Flexbox切換佈局,還需要設定flex-flow:column,否則這三個塊會排成一行。如下圖所示:

Sticky footers

body {
    display: flex;
    flex-flow: column;
}

在這一點上,我們的頁面看起來和之前一樣,因為每個元素所佔視窗高度是由其內容決定。如此一來,我們可以說還沒有真正的利用上Flexbox。

從實際出發,需要給<body>設定min-height值為100vh,讓<body>內容不足視窗高度時也能佔據整個視窗。雖然這樣做了,效果看起來,還是如下圖所示:

Sticky footers

即使給<body>指定了最小高度,但每個盒子的高度仍取決於其內容大小。

這裡我們需要在頁頭和頁尾設定高度,但其內容的高度自動伸縮的來適配剩餘空間。我們可以在<main>上設定flex值大於0(常用的是1):

body {
    display: flex;
    flex-flow: column;
    min-height: 100vh;
}
main { flex: 1; }

flex屬性是flex-growflex-shrinkflex-basis三個屬性縮寫。任何元素設定了flex大於0,元素就會靈活的控制自己的尺寸,來適配容器的剩餘空間。例如,如果<main>設定了flex:2<footer>設定了flex:1,那麼頁尾的高度是主內容高度的二分之一,同樣的,如果值設定的是42而不是21,他們效果是一樣的,因為他們的倍數比例值一樣。

就這樣,不需要更多的程式碼!就能實現如下圖所示的Sticky footers效果:

Sticky footers

僅僅用了四行程式碼,是不是覺得Flexbox很強大,很完美呀。

原文:

https://www.w3cplus.com/css3/css-secrets/sticky-footers.html