css3 flexbox layout(彈性佈局)完全解析

一、背景

Flextbox Layout(彈性盒佈局或伸縮盒佈局),提供了一種更加有效的方式去佈局、對齊和給容器中的子元素分配空間,即使他們的尺寸未知或者是動態改變的。 看看裏面有個flex就能想象出來。

Flexbox layout背後的設計理念:賦予容器去改變他的子元素的寬、高、排列順序的能力,從而可以更好的填充可用空間,尤其對各種各樣的設備和屏幕尺寸提供了便利的方式去佈局。一個具有flex特性的容器可以去拉伸他的子元素去填充可用的自由空間,也可以收縮他的子元素防止溢出。

​ 更重要的一點,flextbox layout 的佈局方向也是不固定的。這點與我們以前的佈局是不同的。比如:block是垂直佈局的,而inline是水平佈局的。 對那些可以工作良好的頁面來說,他們在支持龐大或者複雜的應用方面缺乏靈活性。尤其當面對設備的方向、尺寸、縮放等等方面發生改變的時候,這種缺點更加明顯。

二、基本知識

flexbox是一個完整的模塊,而不是一個單一的屬性。

flexbox加入了大量的屬性。這些屬性一部分用在容器上(父元素,一般稱之爲 flex container),而另外的一些是用在子元素上(一般稱之爲 flex items. 彈性項目)。

下面介紹一些基本概念:

這張圖來自w3c規範。

一般情況下,flex itmes 要麼沿着 main axis 佈局(從主軸起點到主軸重點),要麼沿着 cross axis 佈局(從側軸起點到側軸重點)。

  • 主軸(main axis) : 彈性容器的主軸是最主要的軸,flex items會沿着這條軸被佈局。有一點需要注意:主軸不一定總是水平的,他的方向由 flex-direction 屬性的值來決定。(後面後細講)
  • 主軸起點(main start)和主軸終點(main end):彈性容器中的 flex items 會從 主軸起點 開始 到主軸重點結束 佈局。
  • 主軸長度(main size):flex item的寬或高就是主軸長度。到底是寬還是高,由誰沿着主軸的方向來決定。
  • 側軸(cross axis):垂直於主軸的軸就是側軸。側軸的方向由主軸來決定。
  • 側軸起點(cross start )和側軸終點(cross end):彈性行(flex lines)從側軸起點開始到側軸重點結束。
  • 側軸長度(cross size):伸縮項目的在側軸方向的寬度或高度就是項目的側軸長度,伸縮項目的側軸長度屬性是「width」或「height」屬性,由哪一個沿着着側軸方向決定。

三、flex container的屬性

3.1 display

​ 這個屬性把一個元素定義成爲 flex container。可以設置爲 flexinline-flex。設置爲flex容器就是塊級容器,設置爲 inline-flex 就是行內元素。 這個容器就會成爲他們的直接子元素的 flex context

.container {
    display: flex; /* or inline-flex */
}

3.2 flex-direction

​ 這個屬性創建主軸,定義了 flex items 在彈性容器中佈局的方向。主軸要麼水平方向,要麼垂直方向。

.container {
    flex-direction: row | row-reverse | column | column-reverse;
}
  • row : 主軸水平,方向從左向右。(默認值)
  • row-reverse:主軸水平,方向從右向左
  • column : 主軸垂直,方向從上向下
  • column-reverse:主軸垂直,方向從下向上

3.3 flex-wrap

​ 默認情況下,所有的flex items 都會試圖在一行。通過修改這個屬性的值,可以讓 flex items按照要求多行排列。其實這個屬性可以定義 flex items 在側軸方向的排序方式。

