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

更新於 發佈於 閱讀時間約 1 分鐘
在 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

就像上圖所呈現,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,我們下次見。
關於我:
一名從英文系畢業的前端工程師,喜歡閱讀、寫東西及自我成長。
|聯絡我:vivian.enlife@gmail.com
參考資料:
為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
相信透過之前的介紹,大家對於 CSS 選擇器(CSS selector)已經不陌生了,今天我們要來聊聊兩個在實務上非常好用的偽類(pseudo class )語法,他們分別是 :nth-child() 與 :nth-of-type(),在了解這兩個語法之前,我們首先要先來聊聊什麼是「偽類」呢?
不論是在基礎或是進階的版面排列,幾乎離開不了 position 系列的 CSS 語法,如果對於這些語法不熟悉,要快速完成畫面需求幾乎是不可能的,甚至會延宕整個團隊的開發速度(對,position 語法就是這麽重要)。
相信大家在一開始接觸 CSS 時,一定會很疑惑為什麼除了 width 外,還會有 max-width 及 min-width 語法呢? 當要開發響應式網頁時,到底要使用什麼語法來控制「斷點」?
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
明明想要某個欄位的寬高為 200px,卻發現自己不知道為什麼怎麼更改都會改不動,又或者寬高更改了,卻沒有辦法與其他元素並列。 上述的狀況,通常都是在不熟悉 HTML display 特性而產生的狀況下才會出現⋯⋯
在一個網頁上,會需要使用到圖片的地方有非常多處,像是品牌主視覺、橫幅廣告、側邊廣告、主要內容的預覽圖片、縮圖、背景圖片等。
相信透過之前的介紹,大家對於 CSS 選擇器(CSS selector)已經不陌生了,今天我們要來聊聊兩個在實務上非常好用的偽類(pseudo class )語法,他們分別是 :nth-child() 與 :nth-of-type(),在了解這兩個語法之前,我們首先要先來聊聊什麼是「偽類」呢?
不論是在基礎或是進階的版面排列,幾乎離開不了 position 系列的 CSS 語法,如果對於這些語法不熟悉,要快速完成畫面需求幾乎是不可能的,甚至會延宕整個團隊的開發速度(對,position 語法就是這麽重要)。
相信大家在一開始接觸 CSS 時,一定會很疑惑為什麼除了 width 外,還會有 max-width 及 min-width 語法呢? 當要開發響應式網頁時,到底要使用什麼語法來控制「斷點」?
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
明明想要某個欄位的寬高為 200px,卻發現自己不知道為什麼怎麼更改都會改不動,又或者寬高更改了,卻沒有辦法與其他元素並列。 上述的狀況,通常都是在不熟悉 HTML display 特性而產生的狀況下才會出現⋯⋯
在一個網頁上,會需要使用到圖片的地方有非常多處,像是品牌主視覺、橫幅廣告、側邊廣告、主要內容的預覽圖片、縮圖、背景圖片等。
你可能也想看
Google News 追蹤
Thumbnail
大家好,我是woody,是一名料理創作者,非常努力地在嘗試將複雜的料理簡單化,讓大家也可以體驗到料理的樂趣而我也非常享受料理的過程,今天想跟大家聊聊,除了料理本身,料理創作背後的成本。
Thumbnail
哈囉~很久沒跟各位自我介紹一下了~ 大家好~我是爺恩 我是一名圖文插畫家,有追蹤我一段時間的應該有發現爺恩這個品牌經營了好像.....快五年了(汗)時間過得真快!隨著時間過去,創作這件事好像變得更忙碌了,也很開心跟很多厲害的創作者以及廠商互相合作幫忙,還有最重要的是大家的支持與陪伴🥹。  
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
在本章中,我們探討了CSS Grid佈局的基本概念和應用。CSS Grid提供了一個強大而靈活的二維佈局系統,使得處理複雜的網頁佈局變得更加簡單和直觀。我們學習了如何設置Grid容器和Grid項目,以及如何使用各種Grid屬性來定義和管理佈局。
Thumbnail
在這一章節中,我們介紹了 Flexbox 這個 CSS 模型及其用法,重點講解了 Flex 容器和項目的各種屬性。通過具體的示例,展示了如何使用 Flexbox 進行一維佈局設計,並且通過實踐案例,展示了多行 Flex 項目和不同對齊方式的應用。
Thumbnail
浮動(float)是早期用來創建佈局的技術。元素可以向左或向右浮動,旁邊的元素會環繞浮動元素。浮動元素通常用於圖文混排或簡單的兩欄佈局。
Thumbnail
CSS 盒模型是理解和設計網頁佈局的核心概念。它包括元素的內容、填充、邊框和外邊距。
Thumbnail
CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
Thumbnail
在學習 CSS 的過程中,Padding 與 Margin 是兩個經常出現的名詞,但對於初學者來說,可能會有些難以理解。因此,本篇文章將解釋這兩個非常重要的 CSS 屬性。當你掌握後,便能設計出更具層次或易讀的網頁。
Thumbnail
這篇文章分享了 CSS Battle 第 38 題的解法,並提供了相關的技術總結。文章內容包括了使用 flex 排版處理、背景漸層的方法處理等相關技術。透過這篇文章可以學習到如何解決 CSS 切版的問題。
1.justify-content 用來控制主軸(水平)如何分配對齊 如果要改垂直對齊的話+上 flex-direction : column 2.align-item 他是控制子項目再交叉軸(垂直)的對齊方式 3.flex-shrink 收縮性! 當空間不足時預設會是1,等於是
CSS Box Model 是在 CSS 裡面,html 的每個元素都可被視作為一個盒子,然後可以針對這個盒子去做調整,看以下圖片: 簡單來說margin就是一個是外邊距,與外層元素的間距 Margin 用於控制元素與其周邊元素的間隔,可以設定為正數(增加與其他元素的距離)、負數(減少與其他
Thumbnail
本篇文章分享了前端工程師在 CSS Battle #166 的解題方式,藉由使用 flex 來進行排版,並提供了相關的技術總結。歡迎一起來學習或練習基礎切版的朋友們和作者互動。
Thumbnail
大家好,我是woody,是一名料理創作者,非常努力地在嘗試將複雜的料理簡單化,讓大家也可以體驗到料理的樂趣而我也非常享受料理的過程,今天想跟大家聊聊,除了料理本身,料理創作背後的成本。
Thumbnail
哈囉~很久沒跟各位自我介紹一下了~ 大家好~我是爺恩 我是一名圖文插畫家,有追蹤我一段時間的應該有發現爺恩這個品牌經營了好像.....快五年了(汗)時間過得真快!隨著時間過去,創作這件事好像變得更忙碌了,也很開心跟很多厲害的創作者以及廠商互相合作幫忙,還有最重要的是大家的支持與陪伴🥹。  
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
在本章中,我們探討了CSS Grid佈局的基本概念和應用。CSS Grid提供了一個強大而靈活的二維佈局系統,使得處理複雜的網頁佈局變得更加簡單和直觀。我們學習了如何設置Grid容器和Grid項目,以及如何使用各種Grid屬性來定義和管理佈局。
Thumbnail
在這一章節中,我們介紹了 Flexbox 這個 CSS 模型及其用法,重點講解了 Flex 容器和項目的各種屬性。通過具體的示例,展示了如何使用 Flexbox 進行一維佈局設計,並且通過實踐案例,展示了多行 Flex 項目和不同對齊方式的應用。
Thumbnail
浮動(float)是早期用來創建佈局的技術。元素可以向左或向右浮動,旁邊的元素會環繞浮動元素。浮動元素通常用於圖文混排或簡單的兩欄佈局。
Thumbnail
CSS 盒模型是理解和設計網頁佈局的核心概念。它包括元素的內容、填充、邊框和外邊距。
Thumbnail
CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
Thumbnail
在學習 CSS 的過程中,Padding 與 Margin 是兩個經常出現的名詞,但對於初學者來說,可能會有些難以理解。因此,本篇文章將解釋這兩個非常重要的 CSS 屬性。當你掌握後,便能設計出更具層次或易讀的網頁。
Thumbnail
這篇文章分享了 CSS Battle 第 38 題的解法,並提供了相關的技術總結。文章內容包括了使用 flex 排版處理、背景漸層的方法處理等相關技術。透過這篇文章可以學習到如何解決 CSS 切版的問題。
1.justify-content 用來控制主軸(水平)如何分配對齊 如果要改垂直對齊的話+上 flex-direction : column 2.align-item 他是控制子項目再交叉軸(垂直)的對齊方式 3.flex-shrink 收縮性! 當空間不足時預設會是1,等於是
CSS Box Model 是在 CSS 裡面,html 的每個元素都可被視作為一個盒子,然後可以針對這個盒子去做調整,看以下圖片: 簡單來說margin就是一個是外邊距,與外層元素的間距 Margin 用於控制元素與其周邊元素的間隔,可以設定為正數(增加與其他元素的距離)、負數(減少與其他
Thumbnail
本篇文章分享了前端工程師在 CSS Battle #166 的解題方式,藉由使用 flex 來進行排版,並提供了相關的技術總結。歡迎一起來學習或練習基礎切版的朋友們和作者互動。