National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 17

Flexbox(一):主軸與對齊

主軸與交叉軸、justify-content、align-items、換行與 gap
Interaction 25 minute(s)

Learning Objectives

  • 說明 display: flex 加在父元素(容器)上,子元素就成為可以排成一列的項目
  • 分辨主軸與交叉軸,並說明 flex-direction 怎麼改變主軸的方向
  • 用 justify-content 控制項目在主軸上的位置與間隔,用 align-items 控制交叉軸上的對齊
  • 用 flex-wrap 讓放不下的項目換行,並說明 align-content 什麼時候才有作用
  • 用 gap 設定項目之間的距離,並寫出水平、垂直都置中的版面

把東西排成一排,曾經很麻煩

網頁上到處都是「排成一排」的東西:導覽列的連結、一排按鈕、一列卡片、頁首左邊的 logo 和右邊的登入鈕。

上一課你看過,區塊元素預設由上往下疊;想讓它們並排,過去要用 float 或 display: inline-block。 這兩種做法都能排成一列,但接下來的需求會很棘手:

想做的事 用 float、inline-block 時的困難
一排卡片高度相同 每張卡片的內容長短不一,高度自然不同
把一個方塊放在框框正中央 水平置中還好,垂直置中要靠各種技巧
空間不夠時自動換行,間距維持一致 要自己算 margin,最後一個項目還要特別處理
最後一個按鈕貼齊右邊 要另外浮動或定位

Flexbox(Flexible Box Layout,彈性盒子版面)就是為這類「沿著一個方向排一排東西」的工作設計的。 目前主流瀏覽器都支援,是現在排版的基本工具。這一課學怎麼排、怎麼對齊;下一課學項目怎麼伸縮分配空間。

容器、項目與兩條軸

Flexbox 只要在父元素加一行:

.container {
  display: flex;   /* 這個元素變成 flex 容器(flex container) */
}

它的直接子元素就自動變成 flex 項目(flex item),預設排成一列。孫元素不受影響,它們照舊排在自己的父元素裡。

Flexbox 的每個屬性都依兩條軸來說明:

  • 主軸(main axis):項目排列的方向。預設由左往右。
  • 交叉軸(cross axis):和主軸垂直的方向。預設由上往下。

主軸的方向由容器的 flex-direction 決定:

flex-direction 主軸 項目怎麼排
row(預設) 水平,由左往右 排成一列
row-reverse 水平,由右往左 排成一列,順序反過來
column 垂直,由上往下 排成一欄
column-reverse 垂直,由下往上 排成一欄,順序反過來

記住這件事,後面就不會搞混:justify-content 永遠管主軸,align-items 永遠管交叉軸。 主軸轉成直的,justify-content 就改成管垂直方向。

中文、英文由左往右書寫,所以 row 是由左往右。如果頁面是阿拉伯文這類由右往左書寫的語言,row 也會跟著由右往左。

互動實驗:Flexbox 容器的屬性

下面的虛線框是 flex 容器,裡面 5 個方塊是項目,高度刻意不一樣。點面板上的值,方塊會直接套用那個 CSS,由瀏覽器排出來;框的上方與左邊標出目前的主軸(藍色)和交叉軸(綠色)。下方的程式碼是你目前的設定,黃色是改過的地方。

justify-content 與 align-items

justify-content:主軸上還有空間時,項目放在哪裡、空間怎麼分。

值 效果
flex-start(預設) 全部靠主軸的起點
flex-end 全部靠主軸的終點
center 全部擠在中間
space-between 第一個貼起點、最後一個貼終點,剩下的空間平均分在項目之間
space-around 每個項目左右各分到一樣的空間,所以兩端的空隙是中間的一半
space-evenly 所有空隙(包含兩端)都一樣大

align-items:每個項目在交叉軸上怎麼對齊。

值 效果
stretch(預設的行為) 項目拉長到和這一行一樣高(沒有設定高度時)
flex-start/flex-end 靠交叉軸的起點/終點
center 在交叉軸上置中
baseline 讓每個項目第一行文字的基線對齊,字級不同時很好用

