1. 程式人生 > 實用技巧 >Flex佈局學習記錄

Flex佈局學習記錄

Flex佈局學習記錄


Flex佈局學習參考了知乎—— 《30 分鐘學會 Flex 佈局》

Flex佈局的優勢

簡單且十分靈活,簡單的幾行程式碼就實現各式各樣的頁面佈局。

Flex基本概念


flex的容器中預設存在兩條軸,水平主軸(main axis)和垂直交叉軸(cross axis)。預設設定中以水平軸作為主軸,可以通過修改使得垂直方向成為主軸,水平方向成為交叉軸。

在容器中的每個專案被稱之為flex item,每個專案佔據的主軸空間為:main size,佔據的交叉軸空間為:cross size。

需要注意的是,不能直接把寬當作是main size,高當作是cross size,這個需要取決以你的主軸方向。如果你的主軸是垂直方向為主軸,那麼高度就是main size。

Flex容器


實現flex佈局需要現指定一個容器,任何一個容器都可以被指定為flex佈局,這樣容器內部的元素都可以使用flex佈局。

.container {
    display: flex|inline-flex	//兩種都可以
}

生成一個專案狀或者行內的flex容器。簡單來說,如果使用專案元素如div,就可以使用flex,而如果使用行內元素,可以使用inline-flex。

有六種屬性可以設定在容器上:

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

1.flex-direction

決定主軸的方向。

.container {
    flex-dircetion: row|row-reverse|column|column-reverse
}
  • 預設值為:row,即主軸為水平方向,左端為起點

  • row-reverse:主軸為水平方向,row的翻轉,起點在右端

  • column: 主軸為垂直方向,起點在上沿

  • cloumn-reverse:主軸為垂直方向,column的翻轉,起點在下沿

2.flex-wrap

決定容器內專案是否可換行。預設情況下,專案都排在主軸線上,使用 flex-wrap 可實現專案的換行。

.container {
    flex-wrap: nowrap | wrap | wrap-reverse;
}
  • 預設值:nowrap 不換行,即當主軸尺寸固定時,當空間不足時,專案尺寸會隨之調整而並不會擠到下一行。

  • wrap:專案主軸總尺寸超出容器時換行,第一行在上方

  • wrap-reverse:換行,wrap的反向,第一行在下方

3.flex-flow: flex-direction 和 flex-wrap 的簡寫形式

.container {
    flex-flow: <flex-direction> || <flex-wrap>;
}

預設值為:row nowrap,用處不大,分開寫更好。

4.justify-content

定義了專案在主軸的對齊方式。

.container {
    justify-content: flex-start|flex-end|center|space-between|space-around
}

建立在主軸為水平方向時測試,即 flex-direction: row

  • 預設值: flex-start 左對齊

  • flex-end:右對齊

  • center:居中

  • space-betwenn:兩端對齊,專案之間的間隔相等,即剩餘空間等分成間隙。

  • space-around:每個專案兩側的間隔相等,所以專案之間的間隔比專案與邊緣的間隔大一倍。

5.align-items:定義了專案在交叉軸上的對齊方式

.container {
    align-items: flex-start | flex-end | center | baseline | stretch;
}

建立在主軸為水平方向時測試,即 flex-direction: row

  • 預設值為 stretch 即如果專案未設定高度或者設為 auto,將佔滿整個容器的高度。

假設容器高度設定為 100px,而專案都沒有設定高度的情況下,則專案的高度也為 100px。

  • flex-start:交叉軸的起點對齊

假設容器高度設定為 100px,而專案分別為 20px, 40px, 60px, 80px, 100px, 則如上圖顯示。

  • flex-end:交叉軸的終點對齊

  • center:交叉軸的中點對齊

  • baseline: 專案的第一行文字的基線對齊

6. align-content: 定義了多根軸線的對齊方式,如果專案只有一根軸線,那麼該屬性將不起作用

.container {
    align-content: stretch|center|flex-start|flex-end|space-between|space-around
}

當 flex-wrap 設定為 nowrap 的時候,容器僅存在一根軸線,因為專案不會換行,就不會產生多條軸線。

當 flex-wrap 設定為 wrap 的時候,容器可能會出現多條軸線,這時候就需要去設定多條軸線之間的對齊方式了。

建立在主軸為水平方向時測試,即 flex-direction: row, flex-wrap: wrap

  • 預設值為 stretch

  • flex-start:軸線全部在交叉軸上的起點對齊

  • flex-end:軸線全部在交叉軸上的終點對齊

  • center:軸線全部在交叉軸上的中間對齊

  • space-between:軸線兩端對齊,之間的間隔相等,即剩餘空間等分成間隙。

  • space-around:每個軸線兩側的間隔相等,所以軸線之間的間隔比軸線與邊緣的間隔大一倍。

Flex 專案屬性

有六種屬性可運用在 item 專案上:

  • order
  • flex-basis
  • flex-grow
  • flex-shrink
  • flex
  • align-self

1. order

定義專案在容器中的排列順序,數值越小,排列越靠前,預設值為 0。

.item {
    order: <integer>;
}

在 HTML 結構中,雖然 -2,-1 的 item 排在後面,但是由於分別設定了 order,使之能夠排到最前面。

2. flex-basis

定義了在分配多餘空間之前,專案佔據的主軸空間,瀏覽器根據這個屬性,計算主軸是否有多餘空間。

.item {
    flex-basis: <length> | auto;
}

預設值:auto,即專案本來的大小, 這時候 item 的寬高取決於 width 或 height 的值。

3. flex-grow

定義專案的放大比例。

