【自學程式】那些年你沒搞懂的 Flexbox 及實務應用技巧

更新 發佈閱讀 17 分鐘

在 Modern Web 的世界中,已經有非常多的套件、語法、框架,可以解決大部分網頁排版問題。

以我近期的觀察來說,在專案開發時,大部分公司會為了讓下一個接手、維護的開發者能更快上手專案架構,而採取原生的 CSS 寫法,而不是仰賴快速又方便的套件。

更進一步說,即便專案中使用了套件、框架,開發者好不好上手專案更多時候還是仰賴對 CSS 的熟悉度,如果對 CSS 掌握度不高,也會出現即便使用了套件,依然出現排版與自己預期不同的狀況。

今天我就要來分享過往自己曾常常踩雷的一個 CSS 概念:Flexbox掌握好 Flexbox 的概念,可以解決大部分你在網頁畫面切版上所需要解決的排版問題。


何謂 Flexbox ?為什麼我們需要這個語法?

Flexbox 是 CSS 中一種透過欄與列的方式進行排版的模型,這個模型可以讓元素伸縮、自適應容器,或是在有限空間下,自適應限制元件的寬高。

如果去觀察較早期的網頁,可能會發現有些原始碼還在使用 float 或是 position 的語法進行排版,但其實以上兩種排版方式有滿大的缺點:

  • 沒有辦法同時水平、垂直置中元素
  • 沒有辦法平均分配子元素在父元素中的佔比,及分配父元素的剩餘空間
  • 沒有辦法讓子元素彼此自動對齊彼此的高度

然而 Flexbox 可以很好地透過 flex 系列語法解決以上問題,這也讓開發者更快速、方便的進行網頁排版。


如何使用 Flexbox ?

在開始介紹如何使用 flexbox 之前,我們可以先來看看等等會使用到的程式碼範例:

在上方的範例中,我刻意建立了在實務上如果要建立列表會使用的 HTML 結構(當然我在其他文章中也有提到 ul>li 的使用方式,但為了免除一些不必要的調整,我統一使用 div 做示範)。

範例中也預填好一些簡單明瞭的樣式,接著我們要使用 flexbox 語法,來替列表進行排版:

我們可以在父元素 .list 上加上 display: flex 這個語法,此時就會按照 flexbox 模型進行網頁元素的排列,接著我們可以來看看加上 display: flex 後對範例產生的影響:

  1. 排列的方式改變了:預設的 div 元素,會帶有 display: block 的 CSS 預設屬性,照常理來說帶有 display: block 的元素,並不會與其他元素並列同一列才對,但是當父元素帶有 display: flex 時,會改變子元素 display 預設屬性所帶來的效果。
  2. 排列的方向變了:當父元素 .list 還沒有加上 display: flex 這個語法前,內層的子元素會按照原本的 display: block 特性進行排列,所以在一開始的範例中三個 div 元素是由上至下排列的。但加上 display: flex 這個語法後, 卻改變由左至右排列,且寬度也不再是 100% 了。

這究竟是為什麼呢?以下我們將針對 flexbox 的原理、語法、使用情境細細介紹:


Flex 基礎原理與 Flex container

vocus|新世代的創作平台

就像上圖所呈現,flexbox 的組成會有 flex container 及 flex items 兩個要素。

通常帶有 display: flex 的元素,會稱為 flex container ,其包含的子元素,則會稱為 flex item ,初學 flex 時,可能會覺得這不是很重要而忽略,但其實 flex container 與 flex item 所能使用的語法是大大不同的,所以最好是將此概念銘記在心。

在文章的前半部,我們主要會專注在 flex container 的部分,flex item 的部分則會在後半部才會比較仔細的說明。

首先我們要先聊聊 flex container 是透過怎麼樣的機制來進行網頁排版的:

在 flex container 中,會使用主軸(main axis)與交錯軸(cross)的概念了來指定 flex items 排列的方向,通常我們會使用一個語法:flex-direction,來指定我們的主軸方向為何,讓我們直接來看範例:

