現(xiàn)在大部分瀏覽器都支持flexbox布局方法。react和react-native中幾乎全部采用flex來(lái)布局。簡(jiǎn)單總結(jié)下常用屬性供參考。
1. flex-direction 屬性
先以一個(gè)簡(jiǎn)單的nav為例:
HTML
<nav class="main-nav">
<ul>
<li><a href="#">Work</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
CSS
body {
background: white;
font-family: 'Open Sans', sans-serif;
}
.main-nav li {
width: 100px;
}
.main-nav a {
text-decoration: none;
color: black;
font-size: 21px;
font-weight: 600;
color: #00a9d9;
}
.main-nav a: hover {
text-decoration: underline;
}
效果

現(xiàn)在加上以下屬性
.main-nav ul {
list-style: none;
display: flex;
}
變?yōu)?/p>

flex會(huì)讓<ul>這個(gè)容器成為一個(gè)具有flex功能的block-level容器,并且會(huì)影響到它的子元素的布局表現(xiàn)。
如果想讓<ul>成為一個(gè)inline元素,可以寫(xiě)成display: inline-flex,這樣它仍然具有flex container的效果,同時(shí)也表現(xiàn)為一個(gè)inline元素,就像<img>一樣。
當(dāng)加上display: flex;后,<li>元素由垂直排列變成了水平排列。這是因?yàn)?code>flex的flex-direction屬性的默認(rèn)值為row,如果我們添加上
.main-nav ul {
list-style: none;
display: flex;
flex-direction: column
}
能看到<li>元素又變?yōu)榱舜怪迸帕小?/p>
flex-direction的值除了row,column還可以是row-reverse和column-reverse。
flex-direction這個(gè)屬性在用在響應(yīng)式web design上非常便利,配合media-query可以根據(jù)屏幕大小,將元素從水平排列變成垂直排列。
需要注意的是flexbox屬性, 包括 flex-direction, 在有些瀏覽器上需要加prefixes,所以用之前一定要查查瀏覽器支持情況, can I use 這個(gè)網(wǎng)站就可以。還有個(gè)很方便的方法是用auto prefixer post CSS工具可以自動(dòng)添加前綴,省去很多麻煩。
2. order屬性
先添加加上header,main和footer,為了明顯用背景色塊來(lái)區(qū)分。
HTML
<body>
<header class="main-header">Header</header>
<nav class="main-nav">
<ul>
<li><a href="#">Work</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<main class="main-content">Content</main>
<footer class="main-footer">Footer</footer>
</body>
CSS
.main-header {
background: #B61E32;
padding: 10px;
}
.main-content {
background: #F7CE2B;
min-height: 40vh;
padding: 10px;
}
.main-footer {
background: #ABC999;
padding: 10px;
}
效果

然后將整個(gè)body都設(shè)為flex容器
body {
display: flex;
flex-direction: column;
}
此時(shí),所有的flex元素默認(rèn)order都是0,所以會(huì)按照元素的順序來(lái)渲染,如果將某元素的order改成1:
.main-nav {
order: 1;
}
可以看到main-nav元素跑到了最下面。

當(dāng)然,還能設(shè)為負(fù)數(shù),試試改為-1。
3. justify-content屬性
html
<body>
<article class="fake-article">
<header>
<h1>Fake Article</h1>
</header>
<p>Vestibulum id ligula porta felis euismod semper. Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Donec ullamcorper nulla non metus auctor fringilla.</p>
</article>
<article class="not-real">
<header>
<h1>Not Real</h1>
</header>
<p>Nullam quis risus eget urna mollis ornare vel eu leo. Etiam porta sem malesuada magna mollis euismod.</p>
</article>
<article class="phoney">
<header>
<h1>Phoney</h1>
</header>
<p>Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.</p>
</article>
</body>
css
:root {
height: 100%;
}
body {
font-family: 'Open Sans', sans-serif;
margin: 0;
min-height: 100%;
background: #333;
}
h1 {
font-weight: 600;
margin: 0 0 5px 0;
}
p {
margin: 5px 0;
}
article {
box-sizing: border-box;
background: #FFF;
margin: 5px;
}
body {
display: flex;
flex-direction: column;
}
效果:

