LESSON-07 · 自主延伸

Flexbox 軸線、縮放與順序

把「Flexbox 軸線、縮放與順序」拆成 4 個可獨立完成、可重設、可驗證的自主學習 module。

1. 現在要做什麼

成果:完成可換行、長內容安全且鍵盤順序正確的服務列。

需要的檔案:files/starter/index.html(整合起點,保留跨 module 的最小缺口。)

完成後:完成可換行、長內容安全且鍵盤順序正確的服務列。

0 / 8 個操作已記錄

2. 先備自我檢查

逐項展開;答不出來時先走補救連結,不必硬做。

已完成本章基礎練習並能找到 Starter。

自我檢查:我能否指出本章 Starter 入口與唯一 TODO?

不足時補救:回到本章 README,先完成基礎練習與入口導覽。

能開啟本機 HTML 並讀取至少一種瀏覽器證據。

自我檢查:我能否開啟 Elements、Console 或 Network 並找到本頁?

不足時補救:先開 DevTools,重新整理一次,確認目前文件與第一筆 request。

3. 完整學習目標與 Learning Map

每一個目標只對應一個 module;成功狀態必須能指出證據。

能由 flex-direction 判斷主軸方向,並正確解釋 justify-content 與 align-items 各控制哪一條軸。

為什麼重要
若把水平與垂直背成固定答案,direction 改為 column 後就會反向調錯 property。
完成條件
同一個 Flex container 由 row 切成 column,前後都讀取 computed flex-direction 並觀察 item rect。
成功狀態
runtime 的 flex-direction 由 row 變 column;學生能指出主軸由 inline 方向改為 block 方向,justify/align 的責任隨軸改變。
證據位置
runtime before=row、after=column、property=flex-direction;畫面 item rect 由橫向分布改成縱向堆疊

能拆讀 flex shorthand 的 grow、shrink、basis,並預測剩餘與不足空間如何分配。

為什麼重要
只寫 flex:1 卻不理解三值,容易讓內容在寬版比例失衡,或在窄版因 shrink/basis 判斷錯誤而擠壓。
完成條件
固定 container 寬度,將第一張卡由 0 1 auto 切為 1 0 12rem,並讀取完整 computed flex shorthand。
成功狀態
runtime 的 flex 由 0 1 auto 改為包含 grow=1、shrink=0、basis=192px 的三值;人工比較卡片寬度變化。
證據位置
runtime before 包含 0 1 auto;after 包含 1 0 與 192px;property=flex

能將 Flex item 的自動最小尺寸重設為 0,使它能縮小,再用斷字處理內部長字串。

為什麼重要
Flex item 預設 min-width:auto 可能受 min-content 撐住;只調 shrink 或隱藏 overflow,頁面仍可能橫向溢位或裁掉內容。
完成條件
在固定寬度 Flex container 中放入長 URL,將 item 的 min-width 由 auto 切為 0px。
成功狀態
runtime 的 computed min-width 由 auto 變 0px;人工重測 item 與文件 scrollWidth/clientWidth 不再橫向溢位。
證據位置
runtime before=auto、after=0px、property=min-width;人工證據為 item 與頁面 scrollWidth<=clientWidth

能說明 CSS order 只改變視覺排列,不改 DOM、閱讀或鍵盤焦點順序。

為什麼重要
把主要操作視覺移到最前面卻留在 DOM 最後,會讓鍵盤與螢幕閱讀器使用者遇到與畫面不一致的流程。
完成條件
三個連結的 DOM 順序為 A、B、C,CSS 將 C 視覺排到最前;先真實聚焦 DOM 第一個 A,再手動 Tab 記錄序列。
成功狀態
受控 runtime 聚焦後 activeId=order-link-a;人工 Tab 序列仍為 A→B→C,而視覺順序為 C→A→B。
證據位置
runtime focused=true、activeId=order-link-a;人工證據保存視覺序列與三步 document.activeElement 序列

4. 4 個知識模組與 Micro Labs

依序展開;每次只改一項,操作後確認該模組自己的 DOM、progress 與 evidence。

1flex-direction 與主/交叉軸

完整解釋

白話:主軸是物件排隊的方向;交叉軸就是跟它垂直的另一條方向。

正式說法:flex-direction establishes the flex container main axis;cross axis perpendicular to it。justify-content distributes free space along main axis,align-items aligns items along cross axis。

何時使用:導覽、按鈕列、卡片列需要切換橫排/直排或調整兩軸對齊時。

修改前後:Before:justify-content 永遠被說成水平。After:先讀 direction,再判定主軸與交叉軸。