在 flex-direction 中,我們可以帶入幾種值,分別為:row(由左至右)、row-reverse(由右至左)、column(由上至下)、column-reverse(由下至上),這個方向性就代表了主軸的方向性,交錯軸就會是相反的方向。

從上方的範例中可以看到,flex item 會根據 flex container 所指定的主軸方向進行排列。

在預設的狀況下,當 flex container 只要帶有 display: flex 的狀況下,就會有預設 flex-direction: row 的語法,所以即便我們額外設定,也不會有什麼差別,所以如果通常我們是要由左至右排列時,我們可以單純在 flex container 下 display: flex 這個語法即可。


justify-content 決定 flex items 依主軸的排列方式

在前面有提到,在還沒有 flexbox 的網頁開發時期,要將子元素置中在父元素裡,是一件不輕鬆的事,但透過在 flex container 上使用 justify-content 語法,我們可以很輕鬆的做到這件事。

justify-content 提供了以下幾種值來針對 flex items 做排列:

  • flex-start:將 flex items 集中在主軸的起始位置(起始及結束位置可參考上圖)
  • flex-end:將 flex items 集中在主軸的結束位置
  • center:以主軸方向將 flex items 置中
  • space-around:以主軸方向將 flex items 的兩側,各自空出以間距為單位、二分之一的距離
  • space-between:以主軸方向將 flex items 貼緊 flex containers 兩側且平均分配間距
  • space-evenly:以主軸方向將剩餘空間平均分配在間距及 flex containers 兩側的空間,也就是平均分配 flex items 的距離

我們可以透過下方範例看懂這幾個語法的差異:

在有些狀況底下 justify-content 並不會生效:

  1. 你並不是在 flex container 使用這個語法
  2. 主軸的方向與你預期的不同
  3. 打錯字
  4. 使用到並非能在 flex container 與 flex items 能生效的語法(justify-content 語法有部分的值並非給 flexbox 做使用)


align-items 決定 flex items 依交錯軸的排列方式

除了水平的排列,很多時候我們也會需要針對網頁元素來做垂直的排版,這時我們就可以在 flex container 上使用 align-items 語法依照交錯軸的方向,對 flex items 進行群體的垂直排列(本文中所提到的水平與垂直,是基於 flex-direction: row 的設定,但在 flexbox 中主要還是以主軸、交錯軸為主)。

flex 提供了以下幾種跟 align-items 有關的語法:

  • stretch:如果不在 flex container 上特別設定 align-items 語法, 則會以 stretch 為預設值,帶有 stretch 特性的 flex container,其底下之 flex items 會依照當前 flex items 之最高的元素高度(cross size)做拉伸,或是依照 flex container 之高度直接填滿容器,若在 flex items 上設有高度(當主軸為 row 時)或是寬度(當主軸為 column 時),高度及寬度的權重會大於 align-items: stretch
  • normal(因為 normal 這個屬性,在其他非 flexbox 中也會生效,但在 flexbox 中,等同於 stretch,故不加以說明)
  • flex-start:將 flex items 集中在交錯軸的起始位置(起始及結束位置可參考上圖)
  • flex-end:將 flex items 集中在交錯軸的結束位置
  • center:以交錯軸方向將 flex items 置中

讓我們直接看範例:

這裡補幾個在使用此語法時可能會誤踩的雷點:

  1. 直接把 justify-content 有的語法代換進 align-items 中使用,但實際上他們有些語法是不共用的,例如:justity-content 在 flexbox 無法使用 stretch 這個屬性。
  2. 忘記給 flex container 設高度,導致垂直排版的效果出不來
  3. align-items 必須在 flex container 中使用才會生效


flex items 特性介紹

前文大致上將我們平常會在 flex container 上使用的語法介紹到一個段落,接著我們要來聊聊 flex items 的一些特性。

