[CSS] FlexBox Layout
TL;DR
- 使用 flexbox 的時候盡可能加上
flex-wrap: wrap;
,讓 flex-container 如果容納不下 flex-items 的話,flex-items 不會穿出去,而是會換行
/* for flex container */
.flex-container {
justify-content〈流向軸內容對齊方式〉:
flex-start(default) |
flex-end |
center |
space-between |
space-around
align-items〈垂直軸對齊方式-單行〉:
flex-start |
flex-end |
center |
baseline |
stretch(default)
align-content〈垂直軸對齊方式-多行〉:
flex-start(default) |
flex-end |
center |
space-between |
space-around
flex-direction〈流向軸方向〉:
row(default) |
row-reverse |
column |
column-reverse
flex-wrap〈換行與否〉:
nowrap(default) |
wrap |
wrap-reverse
flex-flow: <flex-direction> <flex-wrap>
}
flex-item 的屬性觀察重點:
- 先看每個 flex-item 的
flex-basis
是多少,如果有多出來的則會透過flex-grow
分配;如果空間不足,則會都過flex-shrink
分配。 - 預設 flex-basis 是 auto,也就是會隨內容寬成長。
/* for flex-item */
.flex-item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
order: 0; // order 的用法類似 z-index,預設是 0
flex-grow: 0; // (default:0)
flex-shrink: 1; // (default:1)
flex-basis: auto; // (default:auto)
flex: <flex-grow> <flex-shrink> <flex-basis>; // (default: 0 1 auto)
}
See the Pen Flexbox Playground by PJCHEN (@PJCHENder) on CodePen.
- Play Ground @ PJCHENder CodePen
- FlexBox Display @ Smashing Magazine
- A Guide to FlexBox @ CSS Tricks
觀念
-
當我們使用
display: flex
其實使用的是display: box flex;
,也就是這個元素會以block
的方式排版,但內部的內容會用flex
的方式排版。 -
看到
align
就要想到垂直軸 -
看到
align-item
是針對當行; 看到align-content
則是針對多行的情況 -
在下面的例子中,灰色表示在
flex-container
中多餘的空間;橘色表示flex-item
的外框(outline)。 -
如果
flex-item
沒有給寬度的話,會完全縮在一起。
flexbox item 的大小預設值
flexbox 的 flex item 有一個非常重要的假設,flex-item 的大小預設不能比其內容大小來的小,因為 flex-item 的預設值是:
min-width: auto;
max-width: auto;
以下面這個例子來說:
<div class="flex-container">
<div class="flex-item-sm">X</div>
<div class="flex-item-lg">
<span class="text-ellipsis">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Perferendis at voluptatibus
</span>
</div>
</div>
當 .flex-container
的寬是 300px,而 .flex-item-sm
的寬是 50px 時,我們會預期 .flex-item-lg
的寬最多只會是 250px,然而,這樣的假設並不一定正確。
在下面這個例子中,flex-item-lg 的寬度變成了和父層的寬度一樣都是 300px,使得 flex-item-lg + flex-item-sm 的寬度超過了 flex-container:
要解決這個問題嗎,可以在 .flex-item-lg
加上 min-width: 0;
。
同樣類似的問題還可以參考這個範例。
Flex Container
Flex Wrap (default: no-wrap)
- 當 flex-container 沒有下
flex-wrap: wrap;
時,預設會是no-wrap
。 - 如果有足夠的空間時,則所有的 flex-item 會以它自身的寬度為最大寬度(因為預設是
flex-basis: auto;
)但若沒有足夠的空間時,則 flex-item 會根據比例縮小(因為預設是flex-shrink: 1;
),不會維持所給定的寬度。
Flex Item
Flex 的縮寫方式
flex
這個 CSS 屬性可以用來定義 flex-container 中有多餘空間時要如何成長或縮小,這是flex-grow
, flex-shrink
和 flex-basis
的縮寫。
⭐ 重點:先看每個 flex-item 的
flex-basis
是多少,如果有多出來的則會透過flex-grow
分配;如果空間不足,則會都過flex-shrink
分配。
Flex Basis
注意:
flex-basis
是該 flex-item 的基準寬度,最後實際的寬度會受到flex-shrink
和flex-grow
而影響。
flex-basis: 0
就是 basis 寬度為 0 的意思。
Flex Grow 和 Flex Shrink
當父層 flex-container 的寬度,在扣除掉每一個 flex-item 的 flex-basis
的寬度後,如果有多出來的空間,則會透過 flex-grow
分配剩下來的空間;相反地,如果空間不夠的話,則會透過 flex-shrink
縮小不足夠的空間。
❗
flex-basis
即使設為auto
仍然會有寬度,其寬度就是內容的寬度。
Flex Basis 和 Width 的關係
content –> width –> flex-basis (limited by max|min-width)
簡單來說,當沒有設定 flex-basis 的情況下(預設是 auto
),則會以該容器的所設定的 width
為準,如果該容器沒設定 width
,則會以內容的寬度為準。這也就是為什麼沒有設定 flex-basis
的時候,該 flex-item 會等同於內容寬。
但若同時有設定 flex-basis
和 width
,那麼 flex-basis
的權力較大,會以 flex-basis
的設定為準,忽略 width
的設定,更精確來說,width
的效果只能作用在當 flex-basis
是 auto
的情況下才有效。
:thumbsup: The Difference Between Width and Flex Basis @ Gedd
Flex Attributes Shorthand
下面的說明是在 Chrome 測試下的結果。
當只給一個值時:
// 什麼都不給的時候的預設值
flex: 0 1 auto;
// auto 會以 item 內容的寬高比例為依據,但會成長到佔滿整個多餘的空間,縮小到能夠符合容器的最小尺寸
flex: auto; // flex-grow: 1; flex-shrink: 1; flex-basis: auto;
flex: 1; // flex-grow: 1; flex-shrink: 1; flex-basis: 0%;
// 如果只有一個數值,但是有單位,表示 flex-basis
flex: 10em;
flex: 30px; // flex-grow: 1; flex-shrink: 1; flex-basis: 30px;
如果有兩個值時:
// 如果有兩個值,其中一個有單位,表示 flex-grow | flex-basis
flex: 1 30px; // flex-grow: 1; flex-shrink: 1; flex-basis: 30px;
flex: 0 30px; // flex-grow: 0; flex-shrink: 1; flex-basis: 30px;
// 如果有兩個值,都沒有單位,表示 flex-grow | flex-shrink
flex: 2 2; // flex-grow: 0; flex-shrink: 1; flex-basis: 0%;
如果給了三個值時:
// 表式: flex-grow | flex-shrink | flex-basis
flex: 2 2 10%;
參考
- CSS Flexible Box Layout @ MDN
- CSS Flex 寬度的計算方式 @ 六角學院