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 之間的關係:
- 當 flex-wrap 為 wrap | wrap-reverse,且子項寬度和不及父容器寬度時,flex-grow 會起作用,子項會根據 flex-grow 設定的值放大(為0的項不放大)
- 當 flex-wrap 為 wrap | wrap-reverse,且子項寬度和超過父容器寬度時,首先一定會換行,換行後,每一行的右端都可能會有剩餘空間(最後一行包含的子項可能比前幾行少,所以剩餘空間可能會更大),這時 flex-grow 會起作用,若當前行所有子項的 flex-grow 都為0,則剩餘空間保留,若當前行存在一個子項的 flex-grow 不為0,則剩餘空間會被 flex-grow 不為0的子項佔據
- 當 flex-wrap 為 nowrap,且子項寬度和不及父容器寬度時,flex-grow 會起作用,子項會根據 flex-grow 設定的值放大(為0的項不放大)
- 當 flex-wrap 為 nowrap,且子項寬度和超過父容器寬度時,flex-shrink 會起作用,子項會根據 flex-shrink 設定的值進行縮小(為0的項不縮小)。但這裡有一個較為特殊情況,就是當這一行所有子項 flex-shrink 都為0時,也就是說所有的子項都不能縮小,就會出現討厭的橫向滾動條
- 總結上面四點,可以看出不管在什麼情況下,在同一時間,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。