常見混淆:row 不保證由左到右;文字方向與 writing mode 也會影響 main-start/main-end。

名詞與最小範例

flex-direction 與主/交叉軸 Flex direction, main axis, and cross axis

白話
主軸是物件排隊的方向;交叉軸就是跟它垂直的另一條方向。
正式定義
flex-direction establishes the flex container main axis;cross axis perpendicular to it。justify-content distributes free space along main axis,align-items aligns items along cross axis。
何時使用
導覽、按鈕列、卡片列需要切換橫排/直排或調整兩軸對齊時。
最小範例
.service-list{display:flex;flex-direction:row;justify-content:space-between;align-items:center}
驗收證據
runtime before=row、after=column、property=flex-direction;畫面 item rect 由橫向分布改成縱向堆疊
常混淆
row 不保證由左到右;文字方向與 writing mode 也會影響 main-start/main-end。

Micro Lab|flex-direction 與主/交叉軸

情境:服務按鈕列在桌機橫排,窄版要改直排,但原本的置中規則方向跟著變了。

起始狀態:container 為 display:flex、flex-direction:row,三個 item 沿主軸橫排。

  1. 執行實驗替 Flex container 切換 direction-column class,讀取 computed flex-direction。
  2. 執行下方操作,觀察獨立的 DOM 與資料狀態。
  3. 依證據欄位重新驗收。

目前主題:flex-direction 與主/交叉軸

方案一方案二方案三
尚未執行;DOM data-state=starter。

預期:runtime 的 flex-direction 由 row 變 column;學生能指出主軸由 inline 方向改為 block 方向,justify/align 的責任隨軸改變。

證據:runtime before=row、after=column、property=flex-direction;畫面 item rect 由橫向分布改成縱向堆疊

第一個檢查:先在 Computed 讀 flex-direction,不先猜 justify-content 是水平或垂直。

重設:重新載入 module,移除 direction-column class。

卡住時

  • 症狀:切成 column 後卡片仍橫排。
    可能原因:direction-column class 沒有加在 Flex container,或 display:flex 寫在錯誤元素。
    先檢查:在 Elements 確認 class 與三張卡是否為同一 container 的直接子層。
    修正:讓被測父層同時具 display:flex 與 direction-column。

理解檢查

flex-direction:column 時,justify-content 控制哪個方向?

尚未作答。

查看解釋

justify-content 始終沿主軸;主軸由 flex-direction 決定。

本模組官方來源:MDN|flex-direction

2flex-grow、shrink、basis

完整解釋

白話:grow 決定有多的空間怎麼分,shrink 決定不夠時怎麼縮,basis 是分配前的起始尺寸。

正式說法:flex-grow is a positive free-space factor;flex-shrink is a negative free-space factor;flex-basis defines the initial main size before free space distribution。

何時使用:同一 Flex row 的卡片需要依比例伸展、保護某張卡不縮,或設定分配基準時。

修改前後:Before:把 flex:1 當成單一開關。After:能逐值說出 1 0 12rem 的分配責任。

常見混淆:flex-basis 不等於永遠的最終 width;內容、min/max size 與 free space distribution 都可能改變 used main size。

名詞與最小範例

flex-grow、shrink、basis Flex grow, shrink, and basis factors

白話
grow 決定有多的空間怎麼分,shrink 決定不夠時怎麼縮,basis 是分配前的起始尺寸。
正式定義
flex-grow is a positive free-space factor;flex-shrink is a negative free-space factor;flex-basis defines the initial main size before free space distribution。
何時使用
同一 Flex row 的卡片需要依比例伸展、保護某張卡不縮,或設定分配基準時。
最小範例
.featured{flex:1 0 12rem}.regular{flex:0 1 10rem}
驗收證據
runtime before 包含 0 1 auto;after 包含 1 0 與 192px;property=flex
常混淆
flex-basis 不等於永遠的最終 width;內容、min/max size 與 free space distribution 都可能改變 used main size。

Micro Lab|flex-grow、shrink、basis

情境:三張服務卡中推薦卡要吃剩餘空間並保留 12rem 基準,其他卡可在不足時縮小。

起始狀態:featured item 使用 flex:0 1 auto,沒有伸展比例與明確 basis。

  1. 執行實驗替 featured item 切換 flex-distribution class,讀取 computed flex shorthand。
  2. 執行下方操作,觀察獨立的 DOM 與資料狀態。
  3. 依證據欄位重新驗收。

目前主題:flex-grow、shrink、basis

推薦方案
一般方案
尚未執行;DOM data-state=starter。

預期:runtime 的 flex 由 0 1 auto 改為包含 grow=1、shrink=0、basis=192px 的三值;人工比較卡片寬度變化。

