flex 是經常使用的 css3 佈局方式,能夠用少許的代碼高效的實現各類頁面佈局,是一個基礎的可是必須會的基本技能,在面試中常常會用到。css
例如,最基本的讓你實現元素的水平/垂直居中,或在這個基礎上延伸出更多其餘複雜一些的問題。html
下面咱們先簡單的認識一下 flex,瞭解一下 flex 有哪些屬性,再結合示例對每個屬性進行講解,進一步瞭解 flex 的使用,掌握每個屬性的做用。屬性比較多,配合使用能夠實現各類各樣的佈局,爲了篇幅不過於冗餘,不會過多的舉例。前端
若是您以前還沒掌握 flex 佈局,但願你在看這篇文章時,能夠邊看邊動手實現每一個例子,並嘗試更多的排列組合實現不一樣的效果,加深印象。並在之後運用到實際項目中,這樣才能真正掌握好這個技能。ios
若是您已經掌握 flex 佈局,也但願能幫你溫習溫習,加深記憶。css3
有時候隔一段時間沒使用,可能會忘記某個屬性的做用,回過頭再看一下這篇文章,能夠快速喚起記憶。git
歡迎一塊兒學習交流,若有錯漏歡迎指出^_^。github
Flex 全稱 Flexible box 佈局模型,一般稱爲 flexbox 或 flex,也稱爲彈性盒子或彈性佈局。一種比較高效率的 css3 佈局方案。面試
既然是盒子,首先須要一個容器 container,而後是項目 item。容器包裹着項目,再經過配置不一樣的屬性,實現各類各樣的排列分佈。算法
flex 有兩根軸線,分別是主軸和交叉軸,主軸的方向由 flex-diretion
屬性控制,交叉軸始終垂直於主軸。瀏覽器
容器爲項目的分佈提供的空間,軸線則控制項目的排列跟對齊的方向, flex 是一種一維的佈局,一個容器只能是一行(左右)或者一列(上下),經過主軸控制項目排列的方向(上下/左右),交叉軸配合實現不一樣的對齊方式。有時候一行放不下,能夠實現多行的佈局,可是對於 flex 來講,新的一行就是一個新的獨立的 flex 容器。做爲對比的是另一個二維佈局 CSS Grid 佈局,能夠同時處理行和列上的佈局。
當使用 flex 佈局時,首先想到的是兩根軸線 — 主軸(Main Axis)和交叉軸(Cross Axis)。主軸由 flex-direction
定義,交叉軸垂直於主軸。
理解主軸和交叉軸的概念對於對齊 flex 裏面的項目是很重要的,flexbox 的特性是沿着主軸或者交叉軸對齊之中的項目,接下來要學習掌握的 flex 的全部屬性都與這兩根軸線有關,必需要理解它。
主軸方向,箭頭的起始位置的容器邊緣線就是對應軸的起始位置,同理重點位置的容器邊緣線對應軸的終點位置。交叉軸垂直於主軸,主軸是
row/row-reverse
-水平方向的時候,交叉軸的起始位置是頂部邊緣,結束位置是底部邊緣線。主軸是column/column-reverse
- 垂直方向的時候,交叉軸的起始位置是容器的左邊邊緣線,結束位置是右邊邊緣線。
flex 必須有一個容器 container,跟多個子元素 item。
當把一個元素的 display
屬性設置爲 flex
或者 inline-flex
後,它就成了一個容器。
flex
與 inline-flex
的關係就相似 block
與 inline-block
的關係,定義裏容器是行內元素仍是塊級元素。
元素變成容器後,就會有一些默認的行爲,若是如今看不懂,先大概有個印象:
block
、 float
、clear
和 vertical-align
屬性都失效。由於項目的排列對齊方式已經變成由 flex 屬性控制。flex 屬性有默認值,後面會詳細說明每一個屬性的做用與默認值。flex-direction
屬性的初始值是 row
)。下面是一個簡單的例子:
<div class="container"> <div class="item">元素一</div> <div class="item">元素二</div> <div class="item">元素三</div> </div> <style> .container { display: flex; width: 300px; // 把容器寬度設置爲 300px;沒有設置高度。 } .item { width: 150px; // 每一個項目寬度爲 150px,加起來大於 300px line-height: 100px; // 設置項目默認撐開的高度爲 100px } .container :nth-child(1) { background-color: #E3ABB3; height: 100px; // 第一個項目給定固定高度 100px; } .container :nth-child(2) { background-color: #9DC54B; } .container :nth-child(3) { background-color: #1FBEE7; height: 300px; } </style>
上面例子展現了 設置爲 flex 後的容器的一些變化。
基於上面這些默認行爲,有的同窗可能會有疑問。
若是不想從左到右,想從右到左怎麼辦?(常見的需求)
若是不想項目自動縮小,想換行怎麼辦?(常見的需求)
若是不想頂部對齊,想垂直居中怎麼辦?
…
帶着這些問題,來看看 flex 是怎麼實現的。
與 Flex 有關的屬性,主要包括如下幾個:
flex-direction
</font> - 用於指定主軸的方向,有4個經常使用選項 row
、row-reverse
、 colunm
、colunm-reverse
。row
是行(與 inline
行爲一致,從左向右 → ),colunm
是列(與 block
行爲一致,從上到下 ↓
)。帶上 reverse
的是指反向,即原來 row
是左右 →
,row-reverse
就是右左 ←
,column
是上下 ↓
,則 column
就是下上 ↑
。flex-wrap
</font> - 用於指定項目太多超過一行的時候是否換行。默認 flex-wrap: nowrap;
不換行。flex-flow
</font> - 是 flex-direction
和 flex-wrap
的合併簡寫。flex-flow: <flex-direction> <flex-wrap>;
justify-content
</font> - 用於控制項目在主軸上的對齊方式。默認是 justfy-content: flex-start;
,主軸起始線對齊。align-items
</font> - 用於控制項目在交叉軸上的對齊方式。默認是 align-items:stretch;
,若是項目沒有設置高度,則拉伸填充到容器一樣高度,若是設置了高度則頂部對齊。align-content
</font> - 用於控制多根軸線(多行)在交叉軸上的對齊方式。flex-grow
</font> - 用於控制項目在主軸方向上拉伸放大佔剩餘空間(若是有的話)的比例。默認是 flex-grow: 0
,不拉伸。flex-shrink
</font> - 用於控制項目在主軸方向上縮小的程度。默認是 flex-shrink: 1
,同等比例收縮。數值越大,收縮越多。flex-basis
</font> - 用於初始化項目佔據主軸空間的尺寸,默認是 flex-basis: auto;
,自動檢測尺寸,若是項目有設置,則取項目設置的值,不然根據項目內容計算出尺寸。flex
</font> - 是上面三個合併的簡寫 flex: <flex-grow> <flex-shrink> <flex-basis>;
。align-self
</font> - 控制項目自己在交叉軸上的對齊方式。優先級高於 align-items
。默認是 align-self: auto;
,意思是使用 align-items
設置的值。比 align-items
多一個 auto
選項,其餘選項與 align-items
一致。order
</font> - 用於控制項目在主軸上的排列順序。默認是 0 ,所有項目按主軸方向依次排列。設置後,按數值大小,從小到大排列。接下來是每一個屬性的使用說明
如下面代碼爲例子:
<div class="container"> <div class="item">元素一</div> <div class="item">元素二</div> <div class="item">元素三</div> <div class="item">...</div> </div> <style> .container { display: flex; border: 1px dashed #666666; text-align: center; width: 400px; // 把容器寬度設置爲 400px;沒有設置高度。 } .item { width: 100px; // 每一個項目寬度爲 150px,加起來大於 300px line-height: 100px; // 設置項目默認撐開的高度爲 100px } .container :nth-child(1) { background-color: #E3ABB3; } .container :nth-child(2) { background-color: #9DC54B; } .container :nth-child(3) { background-color: #1FBEE7; } </style>
flex-direction
在前面介紹軸線的時候就提到這個,direction 是方向,指向的意思,因此這個屬性主要用於改變軸線的方向。也就是項目的排列方向。
flex-direction
有 4 個經常使用選項值。
.container { flex-direction: row | row-reverse | column | column-reverse; }
默認值:flex-direction: row;
。
row
與 row-reverse
是水平方向,cloumn
與 cloumn-reverse
是垂直方向。 reverse 是顛倒、相反的意思,因此帶 reverse 的總與不帶的方向相反。
注:下面例子中項目未超出容器,白色格子假設表示容器「剩餘的空間」,這裏講剩餘空間是爲了方便理解,實際上這個空間被叫作 positive free space ,若是項目超出的容器空間,溢出的部分叫作 negative free space。
row
:默認值,主軸方向爲水平方向,從左向右排列,起始位置是容器的左邊線;row-reverse
:主軸方向是水平方向,從右向左排列,起始位置是容器的右邊線;column
:垂直方向,從上到下排列,其實位置是容器的上邊線;column-reverse
:垂直方向,從下到上排列,起始位置是容器是下邊線;flex-wrap
有 3 個經常使用選項值,用於指定項目太多超過一行的時候是否換行。
.container { flex-wrap: nowrap | wrap | wrap-reverse; }
默認值: flex-wrap: nowrap;
不換行。
設置值爲 wrap
時,若是一行放不下全部項目的時候,就會自動在換行顯示,新的一行的一個新的容器。若是 flex-direction
屬性爲 row
,則建立新行、若是爲 column
則建立新列。
設置值爲 wrap-reverse
,也會換行,加上 reverse 後,換行的方向與原來相反。
接下來在上面的例子多加幾個項目,來測一下flex-wrap
的效果,例子以flex-deriction: row;
水平方向試驗,可自行測試其餘方向下的行爲,加深理解。
nowrap
:默認值,項目沒有換行,項目總寬度超過容器,自動縮小寬度。wrap
:項目換行,新的一行在第一行項目的下方。wrap-reverse
:項目換行,新的一行在第一行項目的上方。這裏能夠試試把容器的高度設置爲高於項目的高度,看看wrap
和wrap-server
在交叉軸方向上的怎麼對齊的~能夠試試把
flex-direction
設置爲column
看看有什麼不一樣~
是 flex-direction
和 flex-wrap
的合併簡寫。
.container { flex-flow: <flex-direction> <flex-wrap>; }
默認是 flex-flow: row nowrap;
例如
flex-flow: column wrap; // 至關於 flex-direction: column; flex-wrap: wrap;
justify 翻譯過來是「使每行排齊、使齊行」,content 翻譯過來是「內容」。合在一塊兒大概意思就是使行的內容對齊的意思。因此,justify-content
是用於控制項目在主軸上的對齊方式。
有 6 個經常使用選項。
.container { justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly; }
默認值: justify-content: flex-start;
flex-start
:默認值,項目在主軸方向上,以主軸起始位置對齊。圖例中主軸方向是從左到右,起始位置是容器的左邊線,能夠看到項目是左邊對齊的。flex-end
:項目在主軸方向上,以主軸結束的位置對齊。圖例中結束位置是容器的右邊線,因此是右邊對齊。center
:項目在主軸方向上居中。space-between
:項目在主軸方向上,兩端對齊,而後項目中間間隔是相等的。space-around
:在主軸方向上,剩餘的空間被平均的分配到每一個項目的兩側。space-evenly
:在主軸上,剩餘空間平均分配,與 space-between
不一樣的是,between 是在項目之間,而 evenly 是在軸的最左邊和最右邊也一樣會有空間分配。如下是我我的的理解,爲了加深對這些參數的印象,你能夠參考,也能夠按你本身的方式理解記憶。space 是「空間」的意思,between 是「在...之間」的意思,因此,能夠看到
space-between
剩餘的空間平均的分配在每一個項目之間。around 是「四周、圍繞」的意思。每一個項目左右兩邊都會分配到相等的空間,而且項目與項目之間的空間獨立不合並。圖例中,「元素一」左邊只有圍繞它自己的空間,而右邊有「元素二」、「元素三」的空間,因此右邊空間是左邊的兩倍。以此類推,在中間的項目的間隔都是「兩倍」,直到最後一個項目的右邊空間又是「一倍」。
evenly 是「平均、均勻」的意思,因此,剩餘的空間是均勻分配的。
假設項目是 n 個,
space-between
兩端沒有分配空間,只有項目之間的間隔有分配,空間平均分配 n-1 份,分配在項目與項目之間。space-evenly
兩端也有,空間平均分配 n+1 份。space-around
是兩側都有,空間平均分配 2n 份。
align-items
是控制項目在交叉軸上的對齊方式。
有 5 個經常使用選項。
.container { align-items: stretch | flex-start | flex-end | center | baseline; }
默認值:align-items: stretch;
stretch
:默認值,若是項目沒有設置固定高度,則會被拉伸填充滿交叉軸方向剩餘的空間。flex-start
:項目在沿交叉軸起始線位置對齊。flex-end
:項目沿交叉軸終點線位置對齊。center
:項目在交叉軸方向居中對齊。baseline
:項目在交叉軸方向沿項目中第一行文字的基線對齊。這個也比較好理解,stretch 是「拉伸,拉長」的意思,因此項目會被拉伸。這裏若是項目設置了固定高度,會沿交叉軸的起始位置對齊。start、end、center 分別的「起始」、「終點」、「中間」的意思,因此項目分別是起始位置、終端位置、居中對齊。
baseline 是「基線、底線」的意思,這裏是沿文字的基線對齊的意思。
align-content
控制多行項目(多根主軸線)對齊方式。相似 justify-content
,只不過,align-content
是控制行與行之間的空間分配,justify-content
是控制項目與項目之間的空間分配。
有 7 個經常使用的選項。
.container { align-content: stretch | flex-start | flex-end | center | space-between | space-around | space-evenly; }
默認值:align-content: stretch;
<div class="container"> <div class="item">元素一</div> <div class="item">元素二</div> <div class="item">元素三</div> <div class="item">元素四</div> <div class="item">元素五</div> <div class="item">元素六</div> <div class="item">元素七</div> <div class="item">元素八</div> <div class="item">元素九</div> </div> <style> .container { border: 1px dashed #666666; margin: 100px auto; display: flex; width: 150px; height: 250px; text-align: center; flex-direction: row; flex-wrap: wrap; /* flex-flow: column wrap; */ /* justify-content: flex-start; */ /* align-items: stretch; */ align-content: stretch; } .item { width: 50px; // 項目寬度爲 50px } .container :nth-child(1) { background-color: #E3ABB3; height: 50px; } .container :nth-child(2) { background-color: #9DC54B; } .container :nth-child(3) { background-color: #1FBEE7; } .container :nth-child(4) { background-color: #218BCC; height: 50px; } .container :nth-child(5) { background-color: #6695D3; } .container :nth-child(6) { background-color: #CFD841; } .container :nth-child(7) { background-color: #F1B605; } .container :nth-child(8) { background-color: #E3ABB3; } .container :nth-child(9) { background-color: #9DC54B; height: 50px; } </style>
上面圖例中「元素1、5、九」設置了固定的高度。其餘項目高度自動識別。由於
align-items
的默認值的效果,其餘項目會被拉伸填充到與行的高度同高。
stretch
:默認值,交叉軸方向剩餘的空間平均分配到每一行,而且行的高度會拉伸,填滿整行的空間。圖例中,由於 align-items
默認值的效果,第一行高度本來是以最高的「元素一」的高度爲行的高度。而後又由於 align-content
的效果,拉伸了行的高度。而其中,「元素一」設置了固定高度,因此沒有被拉伸,「元素2、三」沒有設置高度,因此被拉伸填充到與行一樣的高度。flex-start
:全部行在交叉軸方向上,以交叉軸的起始位置對齊。flex-end
:全部行在交叉軸方向上,以交叉軸的終點位置對齊。center
:全部行在交叉軸上居中對齊。space-between
:行在交叉軸方向上,兩端對齊,而後行中間的間隔相等。space-around
:在交叉軸方向上,剩餘的空間被平均的分配到每一行的兩側。space-evenly
:在交叉軸方向上,剩餘空間平均分配,與 space-between
不一樣的是,between 是在行之間,而 evenly 是在軸的最左邊和最右邊也一樣會有空間分配。flex-grow
用於控制項目在主軸方向上拉伸放大佔剩餘空間(若是有的話)的比例。
grow 的意思是「擴大,使生長」,因此就是讓項目放大的意思。
.item { flex-grow: <number>; }
默認值:0
,不放大。
例子中,容器寬設爲 300px,項目寬設爲 50px。項目總寬 150px,剩餘空間寬 150pxflex-grow 都設置爲 1 的時候,項目拉伸成 100px,剩餘空間被按 1:1:1 分配,每一個項目各佔了 1/3。
flex-grow 分別設爲 3三、6六、66 的時候,項目分別被拉伸成 87.5px、125px、87.5px,剩餘空間被按 1:2:1 分配,項目分別佔了剩餘空間的 1/四、1/二、1/4。
能夠看到,放大的比例跟數值的大小無關,跟數值的比例有關。
flex-shrink
用於控制項目在主軸方向上縮小的程度。數值越大,收縮越多。但它與 flex-grow
不同,不是按比例收縮的,具體的收縮算法原理能夠參考 控制Flex子元素在主軸上的比例。
shrink 是「收縮、縮小」的意思,因此就是讓項目縮小的意思。
.item { flex-shrink: <number>; }
默認是 flex-shrink: 1
,同等比例收縮。
例子中,容器寬爲 400px,項目寬爲100px。由於項目超過了容器空間,因此自動被縮小了。默認 flex-shrink 是 1,全部項目同等比例縮小成 80px。右上,設置 flex-shrink,所有設置爲 0,項目保存原來設置的寬度 100px,不縮小,因此溢出容器空間。
右中,設置 flex-shrink 分別爲 六、六、六、默認、默認,項目寬變成 70px、70px、70px、95px、95px,超出的 100px 分紅 20 份,按比例縮小。
右上,設置 flex-shrink 分別爲 99九、默認、默認、默認、默認,項目寬變成 16px、96px、96px、96px、96px,能夠看到這裏就不按比例縮小的了。
flex-basis
用於初始化每一個項目佔據主軸空間的尺寸(main size)。
.item { flex-basis: <length> | auto; }
默認值:flex-basis: auto
, 自動檢測尺寸,若是項目有設置尺寸,則取項目設置的值,不然根據項目內容計算出尺寸。
能夠像設置width
,height
同樣設置flex-basis
flex
是上面三個合併的簡寫。
.item { flex: <flex-grow> [<flex-shrink>] [<flex-basis>]; }
默認值:flex: 0 1 auto;
後兩個參數爲可選參數。
這個屬性預約義瞭如下幾種簡寫形式:
flex: initial
:等同於 flex: 0 1 auto
。默認值。這裏 flex-grow
爲 0
, 因此項目默認不會拉伸,不會超出自己的 flex-basis
尺寸。flex-shrink
爲 1
,因此項目能夠縮小,防止它們溢出。flex-basis
爲 auto
,能夠是手動設置的尺寸也能夠自動根據內容計算出尺寸。flex: auto
:等同於 flex: 1 1 auto
。能夠拉伸,能夠縮小,自動計算項目尺寸,通常狀況下會自動拉伸填充滿整個容器。flex: none
: 等同於 flex: 0 0 auto
。不能拉伸,不能縮小,直接使用獲取到項目的 flex-basis
尺寸。flex: <positive-number>
:等同於 flex: <positive-number> 1 0
。positive-number 爲正數,例如 flex: 1
等同於 flex: 1 1 0
。#### flex 項目的屬性:align-self
align-self
控制項目自己在交叉軸上的對齊方式。優先級高於 align-items
。align-items
是容器統一控制容器裏的每一個項目的對齊方式,align-self
則是項目控制項目自己的對齊方式。
.item { align-self: auto | flex-start | flex-end | center | baseline | stretch; }
默認值:align-self: auto;
,繼承容器設置的 align-items
的值。也就是默認是由容器設置 align-items
統一控制項目在交叉軸上的對齊方式。
除了比 align-items
多一個 auto
選項外,其餘選項與 align-items
一致。
.container { dispaly: flex; align-items: flex-start; // 容器控制全部項目頂部對齊排列 } .item.four { align-self: flex-end; // 第四個項目控制底部對齊 }
order
用於控制項目在主軸上的排列順序。
.item { order: <number>; }
默認值: order: 0;
,參數值正負數均可以,所有項目按主軸方向依次排列。設置後,按數值大小,從小到大排列。
space-between
兩端對齊,最後一行不對齊問題
這是一種經常使用的佈局方式,可是最後一行大部分時候,咱們是但願他從左到右排列,而不是兩端對齊
解決方案:使用 after 僞元素,把寬設置成與 item 同樣
.conatainer::after { content: ""; width: 50px; /* height: 50px; */ // 若是給僞元素設置高和背景色,能夠看到它的做用。 /* background-color: #eeeeee; */ }
原理是,使用 after 僞元素模擬了最後一個項目,僞裝多了一個項目,佔着最後一個位置。若是給僞元素設置高和背景色,能夠看到它的做用。但這個方法有個明顯的缺點,只適合每行三個項目。超過三個項目就不行了。
space-evenly
兼容性問題上面提到的 justify-content: space-evenly;
對齊方式,這個方式有個明顯的缺點,就是兼容性較差。
當使用的環境中須要兼容較多瀏覽器的時候,能夠考慮如下方案。
.container { display: flex; justify-content: space-between; } .container::after, .container::before { content: ''; display: block; }
使用 after 僞元素,在容器兩端模擬兩個長度爲 0 的項目,就能實現 evenly 一樣的效果。缺點是隻適合一行的佈局。
<header>header</header> <div id='main'> <article>article</article> <nav>nav</nav> <aside>aside</aside> </div> <footer>footer</footer> <style> body { font: 24px Helvetica; } #main { min-height: 500px; margin: 0px; padding: 0px; display: flex; flex-flow: row; } #main > article { margin: 4px; padding: 5px; border: 1px solid #cccc33; border-radius: 7pt; background: #dddd88; flex: 3 1 60%; order: 2; } #main > nav { margin: 4px; padding: 5px; border: 1px solid #8888bb; border-radius: 7pt; background: #ccccff; flex: 1 6 20%; order: 1; } #main > aside { margin: 4px; padding: 5px; border: 1px solid #8888bb; border-radius: 7pt; background: #ccccff; flex: 1 6 20%; order: 3; } header, footer { display: block; margin: 4px; padding: 5px; min-height: 100px; border: 1px solid #eebb55; border-radius: 7pt; background: #ffeebb; } /* 窄到已不足以支持三欄 */ @media all and (max-width: 640px) { #main, #page { flex-direction: column; } #main > article, #main > nav, #main > aside { /* 恢復到文檔內的天然順序 */ order: 0; } #main > nav, #main > aside, header, footer { min-height: 50px; max-height: 50px; } } </style>
參考文檔:MDN flex 佈局文檔
掃下方二維碼或微信搜索,關注公衆號「天才前端計劃」,回覆 「前端面試5」 獲取資源連接。
視頻來自互聯網,僅供我的學習。
謝謝您的支持^_^