CSS - 彈性盒

彈性盒(FlexBox)

「彈性盒」是 CSS 裡很重要的觀念,如同名稱,是一種靈活佈局的盒子,至今 2020 主流的排版方式,許多著名 CSS FrameWork 都以它為佈局基礎。彈性盒的使用方式是在宣告一個元素容器為彈性盒 flex 或 inlne-flex 時,該容器就成為彈性容器(flex container)。而此彈性容器裡面的子元素,無論它們是區塊(block)或是行內(inline)類型,全部都會變成彈性項目(flex item)。當然,一些區塊元素預設的外距還是會造成些許差異(移除外距大家就一樣了),但不影響其成為彈性項目。在彈性盒裡面,有屬於它自己佈局的方式,自成領域。

主軸與次軸

彈性盒與一般盒模型不同的地方,本身具有「兩條看不見的軸」,主軸(main axis)和次軸(交叉軸 cross axis),兩條軸分別都有著起點與終點兩個軸點,主軸是 main start 與 main end,次軸是 cross start 與 cross end,如下圖所示。這些軸點是彈性盒對齊彈性項目的依據。另外,下圖可能會令人認為主軸是負責水平流向,次軸則是垂直流向,其實不是的,主軸與次軸的位置會根據彈性盒的 flex-direction 流向來決定。當 flex-direction:column 時,主軸會變成垂直流向,次軸會變成水平流向。最後,負責主軸對齊屬性是 justify-content,次軸則是 align-items。

彈性盒預設值

在學習彈性盒時,熟記最初建立彈性盒所產生的預設值是有幫助的,也就是宣告元素 display:flex 成為彈性容器時,彈性容器、彈性項目已經構築好預設屬性,一開始的預設佈局方式。以下預設屬性不會顯示出來,但它們確實已經存在。

.flex {
/* 當元素宣告為彈性容器時,其實已經產生以下的預設值 */
display: flex;
/* 主軸對齊方式預設以 main start 開始 */
justify-content: flex-start;
/* 次軸對齊方式預設為伸展拉長 */
align-items: stretch;
/* 以列為水平方向的排列 */
flex-direction: row;
/* 彈性項目不換行 */
flex-wrap: nowrap;
}

彈性盒屬性

設定在彈性盒的屬性,當元素宣告 display:flex 或 inline-flex 成為彈性容器時,才能使用它們。

屬性 說明
justify-content 宣告在彈性容器,水平對齊的位置
align-items 宣告在彈性容器,垂直對齊的位置
flex-direction 宣告在彈性容器,彈性項目的方向
flex-wrap 宣告在彈性容器,單行(不換行)、多行(換行)
flex-flow 宣告 flex-direction、flex-wrap
align-content 宣告在彈性容器,條件必須是多行元素(flex-wrap:wrap)才能使用

justify-content

定義了彈性項目在彈性容器主軸(橫軸)上的對齊行為,宣告在彈性容器,不是在彈性項目。

.flex {
display: flex;
/* 預設 彈性項目對齊主軸 main start 開始端點 */
justify-content: flex-start;
/* 彈性項目對齊主軸 main end 結束端點 */
justify-content: flex-end;
/* 彈性項目對齊主軸中央 */
justify-content: center;
/* 彈性項目會以主軸開始、結束兩端點先做為基準,並讓彈性項目之間平均分配空間 */
justify-content: space-between;
/* 彈性項目平均分配空間,但開始、結束端點會留下空白 */
justify-content: space-around;
}

align-items

定義了彈性容器在次軸上的對齊行為,宣告在彈性容器裡,不是在彈性項目,彈性項目會垂直排列。預設值 stretch 可以拉長到 100% 的 cross-size(垂直尺寸),但要是設定了 min-height、min-width、max-height、width 或 height,這些屬性有較高的優先權。也就是說,要是彈性項目在次軸方向明確定義了尺寸,就無法拉長,stretch 不會影響它的大小。

.flex {
display: flex;
/* 預設 彈性項目會拉長可延伸 */
align-item: stretch;
/* 彈性項目會對齊 cross start 開始端點 */
align-items: flex-start;
/* 彈性項目會對齊 cross end 結束端點 */
align-items: flex-end;
/* 彈性項目會對齊中央 */
align-item: center;
/* 彈性項目會對準基準線,很少使用 */
align-item: baseline;
}

flex-direction

彈性項目的排列方式,水平(row)或垂直(column)排列,宣告在彈性容器裡,不在彈性項目。主軸流向的決定是依據 flex-direction 的屬性值

