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 15

定位

relative、absolute、fixed、sticky 與 z-index
Interaction 25 minute(s)

Learning Objectives

  • 說明一般流(normal flow)的排列方式,以及 position: static 的意思
  • 分辨 relative、absolute、fixed、sticky:是否留在一般流、相對於哪一個包含區塊
  • 用 top、right、bottom、left 指定位移,並找出 absolute 元素的包含區塊(最近的非 static 祖先)
  • 用 z-index 調整重疊的順序,說出 z-index 只對有定位的元素有效,並知道堆疊環境的存在
  • 做出卡片角落的標籤、黏在上方的頁首、固定在畫面角落的按鈕

讓元素離開一般的排列

到目前為止,元素都是一個接一個排好:區塊從上到下,行內元素從左到右。這種排列方式叫做一般流(normal flow), 元素彼此不會重疊,前面的元素變高,後面的元素就往下移。

但有些設計需要「疊上去」:

設計 需要的效果
卡片右上角的「NEW」標籤 貼在卡片角落,不佔卡片內文的空間
捲動時一直留在上方的頁首 捲到它的時候黏住,不跟著捲走
畫面右下角的「回到頂端」或「報名」按鈕 不管捲到哪裡都在同一個位置
下拉選單、提示框 蓋在其他內容上面

這些都由 position 屬性處理。它是 CSS 裡最容易「一改就整頁亂掉」的屬性,關鍵在於弄清楚每個值相對於誰定位。

position 的五個值

值 還在一般流裡嗎(保留空間) top、left… 相對於 常見用途
static(預設) 是 沒有作用 一般內容
relative 是,原本的空間保留 自己原本的位置 微調位置;當 absolute 子元素的參考點
absolute 否,不佔空間 最近一個 position 不是 static 的祖先 角落標籤、下拉選單
fixed 否 視窗(viewport),捲動也不動 固定頁首、浮動按鈕
sticky 是 平常像 relative;捲到門檻時黏在捲動容器的邊緣 黏在上方的頁首、表格標題列

搭配的四個屬性 top、right、bottom、left 表示從參考邊緣往內的距離:

.badge {
  position: absolute;
  top: 8px;      /* 離包含區塊的上緣 8px */
  right: 8px;    /* 離包含區塊的右緣 8px */
}

同一個方向通常只寫一個(top 或 bottom、left 或 right)。position: static 的元素寫這四個屬性完全沒有作用,這是最常見的「怎麼改都不動」的原因。

relative、absolute 與包含區塊

relative:元素先照一般流排好,畫的時候再位移。原本的空間還在,旁邊的元素不會補上來,所以位移後可能和別人重疊。

.note { position: relative; top: 10px; left: 20px; }   /* 往下 10px、往右 20px */

absolute:元素離開一般流,不佔空間,後面的元素會補上它原本的位置。它的位置相對於包含區塊(containing block): 從父元素開始往上找,第一個 position 不是 static 的祖先,以它的 padding 邊緣為準。 如果一路找到最外層都是 static,就以初始包含區塊為準:大小和視窗一樣、從網頁最上方開始的區域。

所以最常見的寫法是父層設 relative(不寫任何位移,只是當參考點),子層設 absolute:

.card  { position: relative; }                           /* 當參考點,自己不會移動 */
.badge { position: absolute; top: 8px; right: 8px; }     /* 貼在 .card 的右上角 */

忘了給 .card 設 relative,標籤就會一路往上找,最後跑到整個網頁的右上角。

定位實驗

左邊(窄螢幕在上方)是一個有自己視窗的小網頁。選一個目標,切換 position 與位移;紅色虛線框是這個目標的包含區塊,relative 的灰色虛線是它原本的位置。可以在預覽裡捲動,或按「預覽往下捲 60px」。依序完成任務。

小測驗:relative 與 absolute

1.

一個段落設了 position: relative; top: 20px;,它後面的段落會怎樣?

2.

.badge { position: absolute; top: 0; right: 0; }。它的父元素是 static,祖父元素是 position: relative,再上一層也是 relative。標籤會貼在誰的右上角?

3.

把一個段落改成 position: absolute;,但沒有寫 top、left。會發生什麼事?

第 1 次作答

fixed 與 sticky