.container{
  flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap :所有的 flex items 在一行。(默認值)
  • wrap :允許 flex items 自動換行在多行,方向是從上向下。
  • wrap-reverse : 允許 flex items 自動換行在多行,方向是從下向上。

html:

<div class='container'>
    <p></p>
    <p></p>
    <p></p>
    <p></p>
</div>

css:

* {
  margin: 0;
  padding: 0;
}

.container {
  display: flex;
  width: 700px;
  height: 500px;
  background-color: gray;
  flex-direction: row;
  flex-wrap: nowrap;
}
p{
  width : 200px;
  height : 200px;
  background-color : pink;
}
p:nth-child(2n){
  background-color: cornflowerblue;
}

效果1:

效果2:

效果3:

效果4:

效果5:

效果6:

3.4 flex-flow

flex-flowflex-directionflex-wrap兩個屬性的合併簡寫方式。一次性的定義了主軸和側軸,他的默認值是:row nowrap

flex-flow: <‘flex-direction’> || <‘flex-wrap’>

3.5 justify-content

​ 該屬性定義了主軸方向flex items的對齊方式。也能把多餘的自由空間,分配給flex-items

.container {
    justify-content: flex-start | flex-end | center | space-between | space-around;
}
  • flex-start:flex-items從主軸起點開始排列。

  • flex-end:flex-items從主軸終點開始排列。

  • center:flex-items在主軸方向居中排列。

  • space-between:把 free space 平局分佈在 flex-items之間。第一個 item緊挨着主軸起點,最後一個item緊挨着主軸終點。

  • space-around:把 free space平均分佈在每個item的周圍。所以中間空白會比邊上的空白大一倍。

3.6 align-items

​ 該屬性定義了flex-items在側軸上的對齊方式。可以看成是justify-content在側軸上的版本。

如果是單行flex-items的情況使用比較好

.container {
    align-items: flex-start | flex-end | center | baseline | stretch;
}
  • flex-start:從側軸起點開始排列
  • flex-end:從側軸的終點開始排列
  • center:沿着側軸方向居中
  • baseline:沿着內容的基線對齊
  • stretch:在側軸方向拉伸flex-items(默認值)。但是他的優先級比設定了具體的heigthmax-height低,但是比auto高。

3.7 align-content

​ 該屬性定義了當有多行flex items時,free-space如何分佈,類似於主軸的justify-content

.container {
    align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
  • flex-start:從側軸起點開始排列
  • flex-end:從側軸的終點開始排列
  • center:沿着側軸方向居中
  • stretch:在側軸方向拉伸flex-items(默認值)。但是他的優先級比設定了具體的heigthmax-height低,但是比auto高。
  • space-between:把 free space 平局分佈在 flex-items之間。第一個 item緊挨着側軸起點,最後一個item緊挨着側軸終點。
  • space-around:把 free space平均分佈在每個item的周圍。所以中間空白會比邊上的空白大一倍。

四、flex-items的屬性

4.1 order

​ 默認情況下,flex-items安裝源碼的屬性佈局。然後,通過 order屬性可以改變他們在彈性容器中的出現的順序。

.item {
    order: <integer>;
}

order的默認默認值是 0 。值越大,佈局越靠後; 反之,越小,佈局越靠前。

.child:nth-child(2){
    order: 2;
}
.child:nth-child(3){
    order: 1;
}

4.2 flex-grow

​ 該屬性設置 flex-item 在主軸方向,有空餘空間的時候可以佔據空餘空間。他的值是一個沒有單位的值,表示佔據空餘空間的比例。

默認值是 0。負值無效

.item {
    flex-grow: <number>; /* default 0 */
}

比如:

  1. 如果有2個item都設置爲 1, 則他們會把剩餘的平分, 因爲分別是: 1 / (1 + 1) * 剩餘空間、1 / (1 + 1) * 剩餘空間

  2. 如果3個item 分別設置爲 2、1、3 。則他們分別分的剩餘空間的 2 / (2 + 1 + 3) * 剩餘空間、1 / (2 + 1 + 3)* 剩餘空間、3 / (2 + 1 + 3)* 剩餘空間

總結: flex-grow / 所有的flex-grow只和 * 剩餘空間

.item:nth-child(1){
    flex-grow: 1;
}
.item:nth-child(2){
    flex-grow: 1;
}

.item:nth-child(1){
    flex-grow: 1;
}
.item:nth-child(3){
    flex-grow: 2;
}

4.3 flex-shrink

​ 該屬性讓 flex-item具有收縮的功能。當一行放不下,並且不允許換行的時候,允許 flex-item收縮。

​ 值是一個整數,來表示收縮比率。默認值是1。 如果是0表示不允許收縮。

一行放不下的時候,其實表示的是剩餘空間爲負,計算方法同 flex-grow是一樣的,只是現在是減去響應的值而已(加負)

.container{
  height : 200px;
  width: 600px;
  background-color : gray;
  display: flex;
}
.item{
    height:100px;
    width: 300px;
    background-color: pink;
    margin: 50px 0 0 0px;

    font-size: 60px;
    text-align: center;
    line-height: 100px;
}
.item:nth-child(2n){
    background-color: cornflowerblue;
}
.item:nth-child(1){
    flex-shrink: 2;
}
.item:nth-child(3){
    flex-shrink: 3;
}

計算:

剩餘空間: 600 - 3 * 300 = -300

剩餘空間每份: -300 / (2 + 1 + 3) = -50

item1寬度: 300 - 50 * 2 = 200

item1寬度: 300 - 50 * 1 = 250

item1寬度: 300 - 50 * 3 = 150

4.4 flex-basis

​ 這個屬性指定在剩餘空間分配之前,flex-item的尺寸。

.item {
    flex-basis: <length> | auto; /* default auto */
}
  • 可以指定具體的長度 px、em、百分比
  • auto:意思是參考這個item的寬或高。 默認值是auto
.container{
    width: 900px;
    display: flex;
}
.item{
  width: 200px;
  background-color: pink;
}
.item:nth-child(1){
  flex-grow: 1;
  flex-basis: auto;  // 
}
.item:nth-child(3){
  flex-grow: 1;
  flex-basis: 60px;  // 
}

剩餘空間: 900 - 200 - 200 - 60 = 440

item1 : 200 + 220 = 420

item2:200

item3:60 + 220 = 280

4.5 flex

​ 是flex-grow、flex-shrink、flex-basis的簡寫。 flex-shrink、flex-basis這2個參數是可選的。 默認值是:0 1 auto

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

強烈建議使用這個簡寫的形式來代替3個獨立的屬性。 簡寫可以智能設置其他的值。

4.6 align-self

​ 單獨的設置某個 item 的對齊方式,來覆蓋align-items或align-content。

.container {
    height: 200px;
    width: 900px;
    background-color: gray;
    display: flex;
    align-items: flex-start;
}
.item:nth-child(3) {
  flex-grow: 1;
  flex-basis: 0px;
  align-self: flex-end;
}

參考文章:

flexbox 完全指導

w3c規範

發佈了79 篇原創文章 · 獲贊 375 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章