justify-content這個(gè)屬性會(huì)影響children沿著flex-direction方向的排列和空間分配。當(dāng)前的flex-direction是column。所以這個(gè)屬性會(huì)影響子元素在從上到下的豎直方向上,如何分配多余空間,但是并不會(huì)改變?cè)乇旧淼膶?shí)際大小。
-
flex-start:
justify-content默認(rèn)值是flex-start,意思是所有元素都是從起始點(diǎn)開(kāi)始向下排列。 - flex-end: 設(shè)成flex-end,可以看到子元素們會(huì)一起從結(jié)束點(diǎn)開(kāi)始排列。
body {
display: flex;
flex-direction: column;
justify-content: flex-end;
}
效果:

- center: 設(shè)成center,他們就會(huì)一起擠在中間的位置,還記得剛開(kāi)始學(xué)css的時(shí)候總是為如何才能實(shí)現(xiàn)真正的vertical-align苦惱,有了flexbox終于能非常簡(jiǎn)單的實(shí)現(xiàn)了。

- space-between: 第一個(gè)元素在start位置,最后一個(gè)元素在end位置,中間元素均等間隙排列。

- space-around: 會(huì)平均分配剩余空間給所有元素間隙,但第一個(gè)元素的前面和最后一個(gè)元素的后面則是中間的間隙距離一半。

4. align-items 和 align-self
justify-content是會(huì)影響子元素沿著flex-direction方向的排列,而align-item則會(huì)影響子元素與flex-direction方向垂直的方向上的排列情況。
為了更直觀的說(shuō)明,將flex-direction改為row,并將article的flex設(shè)為1,意思是所有article所占寬度總相等。
body {
display: flex;
flex-direction: row;
}
article {
box-sizing: border-box;
background: #FFF;
margin: 5px;
flex: 1;
}
- 這樣改之后會(huì)發(fā)現(xiàn),三個(gè)ariticle元素雖然內(nèi)容高度不同,但box都變成了100% height,這是因?yàn)?strong>align-items的默認(rèn)值是
stretch,就是會(huì)用掉所有的垂直方向上的多余空間。

- 若將align-items的值設(shè)為”flex-start“,如圖,就會(huì)變成不同高度。
body {
display: flex;
flex-direction: row;
align-items: flex-start;
}

- 相似的還有 flex-end, center。
- 還有一個(gè)值是 baseline。就是根據(jù)首個(gè)元素的baseline來(lái)進(jìn)行對(duì)齊。
align-items是用于container的屬性,統(tǒng)一設(shè)置子元素的排列規(guī)則。如果想單獨(dú)設(shè)置某一個(gè)子元素的布局規(guī)則,可以使用”align-self“。
比如給第二個(gè)article元素加上class.not-real
.not-real {
align-self: flex-end ;
}
效果如圖,在不影響其他元素的情況下,改變了.not-real。

5. flex-basis,flex-shrink,flex-grow
HTML
<body>
<h1 class="title-1">title1</h1>
<h1 class="title-2">title2</h1>
<h1 class="title-3">title3</h1>
</body>
CSS
body {
margin: 0;
font-family: 'Open Sans', sans-serif;
margin: 0;
color: #eec965;
display: flex;
}
.title-1 {
background: #dd5f40;
}
.title-2 {
background: #3d483a;
}
.title-3 {
background: #468e5d;
}
效果

5.1 flex-basis
flex-basis可以用來(lái)定義子元素在flex-direction方向上的最優(yōu)size。
比如先定義title1的width
.title-1 {
background: #dd5f40;
width: 200px
}

現(xiàn)在title1的寬度變?yōu)榱?00px
但如果加上
.title-1 {
background: #dd5f40;
width: 200px;
flex-basis: 150px;
}
title1的box寬度變成了150px。

