# LESSON-11｜CSS 進階：Position、Sticky 與堆疊

> 對象：完全沒有前端概念的入門者
>
> 時間：3 小時
>
> **本堂專屬焦點：**用 Position 控制元素參考點、捲動行為與前後層級

## 1. 課程目標

完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口；重疊層級清楚，窄版與鍵盤焦點不被遮住。

## 2. 任務情境

商家希望在服務頁標出推薦方案，並讓聯絡入口在長頁面中保持可找到。

## 3. 先備知識與檔案結構

先備知識：知道 HTML 是瀏覽器會讀取的內容結構、CSS 是套用到元素的樣式規則；知道 class、selector、property、value、瀏覽器 viewport 與 DevTools 的 Elements／Styles／Computed。若尚未熟悉，先開啟 README 的四個最小實驗，逐一比對畫面與檔案。

### 檔案地圖

- `index.html`：首頁入口：呈現商家第一印象與主要 CTA。
- `style.css`：CSS 樣式檔：放置本堂「用 Position 控制元素參考點、捲動行為與前後層級」相關的版面規則。
- `examples/`：資料夾位置：存放本堂會被頁面引用的檔案。

## 授課補強｜180 分鐘教學節奏

**本堂專屬焦點：**用 Position 控制元素參考點、捲動行為與前後層級

固定的是八段時間，變化的是本堂檔案、教師操作、學生產出與驗收證據。

