現(xiàn)在大部分瀏覽器都支持flexbox布局方法。react和react-native中幾乎全部采用flex來布局。簡單總結(jié)下常用屬性供參考。
1. flex-direction 屬性
先以一個簡單的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會讓<ul>
這個容器成為一個具有flex功能的block-level容器,并且會影響到它的子元素的布局表現(xiàn)。
如果想讓<ul>
成為一個inline元素,可以寫成display: inline-flex
,這樣它仍然具有flex container的效果,同時也表現(xiàn)為一個inline元素,就像<img>
一樣。
當(dāng)加上display: flex;
后,<li>
元素由垂直排列變成了水平排列。這是因為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
這個屬性在用在響應(yīng)式web design上非常便利,配合media-query
可以根據(jù)屏幕大小,將元素從水平排列變成垂直排列。
需要注意的是flexbox屬性, 包括 flex-direction, 在有些瀏覽器上需要加prefixes,所以用之前一定要查查瀏覽器支持情況, can I use 這個網(wǎng)站就可以。還有個很方便的方法是用auto prefixer post CSS工具可以自動添加前綴,省去很多麻煩。
2. order屬性
先添加加上header,main和footer,為了明顯用背景色塊來區(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;
}
效果
然后將整個body都設(shè)為flex容器
body {
display: flex;
flex-direction: column;
}
此時,所有的flex元素默認(rèn)order都是0,所以會按照元素的順序來渲染,如果將某元素的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這個屬性會影響children沿著flex-direction
方向的排列和空間分配。當(dāng)前的flex-direction
是column
。所以這個屬性會影響子元素在從上到下的豎直方向上,如何分配多余空間,但是并不會改變元素本身的實際大小。
-
flex-start:
justify-content
默認(rèn)值是flex-start
,意思是所有元素都是從起始點開始向下排列。 - flex-end: 設(shè)成flex-end,可以看到子元素們會一起從結(jié)束點開始排列。
body {
display: flex;
flex-direction: column;
justify-content: flex-end;
}
效果:
- center: 設(shè)成center,他們就會一起擠在中間的位置,還記得剛開始學(xué)css的時候總是為如何才能實現(xiàn)真正的vertical-align苦惱,有了flexbox終于能非常簡單的實現(xiàn)了。
- space-between: 第一個元素在start位置,最后一個元素在end位置,中間元素均等間隙排列。
- space-around: 會平均分配剩余空間給所有元素間隙,但第一個元素的前面和最后一個元素的后面則是中間的間隙距離一半。
4. align-items 和 align-self
justify-content
是會影響子元素沿著flex-direction
方向的排列,而align-item則會影響子元素與flex-direction
方向垂直的方向上的排列情況。
為了更直觀的說明,將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;
}
- 這樣改之后會發(fā)現(xiàn),三個ariticle元素雖然內(nèi)容高度不同,但box都變成了100% height,這是因為align-items的默認(rèn)值是
stretch
,就是會用掉所有的垂直方向上的多余空間。
- 若將align-items的值設(shè)為”flex-start“,如圖,就會變成不同高度。
body {
display: flex;
flex-direction: row;
align-items: flex-start;
}
- 相似的還有 flex-end, center。
- 還有一個值是 baseline。就是根據(jù)首個元素的baseline來進(jìn)行對齊。
align-items是用于container的屬性,統(tǒng)一設(shè)置子元素的排列規(guī)則。如果想單獨設(shè)置某一個子元素的布局規(guī)則,可以使用”align-self“。
比如給第二個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可以用來定義子元素在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不會讓元素超過max-width或者小于min-width)。在flex-basis沒有規(guī)定值得情況下,默認(rèn)為auto。那么元素在flex-direction方向上的寬度,在這里就是指的width(因為這里的flex-direction是row),如果width沒有規(guī)定值,那么就默認(rèn)為元素的內(nèi)容寬度,這里就是title1這幾個字的寬度。
總之, Flex-basis就是在有足夠空間的情況下,flex-direction上的最優(yōu)寬度。
5.2 flex-grow
先給每個title都設(shè)定一個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方向上,很明顯是有剩余空間的。
此時,flex-grow就決定了如何分配這些空間。沒有給值得時候,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會占用總的多余空間的1/3,title2占用2/3。
5.3 flex-shrink
flex-shrink會定義當(dāng)總的flex-basis之和大于能夠被分配的空間時,該如何縮減這些子元素。
默認(rèn)的flex-shrink值是1,意思是每個元素都同等份額的縮減寬度。
比如給title1,title2,title3的flex-basis都設(shè)為200px,當(dāng)總寬度小于600時:
給title1的flex-shrink設(shè)為2,那么title1減少的寬度將是其他元素的2倍,但如果設(shè)為100,1000,并不會奏效,因為不會讓元素的寬度小于元素內(nèi)容的寬度。
如果不想讓元素的寬度因為總寬度的改變而減少,可以給flex-shrink的寬度設(shè)為0,若將所有元素的寬度都設(shè)為0,那么為導(dǎo)致overflow。
5.4 flex-basis,flex-grow,flex-shrink的縮寫規(guī)范
注釋部分寫了該縮寫對應(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時,flex-grow為1,flex-shrink為1(因為是默認(rèn)值),比較奇怪的是flex-basis此時為0(其默認(rèn)值應(yīng)該為auto)。
.title-2 {
background: #3d483a;
flex: 20px;
/* flex-grow: 1;
flex-shrink: 1;
flex-basis: 20px;
*/
}
flex:20px時,很明顯只有flex-basis可以規(guī)定具體size。flex-grow是1,這也有點奇怪,因為flex-grow默認(rèn)值是0。
.title-3 {
background: #468e5d;
flex: 0 80px;
/* flex-grow: 0;
flex-shrink: 1;
flex-basis: 80px;
*/
}
當(dāng)先給一個無單位的值,再給一個有單位的值時,flex-grow得到第一個值,flex-basis得到第二個值。flex-shrink保持默認(rèn)值。
其實最常用的方法還是,h1 { flex: 1; }
這樣的縮寫方式。這樣會讓所有元素同等的獲得多余空間,總是保持寬度一致且填滿空間。