首先,怕大家忘記再重複說明一下, flexbox 的基本要素會包含:flex container 及 flex items,我們可以透過在父元素上加上 display: flex 讓子元素成為 flex items 。

而 flexbox 是具有方向性的,分為主軸(main axis)與交錯軸(cross axis),flexbox 的語法在不同的軸上有不同的應用。

根據上方概念, flex items 可以使用以下幾個屬性,但要注意以下語法是只作用在主軸上

  • flex-grow:若有剩餘空間時,flex items  會分配到多少比例的剩餘空間,通常預設值為 0
  • flex-shrink:當 flex item 超過 flex container 時,是否會依比例縮小,通常預設值為 1
  • flex-basis:設定 flex item 在主軸方向上的最小大小,預設值為 auto ,也就是會自適應主軸方向的大小(main size)

以上三個語法,還可以更濃縮為 flex 語法,以預設值作為範例: flex: 0 1 auto ,裡面的值依序為:flex-grow、flex-shrink 及 flex-basis。

讓我們來看看上述幾個語法的範例:

關於在 flex items 上使用 flex 語法,通常我們都只會在 flex-grow 與 flex-shrink 上以 0 與 1 的差異去區分是否要自動分配剩餘空間或是自適應容器。

前面有提到 flex-grow 與 flex-shrink 實際上是以**無單位之係數,**來計算分配比例的權重,然而這部分牽涉到 CSS 底層的演算機制,這裡就不多去研究實際分配權重是怎麼分配的,因為實務上我們也因為官方文件的標示不明確,而較少去使用。

由於權重的計算,也會因為整體容器的大小、flex items 的大小,而有所不同,建議可以直接使用響應式的單位來進行 flex items 大小的調整,例如:百分比。

那什麼狀況底下 flex-grow、flex-shrink 會無法生效呢?

  1. 在錯誤的軸上使用
  2. 搞錯 0 與 1 的使用方式
注:剩餘空間指的是無法填滿 container 時,所剩下來的空間。


align-self 決定 flex item 自身交錯軸的排列方式

講完 flex items 的特性後,再來聊聊另外一個屬於 flex items 的語法:align-self。

這個語法使用起來跟前面所提到的 align-items 差不多,唯一差別在於 align-self 是針對單一 flex item 進行交錯軸上的排列,而 align-items 語法是針對所有交錯軸上的 flex items 進行排列。

實際上,align-items 雖然是 flex container 的語法,但其實是群體性在 flex items 加上 align-self 語法罷了(這邊說的狀況是指最後結果的狀況,並不是使用 align-items 就真的會群體性產生 align-self 的語法)。

由於這兩者使用起來差不多,就不多額外介紹了,但有一個需要再三注意的地雷要提醒大家:並不是所有的 flex 語法都是對稱的,有 align-self 不代表 justify-self 也是作用在 flexbox 上,justify-self 就跟 justify-content: stretch 並不會在 flexbox 的結構中生效一樣,千萬不要搞混了!


flex-wrap 讓 flex items 自適應換行

另外一個 flexbox 非常好用的語法就是 flex-wrap ,這個語法可以判斷當前 flex items 是否會超出 flex container,flex-wrap 語法有以下幾種屬性:

  • wrap:當 flex items 超過 flex container 即依交錯軸起始到結束位置的方向換行(通常是向下)
  • nowrap:當 flex items 超過 flex container 時,隱藏超出去的部分
  • wrap-reverse:當 flex items 超過 flex container 即依交錯軸結束到起始位置的方向換行(通常是向上)

在預設的狀況下,會是 nowrap,讓我們來看看範例:

通常網頁在建立卡片或是列表時,如果是使用 flexbox 作為 layout 的方式,通常會使用此語法來進行列表的自適應。

那什麼樣的狀況下使用 flex-wrap 會不如預期呢?

  • 容器沒有設定寬度,所以容器可以無限延伸
  • flex items 沒有設定寬度,所以會無限被壓縮