| 時間 | 教學活動 | 教師交付 | 學生產出 |
| --- | --- | --- | --- |
| 0–10 分鐘 | 情境導入｜商家希望在服務頁標出推薦方案，並讓聯絡入口在長頁面中保持可找到。 | 展示 index.html、style.css、examples/ 目前的狀態，先請學生預測「完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口；重疊層級清楚，窄版與鍵盤焦點不被遮住。」完成後會出現什麼畫面或資料結果。 | 說出本堂問題與完成目標。；完成後：知道要從 index.html、style.css、examples/ 找到第一個可觀察結果。；驗收：以normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus中的第一項作為導入前後的對照證據。 |
| 10–35 分鐘 | 概念建立｜normal flow、static、relative、absolute、sticky、fixed、containing block、viewport、z-index 與 focus-visible | 用 index.html、style.css、examples/ 中的最小片段逐詞解釋 normal flow、static、relative、absolute、sticky、fixed、containing block、viewport、z-index 與 focus-visible，每介紹一個詞就回到瀏覽器或 DevTools 指出可觀察結果。 | 完成名詞對照表，並先回答一題預測題。；完成後：能用自己的話解釋 normal flow、static、relative、absolute、sticky、fixed、containing block、viewport、z-index 與 focus-visible。；驗收：口頭回答一題預測題，並指出normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus中對應的畫面、Console、Network、DOM 或資料證據。 |
| 35–55 分鐘 | 教師示範｜先比較 normal flow 與 relative，再用 relative card 放置 absolute badge，最後觀察 sticky header、fixed CTA、z-index 與鍵盤 focus。 | 從最小可執行範例開始，逐次修改 index.html、style.css、examples/；每次只改一個檢查點，先預測再重新整理或操作。 | 跟著完成一次修改，記下修改前後差異。；完成後：看到 normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus 中至少一項可觀察結果。；驗收：保留一次修改前後畫面，並記下normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus中至少兩項觀察結果。 |
| 55–95 分鐘 | 學生跟做｜完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口；重疊層級清楚，窄版與鍵盤焦點不被遮住。 | 將示範拆成 10–15 分鐘一個小檢查點，巡迴確認學生真的修改到 index.html、style.css、examples/，卡住時先要求說出症狀與證據。 | 在自己的專案完成：完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口；重疊層級清楚，窄版與鍵盤焦點不被遮住。；完成後：核心成果能在自己的專案重現，而不是只在講師畫面成功。；驗收：提交核心成果、修改檔案清單，以及normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus中可重現的至少兩項證據。 |
| 95–110 分鐘 | 觀察與除錯｜把 absolute 放在錯誤父層、忘記 sticky 的 top、讓 fixed CTA 沒有底部留白，或用 z-index 蓋住焦點，透過畫面、Elements 與 Computed 找出原因。 | 故意重現「把 absolute 放在錯誤父層、忘記 sticky 的 top、讓 fixed CTA 沒有底部留白，或用 z-index 蓋住焦點，透過畫面、Elements 與 Computed 找出原因。」，示範從症狀、證據、假設、單一修正到重新驗證的除錯紀錄。 | 重現一個錯誤，再只修改一處並重新驗證。；完成後：能寫出症狀、原因、修正與修正後結果。；驗收：留下錯誤狀態與修正後狀態的對照，證明normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus中的錯誤已消失。 |
| 110–155 分鐘 | 情境變體與獨立挑戰｜將 fixed 聯絡入口改成預約諮詢提示，保留內容底部留白，並在 390px 與 200% 文字放大下重做驗收。 | 先圈出 index.html、style.css、examples/ 中不變的技術結構，再示範如何完成「將 fixed 聯絡入口改成預約諮詢提示，保留內容底部留白，並在 390px 與 200% 文字放大下重做驗收。」，最後請學生獨立完成同一變體。 | 完成變體：將 fixed 聯絡入口改成預約諮詢提示，保留內容底部留白，並在 390px 與 200% 文字放大下重做驗收。；完成後：能說明哪些結構保留、哪些內容替換，且沒有引入超出本堂範圍的技術。；驗收：將變體結果與原始結果並列，附上檔案或操作位置與一次重新驗證紀錄。 |
| 155–175 分鐘 | 驗收、展示與討論｜normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus | 依 normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus 逐項抽查學生的畫面、Console、Network、DOM 或資料與檔案，請學生先展示證據，再討論不同解法。 | 展示：normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus；完成後：能回答「如果驗收失敗，下一個要查什麼？」。；驗收：留下可重現的驗收包：結果截圖或網址、檔案位置、檢查步驟與實際觀察。 |
| 175–180 分鐘 | 重點回顧與下堂銜接｜狀態與無障礙：下一堂會把 focus、hover 與表單錯誤狀態整理成可操作的介面回饋。 | 用「概念、操作、證據」三問回看 index.html、style.css、examples/ 的成果，再說明它如何接到「狀態與無障礙：下一堂會把 focus、hover 與表單錯誤狀態整理成可操作的介面回饋。」。 | 寫下三句回顧：我理解了什麼、我做出了什麼、我用什麼證據確認；再預測下一堂會修改哪個檔案。；完成後：能用一句話說明本堂成果如何銜接：狀態與無障礙：下一堂會把 focus、hover 與表單錯誤狀態整理成可操作的介面回饋。；驗收：講師抽問一位學生重述狀態與無障礙：下一堂會把 focus、hover 與表單錯誤狀態整理成可操作的介面回饋。，並收回一項本堂驗收證據。 |

## 4. 觀念拆解

本堂第一次出現的詞，先從「白話 → 正式定義 → 何時使用 → 最小例子 → 可觀察證據 → 混淆概念」建立完整理解。

### normal flow（normal flow）

- **白話：**瀏覽器沒有額外定位時，元素依 HTML 順序自然排列。
- **正式定義：**文件中未被特殊定位方式移出的元素，依區塊與行內排版規則佔據原本空間的排列方式。
- **使用時機：**要先預測元素原本會在哪裡，或比較 relative 是否保留空間時。
- **最小範例：**兩張卡片依序出現；前一張改變外觀不會讓後一張消失。
- **觀察證據：**Elements 順序、畫面位置，以及第二張卡片是否仍從原本位置開始。
- **容易混淆：**和 viewport 混淆；normal flow 是文件內的排列規則，不是視窗座標。

### static（position: static）

- **白話：**元素使用瀏覽器預設的普通排列方式。
- **正式定義：**position 的預設值；元素留在 normal flow 中，top、right、bottom、left 不會移動它。
- **使用時機：**不需要特殊定位，只想讓元素依內容順序排列時。
- **最小範例：**.flow-card { position: static; }
- **觀察證據：**Computed 的 position 是 static，設定 top 後畫面仍不位移。
- **容易混淆：**和 relative 混淆；relative 會接受 offset，static 不會。