.item {
    flex-grow: <number>;
}

預設值為 0,即如果存在剩餘空間,也不放大。

當所有的專案都以 flex-basis 的值進行排列後,仍有剩餘空間,那麼這時候 flex-grow 就會發揮作用了。

如果所有專案的 flex-grow 屬性都為 1,則它們將等分剩餘空間。(如果有的話)

如果一個專案的 flex-grow 屬性為 2,其他專案都為 1,則前者佔據的剩餘空間將比其他項多一倍。

當然如果當所有專案以 flex-basis 的值排列完後發現空間不夠了,且 flex-wrap:nowrap 時,此時 flex-grow 則不起作用了。

4. flex-shrink

定義了專案的縮小比例

.item {
    flex-shrink: <number>;
}

預設值: 1,即如果空間不足,該專案將縮小,負值對該屬性無效。

這裡可以看出,雖然每個專案都設定了寬度為 50px,但是由於自身容器寬度只有 200px,這時候每個專案會被同比例進行縮小,因為預設值為 1。

同理可得:

如果所有專案的 flex-shrink 屬性都為 1,當空間不足時,都將等比例縮小。

如果一個專案的 flex-shrink 屬性為 0,其他專案都為 1,則空間不足時,前者不縮小。

5.flex

flex-grow, flex-shrink 和 flex-basis的簡寫。

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

flex 的預設值是以上三個屬性值的組合。假設以上三個屬性同樣取預設值,則 flex 的預設值是 0 1 auto。

有關快捷值:auto (1 1 auto) 和 none (0 0 auto)

關於 flex 取值,還有許多特殊的情況,可以按以下來進行劃分:

  • 當 flex 取值為一個非負數字,則該數字為 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%,如下是等同的:
.item {flex: 1;}
.item {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}
  • 當 flex 取值為 0 時,對應的三個值分別為 0 1 0%
.item {flex: 0;}
.item {
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: 0%;
}
  • 當 flex 取值為一個長度或百分比,則視為 flex-basis 值,flex-grow 取 1,flex-shrink 取 1,有如下等同情況(注意 0% 是一個百分比而不是一個非負數字)
.item-1 {flex: 0%;}
.item-1 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}

.item-2 {flex: 24px;}
.item-2 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 24px;
}
  • 當 flex 取值為兩個非負數字,則分別視為 flex-grow 和 flex-shrink 的值,flex-basis 取 0%,如下是等同的:
.item {flex: 2 3;}
.item {
    flex-grow: 2;
    flex-shrink: 3;
    flex-basis: 0%;
}
  • 當 flex 取值為一個非負數字和一個長度或百分比,則分別視為 flex-grow 和 flex-basis 的值,flex-shrink 取 1,如下是等同的:
.item {flex: 11 32px;}
.item {
    flex-grow: 11;
    flex-shrink: 1;
    flex-basis: 32px;
}

建議優先使用這個屬性,而不是單獨寫三個分離的屬性。

grow 和 shrink 是一對雙胞胎,grow 表示伸張因子,shrink 表示是收縮因子。

grow 在 flex 容器下的子元素的寬度和比容器和小的時候起作用。 grow 定義了子元素的尺寸增長因子,容器中除去子元素之和剩下的尺寸會按照各個子元素的 grow 值進行平分加大各個子元素上。

容器的 flex-wrap 與子項的 flex-shrink、flex-grow 之間的關係:

  1. 當 flex-wrap 為 wrap | wrap-reverse,且子項寬度和不及父容器寬度時,flex-grow 會起作用,子項會根據 flex-grow 設定的值放大(為0的項不放大)
  2. 當 flex-wrap 為 wrap | wrap-reverse,且子項寬度和超過父容器寬度時,首先一定會換行,換行後,每一行的右端都可能會有剩餘空間(最後一行包含的子項可能比前幾行少,所以剩餘空間可能會更大),這時 flex-grow 會起作用,若當前行所有子項的 flex-grow 都為0,則剩餘空間保留,若當前行存在一個子項的 flex-grow 不為0,則剩餘空間會被 flex-grow 不為0的子項佔據
  3. 當 flex-wrap 為 nowrap,且子項寬度和不及父容器寬度時,flex-grow 會起作用,子項會根據 flex-grow 設定的值放大(為0的項不放大)
  4. 當 flex-wrap 為 nowrap,且子項寬度和超過父容器寬度時,flex-shrink 會起作用,子項會根據 flex-shrink 設定的值進行縮小(為0的項不縮小)。但這裡有一個較為特殊情況,就是當這一行所有子項 flex-shrink 都為0時,也就是說所有的子項都不能縮小,就會出現討厭的橫向滾動條
  5. 總結上面四點,可以看出不管在什麼情況下,在同一時間,flex-shrink 和 flex-grow 只有一個能起作用,這其中的道理細想起來也很淺顯:空間足夠時,flex-grow 就有發揮的餘地,而空間不足時,flex-shrink 就能起作用。當然,flex-wrap 的值為 wrap | wrap-reverse 時,表明可以換行,既然可以換行,一般情況下空間就總是足夠的,flex-shrink 當然就不會起作用

6.align-self

單個專案覆蓋 align-items 定義的屬性。

預設值為 auto,表示繼承父元素的 align-items 屬性,如果沒有父元素,則等同於 stretch。

.item {
     align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

這個跟 align-items 屬性時一樣的,只不過 align-self 是對單個專案生效的,而 align-items 則是對容器下的所有專案生效的。

容器 align-items 設定為 flex-start,而第三號align-self設定為flex-end。