證據:runtime before 包含 0 1 auto;after 包含 1 0 與 192px;property=flex

第一個檢查:在 Computed 展開 flex,分別記錄 flex-grow、flex-shrink、flex-basis。

重設:重新載入 module,移除 flex-distribution class。

卡住時

  • 症狀:after 仍顯示 0 1 auto。
    可能原因:class 沒有加到 Flex item,或 shorthand 被個別 flex-* 宣告覆蓋。
    先檢查:確認目標是 container 的直接 child,再在 Styles 看 flex 規則順序。
    修正:移除衝突 longhands,讓 .flex-distribution 的 flex:1 0 12rem 生效。

理解檢查

`flex:1 0 12rem` 的第二個值代表什麼?

尚未作答。

查看解釋

flex shorthand 順序為 grow、shrink、basis。

本模組官方來源:MDN|flex

3min-width: 0 解決長內容

完整解釋

白話:Flex item 雖然說可以縮,預設最小寬度仍可能被長文字卡住;min-width:0 才真正允許它縮進容器。

正式說法:For flex items, automatic minimum size can resolve from content-based min-content contribution;min-width:0 removes that automatic lower bound, while overflow wrapping handles unbroken inline content。

何時使用:Flex 卡片含長 URL、不可斷代碼或很長標題,且 shrink 已開啟仍撐破容器時。

修改前後:Before:只增加 flex-shrink 或 body overflow:hidden。After:先重設 item min-width,再處理內文斷字。

常見混淆:min-width:0 不會自動替長字串加斷點;通常仍要在文字元素使用 overflow-wrap:anywhere。

名詞與最小範例

min-width: 0 解決長內容 Resetting flex item minimum width

白話
Flex item 雖然說可以縮,預設最小寬度仍可能被長文字卡住;min-width:0 才真正允許它縮進容器。
正式定義
For flex items, automatic minimum size can resolve from content-based min-content contribution;min-width:0 removes that automatic lower bound, while overflow wrapping handles unbroken inline content。
何時使用
Flex 卡片含長 URL、不可斷代碼或很長標題,且 shrink 已開啟仍撐破容器時。
最小範例
.service-card{flex:1 1 15rem;min-width:0}.service-card a{overflow-wrap:anywhere}
驗收證據
runtime before=auto、after=0px、property=min-width;人工證據為 item 與頁面 scrollWidth<=clientWidth
常混淆
min-width:0 不會自動替長字串加斷點;通常仍要在文字元素使用 overflow-wrap:anywhere。

Micro Lab|min-width: 0 解決長內容

情境:三欄服務列縮到手機寬度時,只有含長 URL 的卡片把整頁撐寬。

起始狀態:container 可縮;問題 item flex:1 1 15rem,但 min-width 仍是 auto。

  1. 執行實驗替含長 URL 的 Flex item 切換 allow-flex-shrink class,讀取 computed min-width。
  2. 執行下方操作,觀察獨立的 DOM 與資料狀態。
  3. 依證據欄位重新驗收。

目前主題:min-width: 0 解決長內容

尚未執行;DOM data-state=starter。

預期:runtime 的 computed min-width 由 auto 變 0px;人工重測 item 與文件 scrollWidth/clientWidth 不再橫向溢位。

證據:runtime before=auto、after=0px、property=min-width;人工證據為 item 與頁面 scrollWidth<=clientWidth

第一個檢查:先選取問題 Flex item,讀 Computed min-width 與 scrollWidth/clientWidth。

重設:重新載入 module,移除 allow-flex-shrink class。

卡住時

  • 症狀:min-width 已是 0px,但 URL 仍超出卡片。
    可能原因:item 已能縮小,但不可斷字串本身沒有 wrapping 規則。
    先檢查:比較 item clientWidth 與 URL scrollWidth,查看文字的 overflow-wrap。
    修正:保留 min-width:0,並在 URL 元素加入 overflow-wrap:anywhere。

理解檢查

Flex item 設 min-width:0 主要解決什麼?

尚未作答。

查看解釋

auto minimum size 可能阻止 item 縮小;0 允許 Flex sizing 真正收縮。

本模組官方來源:MDN|min-width

4order 與鍵盤順序風險

完整解釋

白話:order 像只把桌上的卡片挪位置,文件原本的閱讀與按 Tab 路線沒有跟著搬。

正式說法:The order property changes flex item ordinal groups in visual layout;it does not reorder DOM nodes and must not be used to repair logical reading or sequential focus order。

何時使用:只做不影響理解的小型視覺調整;若順序代表任務流程,應直接修正 HTML DOM 順序。

