LESSON-11 · 零基礎學生教材
CSS 進階:Position、Sticky 與堆疊
完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口;重疊層級清楚,窄版與鍵盤焦點不被遮住。
先理解:這堂課解決什麼問題?
商家希望在服務頁標出推薦方案,並讓聯絡入口在長頁面中保持可找到。
本堂要完成:完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口;重疊層級清楚,窄版與鍵盤焦點不被遮住。
學習邊界:先完成「用 Position 控制元素參考點、捲動行為與前後層級」,不提前引入尚未教過的框架或建置工具。
第一次上課環境:先理解瀏覽器、CSS 與證據
- 瀏覽器:開啟
examples/01-flow-relative.html;瀏覽器會讀 HTML、套用 CSS,建立你看到的畫面。 - 檔案:本堂只使用
index.html、style.css與examples/;不需要 npm、框架或 JavaScript。 - DevTools:在頁面按右鍵選「檢查」,Elements 看 HTML 階層,Styles 看命中的規則,Computed 看瀏覽器最後採用的 position、top、z-index 與 overflow。
- 操作習慣:每次先預測,再只修改一個 selector;儲存、重新整理、捲動或按 Tab,最後用畫面與 DevTools 證明結果。
先做最小實驗:先看見結果
這不是期末網站,而是一個可以直接看到本堂核心結果的最小實驗。先完成一次操作,再回到檔案和名詞卡對照。
- 入口:開啟
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 暫時修改只要重新整理即可清除。
學生練習流程
依序完成每一張卡;目前只聚焦一個步驟,先操作,再用可觀察證據確認結果。
-
1
名詞
先閱讀檔案地圖與名詞卡,說出 normal flow、viewport、containing block 與 z-index 的白話意思。 -
2
驗收
依序開啟examples/01-flow-relative.html到examples/04-fixed-z-index-focus.html;每個實驗都完成「目的 → 操作 → 預期結果 → DevTools 證據 → 卡住時檢查」。 -
3
Starter
把 Starter 複製到自己的資料夾,依四張微步驟卡完成:relative、absolute badge、sticky、fixed/z-index/focus;每次只修改一個檔案責任。 -
4
Checkpoint
前往 Checkpoint,先預測 badge 沒有 relative 父層時的 containing block,再在style.css修正唯一的 CHECKPOINT-1。 -
5
Solution
前往 Solution,逐檔對照完整 absolute、sticky、fixed、z-index、底部留白與 focus-visible;用 390px、桌機、200% 文字與純 Tab 完成最後驗收。 -
6
變體驗收
完成情境變體與獨立挑戰,留下檔案位置、操作、預期結果、實際觀察與截圖/Computed 證據,並閱讀下一堂銜接:狀態與無障礙:下一堂會把 focus、hover 與表單錯誤狀態整理成可操作的介面回饋。
檔案地圖:每個位置負責什麼?
先不要急著背檔名;請把檔案位置和責任連起來。你在階段頁會看到同一份檔案的可執行版本。
index.html首頁入口:呈現商家第一印象與主要 CTA。style.cssCSS 樣式檔:放置本堂「用 Position 控制元素參考點、捲動行為與前後層級」相關的版面規則。examples/資料夾位置:存放本堂會被頁面引用的檔案。
先學會這些詞
先從名詞、英文與白話意思開始;每次只展開一張名詞卡,再對照正式定義、範例與驗收證據。專業術語、語法、檔案路徑會使用不同樣式。第一次遇到術語時,先回到這裡,不要靠猜。
定位基礎
6 個詞normal flownormal flow 白話意思:瀏覽器沒有額外定位時,元素依 HTML 順序自然排列。 展開查看正式定義、範例與驗收證據
- 正式定義
- 文件中未被特殊定位方式移出的元素,依區塊與行內排版規則佔據原本空間的排列方式。
- 什麼時候用
- 要先預測元素原本會在哪裡,或比較 relative 是否保留空間時。
- 最小範例
- 兩張卡片依序出現;前一張改變外觀不會讓後一張消失。
- 可觀察證據
- Elements 順序、畫面位置,以及第二張卡片是否仍從原本位置開始。
- 容易混淆
- 和 viewport 混淆;normal flow 是文件內的排列規則,不是視窗座標。
staticposition: static 白話意思:元素使用瀏覽器預設的普通排列方式。 展開查看正式定義、範例與驗收證據
- 正式定義
- position 的預設值;元素留在 normal flow 中,top、right、bottom、left 不會移動它。
- 什麼時候用
- 不需要特殊定位,只想讓元素依內容順序排列時。
- 最小範例
.flow-card { position: static; }- 可觀察證據
- Computed 的 position 是 static,設定 top 後畫面仍不位移。
- 容易混淆
- 和 relative 混淆;relative 會接受 offset,static 不會。
relativeposition: relative 白話意思:先留在原本位置,再從原位做小幅位移。 展開查看正式定義、範例與驗收證據
- 正式定義
- 元素仍占據 normal flow 原本的空間,但可依 offset properties 相對自身原位置移動;也能成為 absolute 子元素的 containing block。
- 什麼時候用
- 要微調元素,或要讓卡片成為徽章的定位參考時。
- 最小範例
.service-card { position: relative; }- 可觀察證據
- 卡片移動後原空間仍存在;子層 badge 以卡片角落為參考。
- 容易混淆
- 和 absolute 混淆;relative 保留自己的流內空間,absolute 通常不保留。
absoluteposition: absolute 白話意思:把元素從普通排列中拿出來,放到指定參考盒子的座標。 展開查看正式定義、範例與驗收證據
- 正式定義
- 元素不再占據 normal flow 的空間,位置通常相對最近的 positioned ancestor;若沒有,則繼續尋找更高層的 containing block。
- 什麼時候用
- 徽章、裝飾或卡片內的角標需要貼在父層角落時。
- 最小範例
.featured-badge { position: absolute; top: .75rem; right: .75rem; }- 可觀察證據
- badge 不會把標題往下推,並隨 relative card 一起移動。
- 容易混淆
- 和 fixed 混淆;absolute 的參考可由祖先元素改變,fixed 通常以 viewport 為參考。
containing blockcontaining 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 propertiestop / 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 參與盒子間距與流動排版。
黏附與固定
3 個詞stickyposition: 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。
fixedposition: fixed 白話意思:元素固定在瀏覽器視窗的位置,捲動內容時仍留在那裡。 展開查看正式定義、範例與驗收證據
- 正式定義
- 元素從 normal flow 移出,通常相對 viewport 定位;它不會替後面的內容保留空間。
- 什麼時候用
- 聯絡 CTA、客服按鈕或需要一直可找到的操作入口時。
- 最小範例
.floating-contact { position: fixed; right: 1rem; bottom: 1rem; }- 可觀察證據
- 捲動前後 CTA 都靠近視窗右下角,頁面內容另外用 padding-bottom 避免被遮住。
- 容易混淆
- 和 sticky 混淆;fixed 不會在某個流內自然停止,也不會自動替內容讓位。
viewportviewport 白話意思:瀏覽器目前用來顯示網頁的可視範圍。 展開查看正式定義、範例與驗收證據
- 正式定義
- 使用者代理程式呈現文件內容的視窗區域;fixed 元素通常以它作為定位參考。
- 什麼時候用
- 測試 fixed 位置、390px 窄版或 200% 文字放大時。
- 最小範例
- 在 DevTools 裝置模式切到 390px,再觀察 fixed CTA 的 right/bottom。
- 可觀察證據
- 視窗寬度、document 是否出現水平捲軸,以及 CTA 是否仍可讀可按。
- 容易混淆
- 和整個 HTML 文件高度混淆;viewport 是目前看得到的視窗區域。
層疊與驗收
4 個詞stacking contextstacking 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-indexz-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 不會自己讓元素重疊,也不會取代定位宣告。
overflowoverflow 白話意思:內容超出元素盒子時,決定要顯示、捲動或裁切的設定。 展開查看正式定義、範例與驗收證據
- 正式定義
- 控制內容超過盒子尺寸時的呈現方式;某些 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 讓鍵盤使用者看得到目前位置。
最小例子:先看懂,再複製
這段只保留本堂第一個微成果。先預測結果,再逐行讀;完整檔案請開啟下方最小實驗。
.flow-card--moved {
position: relative;
top: 1rem;
left: 1rem;
}Live Lab:逐段讀碼與驗證
每一步只回答五件事:為什麼做、改哪裡、會看到什麼、用什麼證據確認、卡住先查什麼。
-
Step 1
比較 normal flow 與 relative
- 目的
- 先知道元素原本如何排列,再觀察 relative 位移不會拿走原本空間。
- 修改位置
examples/01-flow-relative.html、style.css
.flow-card--moved { position: relative; top: 1rem; left: 1rem; }- 預期結果
- 第二張卡片視覺上往右下移動,但第三張卡片仍保留原本的排列位置。
- 驗收證據
- 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.service-card{ position: relative; } .featured-badge { position: absolute; top: .75rem; right: .75rem; }- 預期結果
- badge 貼在服務卡右上角,不推動標題;移動 card 時 badge 跟著 card。
- 驗收證據
- 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; }- 預期結果
- 捲動長頁面後 header 停在視窗上方;回到頂端時仍能回到原本的文件位置。
- 驗收證據
- 捲動前後畫面、Computed position: sticky、top: 0 與文件總高度。
- 卡住先查
- 先確認入口頁內容高度大於 viewport,再查看是否有祖先 overflow 改變捲動容器。
-
Step 4
完成 fixed、z-index 與 focus 驗收
- 目的
- 把固定 CTA、實際重疊的卡片與鍵盤焦點放在同一個可操作頁面中。
- 修改位置
index.html、style.css.page-shell{ padding-bottom: 6rem; } .stack-card--front { z-index: 2; }:focus-visible{ outline: 3px solid #1d4ed8; outline-offset: 3px; }- 預期結果
- CTA 固定在 viewport 右下角但不遮內容;兩張重疊卡片有可比較的前後層級;Tab focus 清楚可見。
- 驗收證據
- 捲動前後位置、兩張卡片的 Computed z-index、390px/200% 文字畫面與 Tab focus 截圖。
- 卡住先查
- 先分三件事看:CTA 是否 fixed、內容是否有 padding-bottom、焦點元素是否是 a 或 button。
-
Step 5
整合本堂驗收證據
- 目的
- 把前面完成的修改放回本堂任務,確認不是只修好單一畫面。
- 修改位置
examples/01-flow-relative.html與本堂驗收證據
依序檢查 normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px/200% 文字與鍵盤 focus,只記錄一個實際觀察,不新增本堂以外的技術。- 預期結果
- 完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口;重疊層級清楚,窄版與鍵盤焦點不被遮住。
- 驗收證據
- normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px/200% 文字與鍵盤 focus
- 卡住先查
- 先確認目前開啟的檔案名稱是
examples/01-flow-relative.html,並從導覽逐一開啟其餘三個檔案。
-
Step 6
完成最後回歸檢查
- 目的
- 用本堂的操作與驗收條件重跑一次,留下可以重現的結果。
- 修改位置
examples/01-flow-relative.html與本堂驗收證據
依序檢查 normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px/200% 文字與鍵盤 focus,只記錄一個實際觀察,不新增本堂以外的技術。- 預期結果
- 完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口;重疊層級清楚,窄版與鍵盤焦點不被遮住。
- 驗收證據
- normal flow 與 relative、absolute 包含區塊、sticky 捲動前後、fixed 遮蔽處理、z-index 重疊、390px/200% 文字與鍵盤 focus
- 卡住先查
- 先確認目前開啟的檔案名稱是
examples/01-flow-relative.html,並從導覽逐一開啟其餘三個檔案。
讀碼順序:先找入口,再用畫面、Elements、Styles、Computed、捲動前後與純 Tab 驗證;本堂不使用 JavaScript 載入訊息假裝證明 CSS 定位有效。
互動問答
先回答目前這一題,再展開解析;完成後按下一題,讓每一次回答都回到檔案或瀏覽器完成驗證。
Q1概念理解 「normal flow」在本堂要解決什麼問題? 本題線索:normal flow;回到名詞卡與 Elements 順序、畫面位置,以及第二張卡片是否仍從原本位置開始。 展開解析收合解析
白話解析:
瀏覽器沒有額外定位時,元素依 HTML 順序自然排列。 正式來說,文件中未被特殊定位方式移出的元素,依區塊與行內排版規則佔據原本空間的排列方式。
對照位置:
回到名詞卡「normal flow」,再看 Elements 順序、畫面位置,以及第二張卡片是否仍從原本位置開始。
預期觀察:
你應該能用自己的話說出:要先預測元素原本會在哪裡,或比較 relative 是否保留空間時。
常見錯誤:
不要只回答「它是normal flow」;那是重複名詞,不是說明責任。
立即驗證:
開啟 examples/01-flow-relative.html,依序做「依序開啟四個實驗:比較 normal flow/relative,暫時移除 containing block 的 relative,捲動 sticky,最後捲動 fixed 頁面並用 Tab 走過連結與按鈕。」並記下畫面或工具證據。
Q2程式碼閱讀
修改指定規則後,你預測畫面會看到什麼?
本題線索:examples/01-flow-relative.html、style.css;要修改:.flow-card--moved { position: relative; top: 1rem; left: 1rem; };觀察:Elements 的 DOM 順序、Computed position/top/left,以及第二、三張卡片的畫面位置。
展開解析收合解析
白話解析:
先看檔案責任,再預測結果。這一步的目的:先知道元素原本如何排列,再觀察 relative 位移不會拿走原本空間。
對照位置:
對照 Live Lab Step 1,位置是 examples/01-flow-relative.html、style.css;範例內容:.flow-card--moved {
position: relative;
top: 1rem;
left: 1rem;
}
預期觀察:
第二張卡片視覺上往右下移動,但第三張卡片仍保留原本的排列位置。
常見錯誤:
如果只改了檔案但沒有結果,先不要重寫全部;只檢查 .flow-card--moved 是否命中,並確認頁面目前真的載入這個 HTML。
立即驗證:
實際操作後檢查 Elements 的 DOM 順序、Computed position/top/left,以及第二、三張卡片的畫面位置。。
Q3概念比較
「normal flow」和「static」在本堂的責任有什麼不同?
本題線索:比較 normal flow 與 static;操作位置:index.html、style.css
展開解析收合解析
白話解析:
normal flow:瀏覽器沒有額外定位時,元素依 HTML 順序自然排列。;static:元素使用瀏覽器預設的普通排列方式。
對照位置:
對照兩張名詞卡的正式定義:文件中未被特殊定位方式移出的元素,依區塊與行內排版規則佔據原本空間的排列方式。/position 的預設值;元素留在 normal flow 中,top、right、bottom、left 不會移動它。
預期觀察:
你應該能指出兩者分別出現在哪個檔案或工具,以及哪一個結果會改變。
常見錯誤:
不要把「改變畫面」當成所有技術的責任;先說清楚誰負責結構、呈現、行為或驗收。
立即驗證:
在 index.html、style.css 做「.service-card { position: relative; }
.featured-badge { position: absolute; top: .75rem; right: .75rem; }」,再用 Elements 的父子關係、Computed 的 position,以及 badge 與 card 的相對角落。 比較前後差異。
Q4除錯驗收
如果完成操作後結果不對,你會先從哪一個證據開始查?
本題線索:index.html、style.css;第一個檢查位置:捲動前後位置、兩張卡片的 Computed z-index、390px/200% 文字畫面與 Tab focus 截圖。
展開解析收合解析
白話解析:
先描述症狀,再提出一個最小假設。本堂常見錯誤是:只增加很大的 z-index,卻沒有重疊元素、底部留白或可聚焦的真實控制項。
對照位置:
對照最後一段 Live Lab:index.html、style.css;檢查方式:先分三件事看:CTA 是否 fixed、內容是否有 padding-bottom、焦點元素是否是 a 或 button。
預期觀察:
你要能指出一個具體位置,而不是一次修改很多檔案。
常見錯誤:
不要先清快取、重裝工具或複製 Solution;先查看第一個可觀察錯誤。
立即驗證:
重新操作並留下「症狀、證據、假設、單一修正、結果」五項紀錄。
常見誤解
- 看到畫面沒有變化,不代表程式沒執行;先確認檔案、路徑、元素與狀態證據。
- 能複製 Solution 不代表理解;請先說出修改哪個檔案、預期哪個結果、用什麼證據確認。
- 本堂只使用既定的 HTML、CSS、JavaScript、Vue CDN、Apps Script mock 與 Cloudflare Pages 驗收範圍。
本堂任務與驗收
完成推薦徽章、可捲動的 sticky 頁首與 fixed 聯絡入口;重疊層級清楚,窄版與鍵盤焦點不被遮住。
- 能用 normal flow 與 relative 留下可重現證據。
- 能用 absolute 包含區塊 留下可重現證據。
- 能用 sticky 捲動前後 留下可重現證據。
- 能用 fixed 遮蔽處理 留下可重現證據。
- 能用 z-index 重疊 留下可重現證據。
- 能用 390px/200% 文字與鍵盤 focus 留下可重現證據。
- Starter、Checkpoint、Solution 的入口都能開啟並知道三者差異。
- 遇到問題時能先寫出症狀,再檢查一個最小假設。
官方延伸閱讀
下載講師版 Markdown:需要授課或離線查閱時使用,內容包含完整教學節奏。