### relative（position: relative）

- **白話：**先留在原本位置，再從原位做小幅位移。
- **正式定義：**元素仍占據 normal flow 原本的空間，但可依 offset properties 相對自身原位置移動；也能成為 absolute 子元素的 containing block。
- **使用時機：**要微調元素，或要讓卡片成為徽章的定位參考時。
- **最小範例：**.service-card { position: relative; }
- **觀察證據：**卡片移動後原空間仍存在；子層 badge 以卡片角落為參考。
- **容易混淆：**和 absolute 混淆；relative 保留自己的流內空間，absolute 通常不保留。

### absolute（position: absolute）

- **白話：**把元素從普通排列中拿出來，放到指定參考盒子的座標。
- **正式定義：**元素不再占據 normal flow 的空間，位置通常相對最近的 positioned ancestor；若沒有，則繼續尋找更高層的 containing block。
- **使用時機：**徽章、裝飾或卡片內的角標需要貼在父層角落時。
- **最小範例：**.featured-badge { position: absolute; top: .75rem; right: .75rem; }
- **觀察證據：**badge 不會把標題往下推，並隨 relative card 一起移動。
- **容易混淆：**和 fixed 混淆；absolute 的參考可由祖先元素改變，fixed 通常以 viewport 為參考。

### containing block（containing block）

- **白話：**定位元素拿來計算 top、right、bottom、left 的參考盒子。
- **正式定義：**瀏覽器依定位方式與祖先建立的幾何區域，決定 positioned descendant 的尺寸與 offset 計算基準。
- **使用時機：**absolute badge 跑到頁面角落，或不知道 top／right 是相對誰計算時。
- **最小範例：**.service-card { position: relative; }
.featured-badge { position: absolute; top: 0; right: 0; }
- **觀察證據：**Elements 的祖先關係、Computed position，以及 badge 是否貼在 card 右上角。
- **容易混淆：**和 parent element 混淆；父元素不一定自動成為 containing block，通常要有適合的定位條件。

### offset properties（top / right / bottom / left）

- **白話：**告訴定位元素要離參考盒子的哪一側多遠。
- **正式定義：**用於 positioned element 的偏移屬性；它們的實際效果取決於 position 與 containing block。
- **使用時機：**需要把 relative 元素移一點，或把 absolute badge 貼到角落時。
- **最小範例：**.flow-card--moved { position: relative; top: 1rem; left: 1rem; }
- **觀察證據：**Computed 可看到 top／left，畫面可看到元素位移；static 元素不會因它們移動。
- **容易混淆：**和 margin 混淆；offset 改變定位座標，margin 參與盒子間距與流動排版。

### sticky（position: sticky）

- **白話：**元素先在普通位置，捲到門檻後黏在指定位置。
- **正式定義：**在 normal flow 中保留空間，並在接近指定 inset（例如 top: 0）時於其 scrolling ancestor 範圍內保持可見。
- **使用時機：**長頁面的頁首或分段標題要在捲動時暫時留在視線內時。
- **最小範例：**.site-header { position: sticky; top: 0; z-index: 10; }
- **觀察證據：**捲動前 header 在頁面原位，捲動後 header 停在 viewport 上方附近；Computed 仍是 sticky。
- **容易混淆：**和 fixed 混淆；sticky 受祖先與捲動範圍限制，fixed 通常不占流內空間且跟著 viewport。

### fixed（position: fixed）

- **白話：**元素固定在瀏覽器視窗的位置，捲動內容時仍留在那裡。
- **正式定義：**元素從 normal flow 移出，通常相對 viewport 定位；它不會替後面的內容保留空間。
- **使用時機：**聯絡 CTA、客服按鈕或需要一直可找到的操作入口時。
- **最小範例：**.floating-contact { position: fixed; right: 1rem; bottom: 1rem; }
- **觀察證據：**捲動前後 CTA 都靠近視窗右下角，頁面內容另外用 padding-bottom 避免被遮住。
- **容易混淆：**和 sticky 混淆；fixed 不會在某個流內自然停止，也不會自動替內容讓位。

### viewport（viewport）