修改前後:Before:用 order 把 CTA 提到最前並假設所有人都先遇到它。After:DOM/Tab 維持合理流程,order 不承擔語意順序。

常見混淆:tabindex 正值也不是安全修正;它會建立另一套難維護的焦點順序。

名詞與最小範例

order 與鍵盤順序風險 Flex order and keyboard focus order

白話
order 像只把桌上的卡片挪位置,文件原本的閱讀與按 Tab 路線沒有跟著搬。
正式定義
The order property changes flex item ordinal groups in visual layout;it does not reorder DOM nodes and must not be used to repair logical reading or sequential focus order。
何時使用
只做不影響理解的小型視覺調整;若順序代表任務流程,應直接修正 HTML DOM 順序。
最小範例
.card-c{order:-1} /* 視覺 C,A,B;Tab 仍依 DOM A,B,C */
驗收證據
runtime focused=true、activeId=order-link-a;人工證據保存視覺序列與三步 document.activeElement 序列
常混淆
tabindex 正值也不是安全修正;它會建立另一套難維護的焦點順序。

Micro Lab|order 與鍵盤順序風險

情境:設計稿把第三個『立即預約』卡片視覺移到第一,但 HTML 仍把它放在服務介紹之後。

起始狀態:DOM 依 A、B、C;C 設 order:-1,因此視覺為 C、A、B。

  1. 執行受控 focus 實驗聚焦 DOM 第一個連結 A;再只用 Tab 從頁首記錄 A、B、C,與 CSS order 的視覺 C、A、B 對照。
  2. 執行下方操作,觀察獨立的 DOM 與資料狀態。
  3. 依證據欄位重新驗收。

目前主題:order 與鍵盤順序風險

尚未執行;DOM data-state=starter。

預期:受控 runtime 聚焦後 activeId=order-link-a;人工 Tab 序列仍為 A→B→C,而視覺順序為 C→A→B。

證據:runtime focused=true、activeId=order-link-a;人工證據保存視覺序列與三步 document.activeElement 序列

第一個檢查:先在 Elements 讀三個 a 的 DOM 順序,再看 Computed order,最後才按 Tab。

重設:重新載入 module,焦點回到 document 起點;不改 tabindex。

卡住時

  • 症狀:Tab 看起來也先到視覺第一個 C。
    可能原因:測試不是從頁首開始、DOM 已被 JavaScript 重排,或使用了正 tabindex。
    先檢查:重新載入後檢查 Elements DOM 順序與三個 tabindex attribute。
    修正:移除正 tabindex 與 DOM 重排,只保留 CSS order,再從頁首重測。

理解檢查

若卡片順序代表使用流程,最安全的修正是什麼?

尚未作答。

查看解釋

合理 DOM 能同時服務視覺、閱讀與鍵盤順序;order 不改語意流程。

本模組官方來源:MDN|order accessibility

5. Flexbox 軸線、縮放與順序|整合 Lab

情境:在同一份章節作品中整合 4 個 module,排除單項通過但組合失敗的問題。

交付:完成可換行、長內容安全且鍵盤順序正確的服務列。