而 flex-wrap 還有一個相關的延伸用法,就是當 flexbox 的交錯軸有剩餘空間時,我們可以使用 align-content 來進行行內的空間排列,但通常這樣的狀況不多見,不多見的原因在於:

通常會使用到 flex-wrap 這個語法,就是因為無法預期列表所需要的資料會有多少筆、內容會有多少,所以通常列表的高度我們會保持自適應,而不會寫死一個高度,也不會進而產生剩餘空間。

個人覺得以應用層面來說,align-content 這個語法有點雞肋,我們這邊就不多提這個語法了。


Flexbox 實務應用

最後來做個總結,以不同種的網頁排版來說,flexbox 算是相對彈性、好上手的語法,基本上可以處理掉大部分的網頁排版需求,舉凡:

  • 帶有規律性的列表
  • 可自適應、換行多筆資料所產生的元件
  • 同時做到水平、垂直方向的
  • 置中效果統一,不需要再用古老的置中方法

搞懂 flexbox 的運作模式,算是前端工程師基本中的基本,打好基礎在網頁切版上可以省去不少除錯的時間。

由於今天有提到 display 及 position 相關的用法,不熟悉的朋友可以參考下方文章:



希望透過這篇文章的分享,可以讓大家更了解 flex box 的特性,關於 flexbox 你有什麼想要跟我分享的嗎?歡迎下方留言與我分享!

希望今天的文章有幫助到正在閱讀的你,如果你喜歡我的文章的話,可以留下你的愛心或是收藏我的文章,也或者可以點選「贊助」,你的一杯咖啡絕對是我持續寫下去的動力!或是透過拍拍手,用你小小的行動支持我的創作!

我是Vivian,我們下次見。



關於我:

一名從英文系畢業的前端工程師,喜歡閱讀、寫東西及自我成長。

|Instagram: Vivian Yeh|vivian_enlife

|聯絡我:[email protected]


參考資料:

MND Flexbox

CSS Tricks: A Complete Guide to Flexbox