- **白話：**瀏覽器目前用來顯示網頁的可視範圍。
- **正式定義：**使用者代理程式呈現文件內容的視窗區域；fixed 元素通常以它作為定位參考。
- **使用時機：**測試 fixed 位置、390px 窄版或 200% 文字放大時。
- **最小範例：**在 DevTools 裝置模式切到 390px，再觀察 fixed CTA 的 right／bottom。
- **觀察證據：**視窗寬度、document 是否出現水平捲軸，以及 CTA 是否仍可讀可按。
- **容易混淆：**和整個 HTML 文件高度混淆；viewport 是目前看得到的視窗區域。

### stacking context（stacking context）

- **白話：**瀏覽器用來決定一組元素前後層級的獨立堆疊範圍。
- **正式定義：**元素在同一 stacking context 內依 stack level、z-index 與文件順序繪製；不同 context 不能只靠子元素 z-index 任意穿透。
- **使用時機：**兩個元素真的重疊，卻不知道為什麼某一張卡片在前面時。
- **最小範例：**.stack-demo { position: relative; }
.stack-card--front { position: absolute; z-index: 2; }
- **觀察證據：**兩張卡片實際重疊，Computed 可看到 z-index，畫面能指出哪張在上層。
- **容易混淆：**和單純 z-index 數字混淆；z-index 只在適當的 stacking context 比較，不是全頁絕對排名。

### z-index（z-index）

- **白話：**同一堆疊範圍中，數字用來比較誰畫在前面。
- **正式定義：**設定 positioned element 或特定 layout item 的 stack level；數值較高通常繪製在較低值前方。
- **使用時機：**sticky header、fixed CTA 或兩張重疊卡片需要明確前後順序時。
- **最小範例：**.stack-card--back { z-index: 1; }
.stack-card--front { z-index: 2; }
- **觀察證據：**兩張有面積重疊的卡片中，Computed z-index 與可見遮蓋順序一致。
- **容易混淆：**和 position 混淆；z-index 不會自己讓元素重疊，也不會取代定位宣告。

### overflow（overflow）

- **白話：**內容超出元素盒子時，決定要顯示、捲動或裁切的設定。
- **正式定義：**控制內容超過盒子尺寸時的呈現方式；某些 overflow／scrolling ancestor 也會影響 sticky 的觀察範圍。
- **使用時機：**sticky 沒有如預期黏住，或 fixed／badge 被裁切時。
- **最小範例：**.lesson-frame { overflow: visible; }
- **觀察證據：**Computed 的 overflow 值、實際捲動容器與元素是否被裁切。
- **容易混淆：**和解決問題混淆；用 overflow:hidden 藏住溢位不等於修正定位根因。

### focus-visible（:focus-visible）

- **白話：**鍵盤操作時，讓目前被選到的連結或按鈕顯示清楚外框。
- **正式定義：**當瀏覽器判斷焦點需要以可見方式呈現時套用的 CSS pseudo-class；它補足只測滑鼠 hover 的盲點。
- **使用時機：**驗收 Tab 順序、固定 CTA 是否擋住焦點，或要保留清楚的鍵盤操作位置時。
- **最小範例：**:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
- **觀察證據：**不使用滑鼠，只按 Tab；每個連結與按鈕都有清楚外框，且外框沒有被 fixed 元素遮住。
- **容易混淆：**和 :hover 混淆；hover 依賴滑鼠，focus-visible 讓鍵盤使用者看得到目前位置。

## 5. Live Lab

### 最小可執行實驗

- **入口：**`examples/01-flow-relative.html`
- **操作：**依序開啟四個實驗：比較 normal flow／relative，暫時移除 containing block 的 relative，捲動 sticky，最後捲動 fixed 頁面並用 Tab 走過連結與按鈕。
- **預期結果：**四個檔案都能直接開啟；relative 保留原空間、absolute badge 跟著 card、sticky 有足夠內容可捲動、fixed CTA 不遮住最後內容，兩張重疊卡片可比較 z-index。
- **重設方式：**重新開啟 examples/01-flow-relative.html；DevTools 暫時修改只要重新整理即可清除。
- **第一個檢查位置：**先確認目前開啟的檔案名稱是 examples/01-flow-relative.html，並從導覽逐一開啟其餘三個檔案。