當屬性值為 row:主軸為水平流向,次軸為垂直流向,彈性項目依據主軸水平排列。在預設情況下,寬度可以設定,高度若沒設定會因為 stretch 被拉至最高。
當屬性值為 column:主軸為垂直流向,次軸為水平流向,彈性項目依據主軸垂直排列。在預設情況下,高度可以設定,寬度若沒設定會因為 stretch 被拉至最寬。

.flex {
display: flex;
/* 預設 水平排列*/
flex-direction: row;
/* 垂直排列 */
flex-direction: column;
/* 水平反向排列 */
flex-direction: row-reverse;
/* 垂直反向排列 */
flex-direction: column-reverse;
}

flex-wrap

彈性項目是否要換行,預設為不換行(nowrap)。

設定 flex:nowrap,無論彈性容器多窄,彈向項目都會排在同一列,即便超過彈性容器的寬度,也不會換行。
設定 flex:wrap,彈性項目有設定寬度時,當彈性項目的寬大於彈性容器,彈性項目就會換行。

.flex {
display: flex;
/* 預設 不換行 */
flex-wrap: nowrap;
/* 換行 */
flex-wrap: wrap;
/* 反向換行 */
flex-wrap: wrap-reverse;
}

flex-flow

flex-flow 可以同時設定 flex-direction 與 flex-wrap 的縮寫,定義彈性容器的排列與換行。宣告 display:flex 時,預設是 flex-flow:row nowrap。

align-content

align-content 設置了瀏覽器如何沿著伸縮盒子容器(flexbox container)的橫軸和網格容器(Grid Container)的主軸在內容項之間和周圍分配空間。該屬性對單行彈性盒子模型無效,因此彈性容器必須要 flex-wrap: wrap 才會有作用

彈性項目的屬性

屬性 解說
align-self 覆寫 align-items 屬性
flex-grow 彈性伸展係數,控制彈性項目的伸展比例
flex-shrink 彈性收縮係數,控制彈性項目的收縮比例
flex-basis 彈性基礎係數,控制彈性項目的長度設定
flex 三合一屬性,分別是彈性伸展係數、彈性收縮係數、彈性基礎係數
order 彈性項目的排序

align-self

align-self 可以個別調整彈性項目次軸的對齊方式,因此此屬性是宣告在彈性項目,屬性值與 align-items 一樣。

flex-grow

彈性伸展係數,數字且無單位,預設值為 0,不會進行彈性伸展變化,不可為負值。當彈性項目的 flex-basis 長度「小」於它自己在彈性容器分配的長度,按照數字做相對應的「伸展」比例分配。

flex-shrink

彈性收縮係數,數字且無單位,預設值為 1,設為 0 的話不會進行彈性變化,不可為負值。當彈性項目的 flex-basis 長度「大」於它自己在彈性容器分配的長度,按照數字做相對應的「壓縮」比例分配。每個彈性項目預設收縮係數 1,可表示一件事,彈性項目全部加起來的總長度超過彈性容器時,不會出現爆版。

flex-basis

彈性基礎係數,可為單位 px、rem、百分比等,或是 auto、none,預設值為 auto。控制彈性項目主軸的長度(寬度或高度),預設 auto 指長度設定交由彈性項目的寬度或高度為優先,如果 flex-basis 有設定單位,例如:100px、20%等等,優先權則交由 flex-basis。也就是說,彈性項目本身設定的寬度或高度會變成無效。另外,為甚麼 flex-basis 要用「長度」來說明?這是因為它也是根據主軸流向 flex-direction 來決定,當 flex-direction:row,主軸為水平流向,flex-basis 則是控制寬度;當 flex-direction:column,主軸為垂直流向,flex-basis 則是控制高度。

flex

flex 是三合一屬性,可以分別設定伸展係數、收縮係數、基礎係數,預設值為 0 1 auto,也就是說當彈性盒形成,每個彈性項目均為 flex:0 1 auto。縮寫分為數字、文字表示方式。

數字表示

以數字表示,數字代表 flex-grow,彈性基準係數為 0%。

縮寫 全部
flex: 0 flex: 0 1 0%
flex: 1 flex: 1 1 0%
flex: 2 flex: 2 1 0%

文字表示

以文字表示,彈性基準係數為 auto。

縮寫 全部
flex: initial flex: 0 1 auto
flex: auto flex: 1 1 auto
flex: none flex: 0 0 auto

flex-grow 表示

以 flex-grow 表示,與文字 initial、auto 相同。

縮寫 全部 相同
flex-grow: 0 flex: 0 1 auto 等同 flex: initial
flex-grow: 1 flex: 1 1 auto 等同 flex: auto