flex-basis屬性覆蓋了width屬性(但flex-basis不會(huì)讓元素超過(guò)max-width或者小于min-width)。在flex-basis沒(méi)有規(guī)定值得情況下,默認(rèn)為auto。那么元素在flex-direction方向上的寬度,在這里就是指的width(因?yàn)檫@里的flex-direction是row),如果width沒(méi)有規(guī)定值,那么就默認(rèn)為元素的內(nèi)容寬度,這里就是title1這幾個(gè)字的寬度。
總之, Flex-basis就是在有足夠空間的情況下,flex-direction上的最優(yōu)寬度。
5.2 flex-grow
先給每個(gè)title都設(shè)定一個(gè)flex-basis:
.title-1 {
background: #dd5f40;
flex-basis: 120px;
}
.title-2 {
background: #3d483a;
flex-basis: 40px;
}
.title-3 {
background: #468e5d;
flex-basis: 100px;
}
現(xiàn)在在row方向上,很明顯是有剩余空間的。

此時(shí),flex-grow就決定了如何分配這些空間。沒(méi)有給值得時(shí)候,flex-grow默認(rèn)為0。
如果:
.title-1 {
background: #dd5f40;
flex-basis: 120px;
flex-grow: 1
}
現(xiàn)在title-1占用了全部的多余空間。

如果把titile2的flex-grow變成2,那么titile-1會(huì)占用總的多余空間的1/3,title2占用2/3。
5.3 flex-shrink
flex-shrink會(huì)定義當(dāng)總的flex-basis之和大于能夠被分配的空間時(shí),該如何縮減這些子元素。
默認(rèn)的flex-shrink值是1,意思是每個(gè)元素都同等份額的縮減寬度。
比如給title1,title2,title3的flex-basis都設(shè)為200px,當(dāng)總寬度小于600時(shí):
給title1的flex-shrink設(shè)為2,那么title1減少的寬度將是其他元素的2倍,但如果設(shè)為100,1000,并不會(huì)奏效,因?yàn)椴粫?huì)讓元素的寬度小于元素內(nèi)容的寬度。
如果不想讓元素的寬度因?yàn)榭倢挾鹊母淖兌鴾p少,可以給flex-shrink的寬度設(shè)為0,若將所有元素的寬度都設(shè)為0,那么為導(dǎo)致overflow。
5.4 flex-basis,flex-grow,flex-shrink的縮寫(xiě)規(guī)范
注釋部分寫(xiě)了該縮寫(xiě)對(duì)應(yīng)的flex-grow,flex-shrink,flex-basis。
.title-1 {
background: #dd5f40;
flex: 1;
/* flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
}
當(dāng)flex:1時(shí),flex-grow為1,flex-shrink為1(因?yàn)槭悄J(rèn)值),比較奇怪的是flex-basis此時(shí)為0(其默認(rèn)值應(yīng)該為auto)。
.title-2 {
background: #3d483a;
flex: 20px;
/* flex-grow: 1;
flex-shrink: 1;
flex-basis: 20px;
*/
}
flex:20px時(shí),很明顯只有flex-basis可以規(guī)定具體size。flex-grow是1,這也有點(diǎn)奇怪,因?yàn)閒lex-grow默認(rèn)值是0。
.title-3 {
background: #468e5d;
flex: 0 80px;
/* flex-grow: 0;
flex-shrink: 1;
flex-basis: 80px;
*/
}
當(dāng)先給一個(gè)無(wú)單位的值,再給一個(gè)有單位的值時(shí),flex-grow得到第一個(gè)值,flex-basis得到第二個(gè)值。flex-shrink保持默認(rèn)值。
其實(shí)最常用的方法還是,h1 { flex: 1; }這樣的縮寫(xiě)方式。這樣會(huì)讓所有元素同等的獲得多余空間,總是保持寬度一致且填滿空間。