### Step 1：比較 normal flow 與 relative

- **教學目的：**先知道元素原本如何排列，再觀察 relative 位移不會拿走原本空間。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**examples/01-flow-relative.html、style.css
- **修改前：**先開啟 examples/01-flow-relative.html，記下三張卡片的文件順序與第二張卡片的原本位置。
- **本次只修改：**.flow-card--moved { position: relative; top: 1rem; left: 1rem; }
- **程式碼或操作：**

  ```text
  .flow-card--moved {
    position: relative;
    top: 1rem;
    left: 1rem;
  }
  ```
- **預期結果：**第二張卡片視覺上往右下移動，但第三張卡片仍保留原本的排列位置。
- **學生可能的錯誤答案：**改用 position: absolute，或只改 margin 便宣稱這是 relative 的效果。
- **講師追問：**第二張卡片移動後，瀏覽器有沒有把它原本占據的空間交給第三張？
- **Elements／Styles／Computed／捲動／Tab 驗收：**Elements 的 DOM 順序、Computed position／top／left，以及第二、三張卡片的畫面位置。
- **卡住時的單一檢查：**只檢查 .flow-card--moved 是否命中，並確認頁面目前真的載入這個 HTML。

### Step 2：讓 absolute badge 找到 containing block

- **教學目的：**用推薦徽章理解 absolute 不在 normal flow，且會尋找最近的 positioned ancestor。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**index.html、style.css
- **修改前：**在服務卡中加入 badge，再先預測沒有 relative 父層時 top／right 會相對哪個盒子。
- **本次只修改：**.service-card { position: relative; }
.featured-badge { position: absolute; top: .75rem; right: .75rem; }
- **程式碼或操作：**

  ```text
  .service-card { position: relative; }
  .featured-badge {
    position: absolute;
    top: .75rem;
    right: .75rem;
  }
  ```
- **預期結果：**badge 貼在服務卡右上角，不推動標題；移動 card 時 badge 跟著 card。
- **學生可能的錯誤答案：**只調整 badge 的 top／right，卻沒有讓服務卡成為 containing block。
- **講師追問：**請在 Elements 往上走：哪一個祖先真的有 position，不是只有 class 名稱？
- **Elements／Styles／Computed／捲動／Tab 驗收：**Elements 的父子關係、Computed 的 position，以及 badge 與 card 的相對角落。
- **卡住時的單一檢查：**只查看 .featured-badge 最近的 .service-card 是否有 position: relative。

### Step 3：捲動觀察 sticky

- **教學目的：**理解 sticky 先留在文件流，再在 top 門檻成立後黏住。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**style.css、index.html
- **修改前：**確認入口頁有足夠長的內容，先記下頁首在頁面頂端的原始位置。
- **本次只修改：**.site-header { position: sticky; top: 0; z-index: 10; }
- **程式碼或操作：**

  ```text
  .site-header {
    position: sticky;
    top: 0;
    z-index: 10;
  }
  ```
- **預期結果：**捲動長頁面後 header 停在視窗上方；回到頂端時仍能回到原本的文件位置。
- **學生可能的錯誤答案：**沒有內容可捲動，或把 sticky 改成 fixed 後便誤以為兩者相同。
- **講師追問：**sticky 和 fixed 都看起來留在上方，但哪一個仍保留 normal flow 空間並受祖先範圍影響？
- **Elements／Styles／Computed／捲動／Tab 驗收：**捲動前後畫面、Computed position: sticky、top: 0 與文件總高度。
- **卡住時的單一檢查：**先確認入口頁內容高度大於 viewport，再查看是否有祖先 overflow 改變捲動容器。

### Step 4：完成 fixed、z-index 與 focus 驗收

- **教學目的：**把固定 CTA、實際重疊的卡片與鍵盤焦點放在同一個可操作頁面中。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**index.html、style.css
- **修改前：**先捲動到頁面底部，記下 CTA 是否遮住文字、兩張卡片是否真的重疊，以及 Tab 順序。
- **本次只修改：**.page-shell { padding-bottom: 6rem; }
.stack-card--front { z-index: 2; }
:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
- **程式碼或操作：**

  ```text
  .floating-contact { position: fixed; right: 1rem; bottom: 1rem; z-index: 20; }
  .page-shell { padding-bottom: 6rem; }
  .stack-card--front { z-index: 2; }
  :focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
  ```