尚未執行整合步驟。
  1. 1觀察整合 Starter 並找出第一個未通過 module。

    檔案:files/starter/index.html 定位:#observe

    操作:逐項讀取 outcomes,執行一次現況操作。

    // OBSERVE:不修改程式,先記錄第一個失敗 moduleId。

    預期:能指出第一個未通過 module。

    證據:第一個 moduleId 與缺少的 evidence。

    原因:先觀察可避免未重現就直接改答案。

    卡住先查:確認開啟的是 files/starter/index.html。

  2. 2依 module 順序修改,一次只加入一個責任。

    檔案:files/starter/index.html 定位:#modify

    操作:執行實驗替 Flex container 切換 direction-column class,讀取 computed flex-direction。 → 執行實驗替 featured item 切換 flex-distribution class,讀取 computed flex shorthand。 → 執行實驗替含長 URL 的 Flex item 切換 allow-flex-shrink class,讀取 computed min-width。 → 執行受控 focus 實驗聚焦 DOM 第一個連結 A;再只用 Tab 從頁首記錄 A、B、C,與 CSS order 的視覺 C、A、B 對照。

    // 07-01-flex-direction: 執行實驗替 Flex container 切換 direction-column class,讀取 computed flex-direction。
    // 07-02-flex-grow-shrink-basis: 執行實驗替 featured item 切換 flex-distribution class,讀取 computed flex shorthand。
    // 07-03-min-width-0: 執行實驗替含長 URL 的 Flex item 切換 allow-flex-shrink class,讀取 computed min-width。
    // 07-04-order: 執行受控 focus 實驗聚焦 DOM 第一個連結 A;再只用 Tab 從頁首記錄 A、B、C,與 CSS order 的視覺 C、A、B 對照。

    預期:完成可換行、長內容安全且鍵盤順序正確的服務列。

    證據:runtime before=row、after=column、property=flex-direction;畫面 item rect 由橫向分布改成縱向堆疊;runtime before 包含 0 1 auto;after 包含 1 0 與 192px;property=flex;runtime before=auto、after=0px、property=min-width;人工證據為 item 與頁面 scrollWidth<=clientWidth;runtime focused=true、activeId=order-link-a;人工證據保存視覺序列與三步 document.activeElement 序列

    原因:逐項整合能把回歸定位到明確 module。

    卡住先查:回到第一個未通過的 module,只修該處。

  3. 3驗證所有 module 在整合後仍成立。

    檔案:files/solution/index.html 定位:#verify

    操作:重新整理並依 outcomes 順序重跑所有證據。

    // VERIFY:逐項記錄 pass/fail,不以看到畫面代替 evidence。

    預期:4/4 module 通過。

    證據:每個 moduleId 都有實際結果與重設後重現紀錄。

    原因:單項通過不代表整合後沒有 selector、id 或狀態衝突。

    卡住先查:若失敗,回到第一個失敗 module,不同時修多項。

  4. 4把本章責任轉用到不同內容情境。

    檔案:files/starter/index.html 定位:#challenge

    操作:替另一個商家情境重做,仍達成:完成可換行、長內容安全且鍵盤順序正確的服務列。

    // CHALLENGE:只替換內容與資料,不新增框架或跳過 self-check。

    預期:完成可換行、長內容安全且鍵盤順序正確的服務列。

    證據:轉用後的作品與全數 module self-check。

    原因:能轉用才代表理解責任,而非只記住原範例。

    卡住先查:先確認共同基底與 module id 未被改壞。

重設方法:重新載入 files/starter/index.html;若 localStorage 不可用,使用頁面內記憶狀態並提供重設按鈕。

6. 自學挑戰與三層提示

挑戰:將同一組責任轉用到另一個商家情境,仍達成:完成可換行、長內容安全且鍵盤順序正確的服務列。

限制:不新增框架。;保留 module id 與驗收證據。

提交證據:提交可直接開啟的作品與逐項 self-check。

提示 1|方向提示

拆小:在「Flexbox 軸線、縮放與順序」先完成第一個尚未通過的 module:flex-direction 與主/交叉軸,不同時修改其他責任。

提示 2|關鍵片段

串接:依 07-01-flex-direction → 07-02-flex-grow-shrink-basis → 07-03-min-width-0 → 07-04-order 核對各自輸入與證據。

提示 3|完整解答與原因

完整解答與原因:依序執行 執行實驗替 Flex container 切換 direction-column class,讀取 computed flex-direction。 → 執行實驗替 featured item 切換 flex-distribution class,讀取 computed flex shorthand。 → 執行實驗替含長 URL 的 Flex item 切換 allow-flex-shrink class,讀取 computed min-width。 → 執行受控 focus 實驗聚焦 DOM 第一個連結 A;再只用 Tab 從頁首記錄 A、B、C,與 CSS order 的視覺 C、A、B 對照。;這個順序能把每個結果對回單一 module,避免整合後無法定位。

完整解答預設收合;先留下自己的嘗試,再開第三層。

7. 症狀式除錯指南

8. 理解測驗、驗收證據與下一步

哪個狀態代表 07-01-flex-direction 完成?

尚未作答。

查看解釋

若把水平與垂直背成固定答案,direction 改為 column 後就會反向調錯 property。

哪個狀態代表 07-02-flex-grow-shrink-basis 完成?

尚未作答。

查看解釋

只寫 flex:1 卻不理解三值,容易讓內容在寬版比例失衡,或在窄版因 shrink/basis 判斷錯誤而擠壓。

哪個狀態代表 07-03-min-width-0 完成?

尚未作答。

查看解釋

Flex item 預設 min-width:auto 可能受 min-content 撐住;只調 shrink 或隱藏 overflow,頁面仍可能橫向溢位或裁掉內容。

哪個狀態代表 07-04-order 完成?

尚未作答。

查看解釋

把主要操作視覺移到最前面卻留在 DOM 最後,會讓鍵盤與螢幕閱讀器使用者遇到與畫面不一致的流程。

驗收清單

官方來源

回到課程地圖選擇下一章