留言
avatar-img
Vivian Yeh - 跨領域轉職的軟體工程師
459會員
103內容數
為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
2023/06/07
說到 HTML 元素的換行效果,在前端有滿多種實作方式的最常見的方式是使用 <br /> 這個 HTML 元素來進行換行 ⋯⋯
Thumbnail
2023/06/07
說到 HTML 元素的換行效果,在前端有滿多種實作方式的最常見的方式是使用 <br /> 這個 HTML 元素來進行換行 ⋯⋯
Thumbnail
2022/03/23
相信透過之前的介紹,大家對於 CSS 選擇器(CSS selector)已經不陌生了,今天我們要來聊聊兩個在實務上非常好用的偽類(pseudo class )語法,他們分別是 :nth-child() 與 :nth-of-type(),在了解這兩個語法之前,我們首先要先來聊聊什麼是「偽類」呢?
Thumbnail
2022/03/23
相信透過之前的介紹,大家對於 CSS 選擇器(CSS selector)已經不陌生了,今天我們要來聊聊兩個在實務上非常好用的偽類(pseudo class )語法,他們分別是 :nth-child() 與 :nth-of-type(),在了解這兩個語法之前,我們首先要先來聊聊什麼是「偽類」呢?
Thumbnail
2021/12/05
不論是在基礎或是進階的版面排列,幾乎離開不了 position 系列的 CSS 語法,如果對於這些語法不熟悉,要快速完成畫面需求幾乎是不可能的,甚至會延宕整個團隊的開發速度(對,position 語法就是這麽重要)。
Thumbnail
2021/12/05
不論是在基礎或是進階的版面排列,幾乎離開不了 position 系列的 CSS 語法,如果對於這些語法不熟悉,要快速完成畫面需求幾乎是不可能的,甚至會延宕整個團隊的開發速度(對,position 語法就是這麽重要)。
Thumbnail
看更多
你可能也想看
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
在這一章節中,我們介紹了 Flexbox 這個 CSS 模型及其用法,重點講解了 Flex 容器和項目的各種屬性。通過具體的示例,展示了如何使用 Flexbox 進行一維佈局設計,並且通過實踐案例,展示了多行 Flex 項目和不同對齊方式的應用。
Thumbnail
在這一章節中,我們介紹了 Flexbox 這個 CSS 模型及其用法,重點講解了 Flex 容器和項目的各種屬性。通過具體的示例,展示了如何使用 Flexbox 進行一維佈局設計,並且通過實踐案例,展示了多行 Flex 項目和不同對齊方式的應用。
Thumbnail
明明想要某個欄位的寬高為 200px,卻發現自己不知道為什麼怎麼更改都會改不動,又或者寬高更改了,卻沒有辦法與其他元素並列。 上述的狀況,通常都是在不熟悉 HTML display 特性而產生的狀況下才會出現⋯⋯
Thumbnail
明明想要某個欄位的寬高為 200px,卻發現自己不知道為什麼怎麼更改都會改不動,又或者寬高更改了,卻沒有辦法與其他元素並列。 上述的狀況,通常都是在不熟悉 HTML display 特性而產生的狀況下才會出現⋯⋯
Thumbnail
Flexbox一種強大佈局技術,主要用於一維排列 的元素。它提供了更靈活的對齊方式,能夠輕鬆控制子元素的方向、對齊方式、間距與自適應能力,適用於現代網頁設計與響應式開發。使用方式為在 HTML 的父元素當中,透過寫入 display:flex; 這行語法,即能夠讓子元素產生各種排列的方式。
Thumbnail
Flexbox一種強大佈局技術,主要用於一維排列 的元素。它提供了更靈活的對齊方式,能夠輕鬆控制子元素的方向、對齊方式、間距與自適應能力,適用於現代網頁設計與響應式開發。使用方式為在 HTML 的父元素當中,透過寫入 display:flex; 這行語法,即能夠讓子元素產生各種排列的方式。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
在 pxCode 裡,我們也建議應用相同的概念 —— 在切版前先進行一輪的【思考切版】。當有了結構概念之後,再動手執行,會更有效率!
Thumbnail
在 pxCode 裡,我們也建議應用相同的概念 —— 在切版前先進行一輪的【思考切版】。當有了結構概念之後,再動手執行,會更有效率!
Thumbnail
在 Modern Web 的世界中,已經有非常多的套件、語法、框架,可以解決大部分網頁排版問題。 以我近期的觀察來說,在專案開發時,大部分公司會為了讓下一個接手、維護的開發者能更快上手專案架構,而採取原生的 CSS 寫法,而不是仰賴快速又方便的套件。
Thumbnail
在 Modern Web 的世界中,已經有非常多的套件、語法、框架,可以解決大部分網頁排版問題。 以我近期的觀察來說,在專案開發時,大部分公司會為了讓下一個接手、維護的開發者能更快上手專案架構,而採取原生的 CSS 寫法,而不是仰賴快速又方便的套件。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本篇習作內容進入到 CSS 排版實作,一起瞭解 Flexbox,開始第一個網頁排版吧 💪🏻!
Thumbnail
本篇習作內容進入到 CSS 排版實作,一起瞭解 Flexbox,開始第一個網頁排版吧 💪🏻!
Thumbnail
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
Thumbnail
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
Thumbnail
display 是一種 CSS 屬性,指定「 是否 / 如何 」顯示元素,而每一個 HTML element 都有預設的 display value,然而在預設的情況下,新手如我在剛接觸時常踩入深不見底的盲區, 一起來釐清學會辨識吧!
Thumbnail
display 是一種 CSS 屬性,指定「 是否 / 如何 」顯示元素,而每一個 HTML element 都有預設的 display value,然而在預設的情況下,新手如我在剛接觸時常踩入深不見底的盲區, 一起來釐清學會辨識吧!
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News