- **預期結果：**CTA 固定在 viewport 右下角但不遮內容；兩張重疊卡片有可比較的前後層級；Tab focus 清楚可見。
- **學生可能的錯誤答案：**只增加很大的 z-index，卻沒有重疊元素、底部留白或可聚焦的真實控制項。
- **講師追問：**z-index 解決的是誰在前面；它有沒有替 fixed CTA 下面的文字保留空間？
- **Elements／Styles／Computed／捲動／Tab 驗收：**捲動前後位置、兩張卡片的 Computed z-index、390px／200% 文字畫面與 Tab focus 截圖。
- **卡住時的單一檢查：**先分三件事看：CTA 是否 fixed、內容是否有 padding-bottom、焦點元素是否是 a 或 button。

### Live Lab 與階段任務對照

- Step 1 對應 **starter-1**：style.css｜.flow-card--moved；學生停點：第二張卡片往右下移動，但第三張卡片仍保留原本的文件流位置。；證據：Computed 的 position、top、left，以及第二與第三張卡片的畫面位置。
- Step 2 對應 **starter-2**：index.html｜.featured-badge；學生停點：推薦標籤貼在指定卡片角落，不影響其他卡片排版。；證據：Elements 父層與捲動畫面位置。
- Step 3 對應 **starter-3**：style.css｜.site-header；學生停點：捲動內容時頁首停在容器頂端。；證據：捲動畫面、Computed position 與 top。
- Step 4 對應 **starter-4**：index.html、style.css｜.floating-contact、.stack-card--front、.page-shell；學生停點：聯絡入口固定在右下角但不遮住最後文字，兩張重疊卡片可比較前後層級，Tab focus 清楚可見。；證據：捲動前後位置、Elements 的 href、兩張卡片的 Computed z-index、390px／200% 文字與 Tab。

## 6. 觀察與除錯

教師先示範故意錯誤，再要求學生依序寫下「症狀 → 證據 → 假設 → 單一修正 → 重新驗證」。本堂常見錯誤是：把 absolute 放在錯誤父層、忘記 sticky 的 top、讓 fixed CTA 沒有底部留白，或用 z-index 蓋住焦點，透過畫面、Elements 與 Computed 找出原因。

## 7. 學生任務

### 教師完整示範

示範 先比較 normal flow 與 relative，再用 relative card 放置 absolute badge，最後觀察 sticky header、fixed CTA、z-index 與鍵盤 focus。；每次只修改一個檔案或區塊，先讓學生預測，再立即回到畫面、DOM、Console、Network 或資料結果。

### 學生跟做

把教師示範拆成三到四個 10–15 分鐘微任務：先完成入口，再完成核心修改，接著重現錯誤，最後留下驗收證據。學生必須在自己的資料夾重現，不以講師畫面成功為完成。

### 情境變體

將 fixed 聯絡入口改成預約諮詢提示，保留內容底部留白，並在 390px 與 200% 文字放大下重做驗收。

### 獨立挑戰

不看 Solution，替另一個服務型商家完成「用 Position 控制元素參考點、捲動行為與前後層級」，並留下 normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus 的驗收證據。

### 驗收證據

normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px／200% 文字與鍵盤 focus。學生需提交修改檔案清單、操作步驟、預期結果、實際觀察與一項可重現證據。

### 離場前回顧

請學生回答：我理解了什麼？我做出了什麼？我用什麼證據確認？下一堂會接著處理什麼？

下堂銜接：狀態與無障礙：下一堂會把 focus、hover 與表單錯誤狀態整理成可操作的介面回饋。

### 官方來源補充

- [MDN：CSS positioning](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Positioning)
- [MDN：Containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Display/Containing_block)
- [MDN：Understanding z-index](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Positioned_layout/Understanding_z-index)
- [W3C：WCAG 2.2](https://www.w3.org/TR/WCAG22/)
