轉載請註明出處:葡萄城官網,葡萄城爲開發者提供專業的開發工具、解決方案和服務,賦能開發者。
【年末促銷】葡萄城 2018 歲末福利火熱放送中
原文出處:https://www.sitepoint.com/flexbox-css-flexible-box-layout/
近幾年,CSS領域出現了一些複雜的專用佈局工具,用以代替原有的諸如使用表格、浮動和絕對定位之類的各種變通方案。Flexbox,或者說是彈性盒子佈局模塊(Flexible Box Layout Module)是這些新佈局工具中的第一個,接着是CSS網格佈局模塊(CSS Grid Layout Module)。我們會在本文給出一個易於理解的flexbox入門介紹。
隨着CSS網格佈局的引入,你可能會問flexbox佈局是否真的還有必要。雖然它們所能做的事情有一些重疊,但其各自在CSS佈局中有着非常特別的目的。一般來說,flexbox在一維場景(比如,一串類似的元素)下有最佳應用,而網格是二維場景下理想的佈局方案(例如整個頁面的元素)。
即便如此,flexbox仍可以用於整個頁面的佈局,這樣它能爲那些還不支持網格佈局的瀏覽器提供合適的兼容處理。(必須承認,網格佈局正在大多數現代瀏覽器中快速得到支持,不過對flexbox的支持仍然更爲廣泛,所以如果你想讓你的佈局在稍微老舊的瀏覽器中也生效,使用flexbox作爲網格佈局的降級方案是很容易的)。
使用Flexbox的好處
flexbox的一些好處是:
- 頁面元素能被任意方向地放置(靠左、靠右、從上往下甚至從下往上)
- 佈局內容的可視順序能夠被反轉或重排
- 元素大小能“彈性”適應可用空間,並根據容器或者兄弟元素進行相應地對齊
- 能輕鬆實現等列寬佈局(與每一列裏面的內容無關)
爲了闡述其多樣的屬性和可能性,讓我們假設下面有這樣的佈局用例:
<div class="example">
<header>
header content here
</header>
<main class="main">
<nav>
nav content here
</nav>
<div class="content">
main content here
</div>
<aside>
aside content here
</aside>
</main>
<footer>
footer content here
</footer>
</div>
首先,是把元素一起放進.main
裏,比如,<nav>
和<aside>
。如果沒有flexbox,我們可能會把三個元素全部進行浮動,但想讓它按理想的方式工作顯得並不直觀。而且,按傳統的方式做這件事會出現一個衆所周知的問題:每一列僅僅和它的內容一樣高。因此,你可能需要把三個元素都設置爲統一的高度,或者使用某種黑科技。
讓flexbox來救場吧。
讓我們Flex
flexbox的要點是出現在display
屬性上的flex
值,它需要被設置在容器元素上。如此設置會讓它的子元素變成“彈性項目(flex item)”。這些彈性項目擁有一些易於使用的默認屬性。比如,它們被緊挨着放置,那些沒有特別指明寬度的元素自動佔滿了剩餘的空間。
因此,如果你給.main
設置了display:flex
,它的子元素.content
就被自動擠在<nav>
和<aside>
之間。不需要再多餘的計算,多麼方便是吧?作爲附加獎賞,所有三個元素神奇地擁有了相同的高度。
.main {
display: flex;
}
請查看下面的例子,包含了所有的細節:flexbox-demo-1。
項的順序:Flebox的order
屬性
另外一個flexbox的能力,是能夠輕鬆改變元素的顯示順序。讓我們假設你爲一個客戶製作了上面的佈局,而她現在想要.content
出現在<nav>
之前。
通常,你需要深入到HTML源碼中去,在那裏改變元素的順序。而有了Flexbox,你可以完全使用CSS完成這項任務。只需把.content
的order
屬性設置爲-1
,那麼這一列就會出現在前面,這本例就是最左邊。
.main {
display: flex;
}
.content {
order: -1;
}
本例中,你不需要改變其他列的order
。例子在flexbox-demo-2。
如果你傾向於顯式地爲每一列指定order
,你可以將.content
的order
設爲1
,把<nav>
的order
設爲2
,把<aside>
的設爲3
。
HTML源碼獨立於CSS的Flexbox樣式
但你的客戶並不滿足。她想讓<footer>
成爲頁面的第一個元素,顯示在<header>
之前。那好,同樣的,flexbox是你的朋友(雖然像在此例中,可能你得跟你的客戶好好談談,而不是跟隨指示)。因爲你不僅要重排列內部元素,還要重排外部的,display:flex
規則將被設置在<div class="example">
之上。注意這裏是如何在頁面中嵌套使用flex容器來達到你想要的效果的。
因爲<header>
,<main class="main">
和<footer>
相互堆疊着,你需要首先設置一個垂直上下文,它能夠通過設置flex-direction:column
來快速完成。還有,<footer>
的order
被設置爲-1
,如此一來它就出現在頁面的最上頭。就這麼簡單。
.example {
display: flex;
flex-direction: column;
}
footer {
order: -1;
}
所以,如果你想把一行元素修改爲一列,或者相反,你可以使用flex-direction
屬性,並設置它相應地爲column
或row
(row
是默認值)。
完整的例子在flexbox-demo-3。
然而,強大的能力也到來了更多的責任:謹記,一些用戶可能會使用鍵盤來導航你的基於flexbox的網站,如果你HTML源碼中元素的順序和屏幕上顯示的有所出入,那麼無障礙訪問的能力就成爲需要認真對待的問題。如果想了解得更多,請不要錯過HTML源碼順序 vs CSS顯示順序,網站無障礙訪問和易用性的專家Adrian Roselli針對這個問題給出了深入討論。
如何在Flexbox中對齊子項
Flexbox能非常直觀地處理子項的水平對齊和垂直對齊。
你可以使用align-items
對flex容器中的所有子項設置統一的對齊。如果你想給個別元素設置不同的對齊方式,使用align-self
。元素的對齊方式跟它所在父容器的flex-direction
有關。如果它的值是row
(意味着元素水平排列),對齊方式是指在垂直軸上。如果flex-direction
被設置爲column
(意味着元素垂直排列),對齊方式就是指在水平軸上。
例如,你讓一些元素在容器中分別有不同的對齊方式,你需要:
- 設置每個元素的
align-self
屬性爲合適的值。可能的值有:center
,stretch
(元素撐滿它的容器),flex-start
,flex-end
和baseline
(元素被放置在父容器的baseline上) - 把容器元素設置爲
display:flex
- 最後,注意父容器的
flex-direction
屬性,因爲它關係到子元素的對齊方式。
.example {
display: flex;
flex-direction: column;
}
.red {
align-self: center;
}
.blue {
align-self: flex-start;
}
.pink {
align-self: flex-end;
}
試試在下面的例子中,把父容器的flex-direction
在row
和column
之間切換,看看它們引起的實時變化。
如果想要容器中所有的元素有統一的對齊方式,你可以在容器上使用align-items
。可以的值有center
,flex-start
,flex-end
,stretch
(默認值:子項被拉伸以適應它們的容器)和baseline
(子項被放置在父容器的baseline上)。
.example {
display: flex;
align-items: center;
}
像往常一樣,試着把父容器的flex-direction
在row
和column
之間切換,看看它們如何影響着你設置align-items
值時所發生的作用。
在Flexbox裏兩端對齊
另一個控制對齊的屬性是justify-content
,當你想讓多個元素等分空間時非常有用。
可接受的值有:center
,flex-start
,flex-end
, space-between
(元素利用主軸之間的空間而排布)和space-around
(元素利用主軸之前、之間和之後的空間而排布)。
例如,在之前你一直使用的簡單HTML模板裏,你可以在<main>
裏找到三個元素:<nav>
,.content
和<aside>
。之前,它們都被擠在頁面的左邊。如果你想讓它們之間有一些空間,但是不讓第一個元素的左邊有空間,也不想讓最後一個元素的右邊有空間,你可以把.main
(即它們的父容器)裏的justify-content
設置爲space-between
。
.main {
display: flex;
justify-content: space-between;
}
也試一下設置爲space-around
,觀察不同的結果。例子在flexbox-demo-6。
在上面的例子中,我同樣把<header>
中的文字水平和垂直對齊了,分別是把justify-content
(水平居中)和align-items
(垂直居中)都設置爲center
。
header {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
Flexbox中彈性子項的大小
使用flex
屬性,你能夠對照flex容器中其他元素來控制彈性子項的大小。
這個屬性是以下獨立屬性的簡寫:
flex-grow
:一個數字,指明元素如何相對其他flex項來拉伸flex-shrink
:一個數字,指明元素如何相對其他flex項來收縮flex-basis
:元素的長度。可接受的值有:auto
,inherit
或者一個數字後面緊跟着%
,px
,em
或其他長度單位。
例如,想得到三個等寬的列,只需給每一列設置flex:1
,其他什麼都不用做:
nav, aside, .content {
flex: 1;
}
如果你需要.content
佔據<nav>
和<aside>
的兩倍寬,那麼就把.content
設爲flex:2
,讓其他兩個爲1
。
那僅僅是對flex
屬性最簡單的應用。同樣可以設置flex-grow
,flex-shrink
和flex-basis
這些值,不過那超出本文的話題範圍了。
進一步的資源
如果你準備好繼續前進,並想學着精通flexbox的更多東西,請查看下面的資源:
- Flexbox SitePoint上Guy Routledge製作的一個付費課程
- Building Mega Menus with Flexbox
- How 3 Modern Tools are Using Flexbox Grids
- Make Forms Fun with Flexbox.
總結
如你所見,如果我們想控制元素在網頁中的佈局,flexbox可以讓我們的生活更加輕鬆。它非常穩固和可靠,讓以前那些我們每天使用的諸如使
讓容器坍縮之類的奇技淫巧,成爲了過去。
像我們說的,如今,在針對整個頁面進行佈局時,CSS網格是更好的方案,但我們仍然值得去了解flexbox能做的那些事情。flexbox的最佳應用場景,體現在對元素的一維排列上,但如果有需要,它也能在稍老舊的瀏覽器中,爲CSS網格佈局提供方便的替代方案。