【自學程式】那些年你沒搞懂的 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

raw-image

就像上圖所呈現,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

|聯絡我:vivian.enlife@gmail.com


參考資料:

MND Flexbox

CSS Tricks: A Complete Guide to Flexbox

留言
avatar-img
留言分享你的想法!
avatar-img
Vivian Yeh - 跨領域轉職的軟體工程師
444會員
102內容數
為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上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
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
Flexbox一種強大佈局技術,主要用於一維排列 的元素。它提供了更靈活的對齊方式,能夠輕鬆控制子元素的方向、對齊方式、間距與自適應能力,適用於現代網頁設計與響應式開發。使用方式為在 HTML 的父元素當中,透過寫入 display:flex; 這行語法,即能夠讓子元素產生各種排列的方式。
Thumbnail
Flexbox一種強大佈局技術,主要用於一維排列 的元素。它提供了更靈活的對齊方式,能夠輕鬆控制子元素的方向、對齊方式、間距與自適應能力,適用於現代網頁設計與響應式開發。使用方式為在 HTML 的父元素當中,透過寫入 display:flex; 這行語法,即能夠讓子元素產生各種排列的方式。
Thumbnail
在這一章節中,我們介紹了 Flexbox 這個 CSS 模型及其用法,重點講解了 Flex 容器和項目的各種屬性。通過具體的示例,展示了如何使用 Flexbox 進行一維佈局設計,並且通過實踐案例,展示了多行 Flex 項目和不同對齊方式的應用。
Thumbnail
在這一章節中,我們介紹了 Flexbox 這個 CSS 模型及其用法,重點講解了 Flex 容器和項目的各種屬性。通過具體的示例,展示了如何使用 Flexbox 進行一維佈局設計,並且通過實踐案例,展示了多行 Flex 項目和不同對齊方式的應用。
Thumbnail
本篇習作內容進入到 CSS 排版實作,一起瞭解 Flexbox,開始第一個網頁排版吧 💪🏻!
Thumbnail
本篇習作內容進入到 CSS 排版實作,一起瞭解 Flexbox,開始第一個網頁排版吧 💪🏻!
Thumbnail
display 是一種 CSS 屬性,指定「 是否 / 如何 」顯示元素,而每一個 HTML element 都有預設的 display value,然而在預設的情況下,新手如我在剛接觸時常踩入深不見底的盲區, 一起來釐清學會辨識吧!
Thumbnail
display 是一種 CSS 屬性,指定「 是否 / 如何 」顯示元素,而每一個 HTML element 都有預設的 display value,然而在預設的情況下,新手如我在剛接觸時常踩入深不見底的盲區, 一起來釐清學會辨識吧!
Thumbnail
在 Modern Web 的世界中,已經有非常多的套件、語法、框架,可以解決大部分網頁排版問題。 以我近期的觀察來說,在專案開發時,大部分公司會為了讓下一個接手、維護的開發者能更快上手專案架構,而採取原生的 CSS 寫法,而不是仰賴快速又方便的套件。
Thumbnail
在 Modern Web 的世界中,已經有非常多的套件、語法、框架,可以解決大部分網頁排版問題。 以我近期的觀察來說,在專案開發時,大部分公司會為了讓下一個接手、維護的開發者能更快上手專案架構,而採取原生的 CSS 寫法,而不是仰賴快速又方便的套件。
Thumbnail
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
Thumbnail
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
Thumbnail
在 pxCode 裡,我們也建議應用相同的概念 —— 在切版前先進行一輪的【思考切版】。當有了結構概念之後,再動手執行,會更有效率!
Thumbnail
在 pxCode 裡,我們也建議應用相同的概念 —— 在切版前先進行一輪的【思考切版】。當有了結構概念之後,再動手執行,會更有效率!
Thumbnail
明明想要某個欄位的寬高為 200px,卻發現自己不知道為什麼怎麼更改都會改不動,又或者寬高更改了,卻沒有辦法與其他元素並列。 上述的狀況,通常都是在不熟悉 HTML display 特性而產生的狀況下才會出現⋯⋯
Thumbnail
明明想要某個欄位的寬高為 200px,卻發現自己不知道為什麼怎麼更改都會改不動,又或者寬高更改了,卻沒有辦法與其他元素並列。 上述的狀況,通常都是在不熟悉 HTML display 特性而產生的狀況下才會出現⋯⋯
Thumbnail
一開始接觸網頁開發的時候,可能會常常在切版時遇到一些奇奇怪怪的問題:版面總是無法貼齊,左右參差不齊;圖片或是版型變形,但都找不到問題,又或者是技術跟不上設計稿,怎麼切怎麼亂。 會有這樣的狀況主要是⋯⋯
Thumbnail
一開始接觸網頁開發的時候,可能會常常在切版時遇到一些奇奇怪怪的問題:版面總是無法貼齊,左右參差不齊;圖片或是版型變形,但都找不到問題,又或者是技術跟不上設計稿,怎麼切怎麼亂。 會有這樣的狀況主要是⋯⋯
Thumbnail
Flexbox長於小規模佈局,而Grid layout則適於大規模佈局。 Flexbox是單向度的排版,Grid則是包含X軸和Y軸的平面排版方式。 如果你想要簡單輕便的實現單一軸向的自適應式排版,例如導覽列、卡片式排版、相簿等,可以選擇使用Flexbox。如果你想快速實現雙軸平面式,甚至不規則的排版
Thumbnail
Flexbox長於小規模佈局,而Grid layout則適於大規模佈局。 Flexbox是單向度的排版,Grid則是包含X軸和Y軸的平面排版方式。 如果你想要簡單輕便的實現單一軸向的自適應式排版,例如導覽列、卡片式排版、相簿等,可以選擇使用Flexbox。如果你想快速實現雙軸平面式,甚至不規則的排版
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News