fixed 相對於視窗定位,網頁捲動時它不動:

.back-to-top { position: fixed; right: 16px; bottom: 16px; }   /* 永遠在畫面右下角 */
.site-header { position: fixed; top: 0; left: 0; right: 0; }  /* 固定在最上方、左右撐滿 */
body { padding-top: 56px; }   /* fixed 不佔空間:要留出頁首的高度,否則第一段內容會被頁首蓋住 */

sticky 平常留在一般流裡,捲動到你設定的門檻時黏住:

.site-header { position: sticky; top: 0; }   /* 捲到頂端時黏在上緣 */
  • 一定要寫門檻(top、bottom 等至少一個),沒寫的話它就和 relative 一樣,不會黏住。
  • 它只在父元素的範圍內黏住:父元素捲出畫面時,它也跟著被帶走。所以 sticky 的頁首通常放在 body 底下,不要包在一個矮的容器裡。
  • 它黏在最近一個會捲動的祖先(overflow 是 hidden、scroll、auto 的元素)上;某個祖先設了 overflow: hidden,常會讓 sticky 看起來「失效」。

fixed 的頁首會一直佔著畫面高度;手機畫面不大,固定的頁首與按鈕要盡量矮、盡量少。

z-index:誰疊在上面

元素重疊時,預設的順序是:有定位的元素蓋在沒定位的上面;同樣有定位的,HTML 裡寫在後面的蓋在上面。 要改變順序,用 z-index,數字大的在上面:

.site-header { position: sticky; top: 0; z-index: 10; }   /* 捲動時蓋在內容上面 */
.dropdown    { position: absolute; z-index: 20; }
  • z-index 只對有定位的元素(position 不是 static)有效;Flex 與 Grid 的項目也可以用。對一般的 static 元素寫 z-index 沒有作用。
  • 可以是負數;auto 是預設值。

堆疊環境(stacking context):一個元素設了 z-index(且有定位),或設了 opacity 小於 1、transform 等屬性時,會形成一個自己的堆疊環境, 裡面的子元素的 z-index 只在這個環境裡面比。所以子元素寫 z-index: 9999 也蓋不過父元素外面一個 z-index 比父元素大的元素。 遇到「z-index 設多大都沒用」,先檢查它的祖先是不是形成了堆疊環境。

互動練習:角落標籤與浮動按鈕

「NEW」標籤擠在標題前面,「報名」按鈕跟著內容捲走。用定位把標籤放到卡片右上角,把按鈕固定在預覽的右下角。修改 CSS 後按「執行」。

互動練習:黏在上方的頁首

這份課程筆記的頁首一捲就不見了。讓它黏在上方,並確認捲動時示意圖不會蓋過頁首。修改 CSS 後按「執行」,在預覽裡往下捲動看看。

小測驗:fixed、sticky 與 z-index

1.

對一個沒有設定 position 的 <div> 寫 z-index: 100;,它還是被別的元素蓋住。原因是?

2.

寫了 .header { position: sticky; },捲動時頁首沒有黏住。最可能少了什麼?

3.

頁首改成 position: fixed; top: 0; 之後,網頁的第一段內容被頁首蓋住。合適的修正是?

4.

兩個重疊的方塊都是 position: relative,都沒有設 z-index。哪一個在上面?

第 1 次作答

重點整理

  • 一般流:區塊從上到下、行內從左到右,彼此不重疊;static 是預設值,top、left 與 z-index 都沒有作用。
  • relative:相對於自己原本的位置位移,原本的空間保留。
  • absolute:離開一般流,相對於最近一個 position 不是 static 的祖先;常見寫法是父層 relative、子層 absolute。
  • fixed:相對於視窗,捲動也不動;記得替被蓋住的內容留空間。
  • sticky:平常在一般流裡,捲到門檻(一定要寫 top 等)時黏住,只在父元素範圍內有效。
  • z-index 數字大的在上面,只對有定位的元素(與 Flex、Grid 項目)有效;它只在同一個堆疊環境裡比較。

下一課講溢位、顯示與浮動:內容比盒子大時怎麼處理、隱藏元素的幾種方式,以及舊時代用 float 排版的方法。

這一課完成了!
Next lesson:溢位、顯示與浮動
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。