在剛才的實驗裡,一開始 5 個方塊一樣高,就是因為 stretch:它們被拉到和容器一樣高。 這也是 Flexbox 做「等高卡片」的原理。

你也會看到 start、end 這兩個值,它們來自較新的對齊規格,大多數情況和 flex-start、flex-end 效果相同。

完美置中:三行 CSS

「把一個東西放在框框正中央」曾經是網頁排版的經典難題。用 Flexbox 只要在外框寫三行:

.hero {
  display: flex;
  justify-content: center;  /* 主軸(水平)置中 */
  align-items: center;      /* 交叉軸(垂直)置中 */
}

注意兩件事:

  1. 這三行寫在外框(容器)上,不是寫在要置中的卡片上。
  2. 外框要有高度,垂直置中才看得出來;高度和內容一樣時,上下沒有多的空間可以分。

互動練習:把海報卡片放到正中央

社團成果展的首頁橫幅(.hero)裡有一張卡片,現在擠在左上角。只改 CSS,讓卡片在橫幅裡水平、垂直都置中。

小測驗:軸與對齊

1.

容器設定了 flex-direction: column。這時 justify-content: center 會讓項目在哪個方向置中?

2.

想讓 <nav> 裡的四個 <a> 排成一列,display: flex 應該寫在哪裡?

3.

一列三個按鈕,希望所有空隙一樣大,包含最左邊和最右邊的空隙。應該用哪個值?

第 1 次作答

放不下時:flex-wrap、align-content 與 gap

Flexbox 預設 flex-wrap: nowrap:所有項目擠在同一行,寧可縮小(下一課會講縮小的規則), 縮到不能再縮就超出容器。標籤、按鈕這種數量不固定的東西,通常要讓它換行:

.tags {
  display: flex;
  flex-wrap: wrap;   /* 放不下就換到下一行 */
  gap: 8px;          /* 項目之間留 8px,行與行之間也是 8px */
}

gap 只加在項目之間,不加在最外側,所以不用再為最後一個項目特別處理 margin。 要分開設定可以寫 gap: 12px 8px(第一個是行與行之間 row-gap,第二個是項目之間 column-gap)。

換行之後出現好幾行,這時才有 align-content:它決定這幾行在交叉軸上怎麼分配多出來的空間, 值和 justify-content 很像(flex-start、center、space-between…)。

屬性 管什麼 什麼時候有作用
align-items 每一行裡面,項目在交叉軸上怎麼對齊 一直都有
align-content 好幾行整體在交叉軸上怎麼排 只有 flex-wrap: wrap 而且真的換成多行時

只有一行(nowrap)的容器設定 align-content 不會有任何效果,這是很常見的疑問。

互動練習:會自動換行的技能標籤

作品集頁的技能標籤已經是 flex 容器,但 8 個標籤全擠在同一行,衝出了 300px 的虛線框。用 CSS 修好它。

小測驗:換行、間距與置中

1.

下面哪一種情況,設定 align-content: center 不會有任何效果?

2.

要讓 .box 在 300px 高的 .wrap 裡水平、垂直都置中,最精簡的寫法是?

3.

容器設定 gap: 10px,裡面一行有 4 個項目。項目之間的空隙一共有幾段 10px?

第 1 次作答

重點整理

  • display: flex 寫在容器上,直接子元素變成 flex 項目。
  • 主軸是項目排列的方向,由 flex-direction 決定;交叉軸和它垂直。
  • justify-content 管主軸(起點、終點、置中、space-between/around/evenly);align-items 管交叉軸(預設 stretch,所以項目等高)。
  • flex-wrap: wrap 讓放不下的項目換行;多行時才用 align-content 安排這幾行。
  • 項目之間的距離用 gap,它不會加在最外側。
  • 完美置中:容器寫 display: flex; justify-content: center; align-items: center;,而且容器要有高度。

下一課講 Flexbox 的另一半:flex-grow、flex-shrink、flex-basis 怎麼把空間分給項目,以及導覽列、等高卡片、頁尾貼底這幾種常見版型。

這一課完成了!
Next lesson:Flexbox(二):伸縮與常見版型
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。