定位

定位允許您將元素從正常的文件流中取出,並使其表現出不同的行為,例如,彼此疊加或始終保持在瀏覽器視口內的相同位置。本文介紹了不同的position值以及如何使用它們。

先決條件 HTML 基礎知識(學習HTML 簡介),以及 CSS 工作原理的概念(學習CSS 簡介)。
目標 瞭解 CSS 定位的工作原理。

我們希望您在本地計算機上完成以下練習。如果可能,請從我們的 GitHub 倉庫中獲取0_basic-flow.html的副本(此處檢視原始碼),並將其作為起點。

介紹定位

定位允許我們透過覆蓋正常的文件流來產生有趣的結果。如果您想稍微更改一些盒子的位置,使其偏離預設的流位置,以營造出略帶古怪、破舊的感覺,該怎麼辦?定位就是您的工具。或者,如果您想建立一個 UI 元素,使其浮動在頁面其他部分的頂部,並且/或者始終位於瀏覽器視窗內的相同位置,無論頁面滾動多少,該怎麼辦?定位使這種佈局工作成為可能。

您可以對 HTML 元素應用多種不同型別的定位。要使特定型別的定位對元素生效,我們使用position屬性。

靜態定位

要檢視這一點(併為將來的部分設定示例),首先在 HTML 中的第二個<p>中新增一個名為 positionedclass

靜態定位是每個元素都具有的預設值。它只是意味著“將元素放置到文件流中的正常位置——這裡沒有什麼特別之處”。

html
<p class="positioned"></p>

現在將以下規則新增到 CSS 的底部

css
.positioned {
  position: static;
  background: yellow;
}

如果儲存並重新整理,您將看不到任何差異,除了更新了第二段的背景顏色。這很好——正如我們之前所說,靜態定位是預設行為!

注意:您可以在1_static-positioning.html檢視原始碼)處檢視此示例。

相對定位

相對定位是我們將要檢視的第一種定位型別。這與靜態定位非常相似,除了定位元素在正常流中佔據其位置後,您可以修改其最終位置,包括使其與頁面上的其他元素重疊。繼續更新程式碼中的position宣告

css
position: relative;

如果在此階段儲存並重新整理,您將根本看不到結果發生變化。那麼如何修改元素的位置呢?您需要使用topbottomleftright屬性,我們將在下一節中解釋這些屬性。

介紹 top、bottom、left 和 right

topbottomleftrightposition一起使用,以精確指定將定位元素移動到哪裡。要嘗試此操作,請將以下宣告新增到 CSS 中的.positioned規則中

css
top: 30px;
left: 30px;

注意:這些屬性的值可以採用您合理期望的任何單位:畫素、毫米、rem、% 等。

如果您現在儲存並重新整理,您將得到類似於以下的結果

很酷,是嗎?好的,這可能不是您期望的結果。如果我們指定了topleft,為什麼它會移動到底部和右側?這可能看起來違反直覺。您需要將其視為一種無形的力量,它會推動定位框的指定邊,使其向相反方向移動。例如,如果您指定top: 30px;,則就像一股力會推動框的頂部,導致它向下移動 30px。

注意:您可以在2_relative-positioning.html檢視原始碼)處檢視此示例。

絕對定位

絕對定位會帶來截然不同的結果。

設定 position: absolute

讓我們嘗試如下更改程式碼中的 position 宣告

css
position: absolute;

如果您現在儲存並重新整理,您應該會看到如下所示的內容

首先,請注意,文件流中定位元素應該存在的間隙不再存在——第一個和第三個元素已經合在一起,就像它不再存在一樣!好吧,從某種意義上說,這是真的。絕對定位的元素不再存在於正常的文件流中。相反,它位於自己的圖層上,與其他所有內容分離。這非常有用:這意味著我們可以建立獨立的 UI 功能,這些功能不會干擾頁面上其他元素的佈局。例如,彈出資訊框、控制選單、懸停面板、可以在頁面上任何位置拖放的 UI 功能等等。

其次,請注意元素的位置已更改。這是因為topbottomleftright在絕對定位中具有不同的行為。它們不是根據元素在正常文件流中的相對位置來定位元素,而是指定元素距包含元素各邊的距離。因此,在本例中,我們說絕對定位的元素應位於“包含元素”頂部 30px 處和左側 30px 處。(在本例中,“包含元素”是初始包含塊。有關更多資訊,請參閱下面的部分)

注意:如果需要,您可以使用topbottomleftright來調整元素的大小。嘗試在您的定位元素上設定top: 0; bottom: 0; left: 0; right: 0;margin: 0;,看看會發生什麼!之後再放回去……

注意:是的,邊距仍然會影響定位元素。但是,邊距摺疊不會。

注意:您可以在3_absolute-positioning.html檢視原始碼)處檢視此示例。

定位上下文

絕對定位元素的“包含元素”是哪個元素?這在很大程度上取決於定位元素的祖先元素的 position 屬性(請參閱確定包含塊)。

如果祖先元素的 position 屬性沒有明確定義,則預設情況下所有祖先元素都將具有靜態位置。其結果是絕對定位的元素將包含在初始包含塊中。初始包含塊具有視口的大小,也是包含<html>元素的塊。換句話說,絕對定位的元素將顯示在<html>元素之外,並相對於初始視口進行定位。

定位元素巢狀在 HTML 原始碼中的<body>中,但在最終佈局中,它距頁面頂部和左側邊緣 30px。我們可以更改定位上下文,即絕對定位元素相對於哪個元素進行定位。這是透過在元素的某個祖先元素上設定定位來完成的:在它巢狀其中的某個元素上(您不能將其相對於它未巢狀其中的元素進行定位)。要檢視這一點,請將以下宣告新增到您的body規則中

css
position: relative;

這應該會產生以下結果

定位元素現在相對於<body>元素進行定位。

注意:您可以在4_positioning-context.html檢視原始碼)處檢視此示例。

介紹 z-index

所有這些絕對定位都很有趣,但我們還沒有考慮另一個功能。當元素開始重疊時,是什麼決定了哪些元素出現在其他元素之上,哪些元素出現在其他元素之下?在我們到目前為止看到的示例中,我們只有一個定位上下文中的定位元素,並且它出現在頂部,因為定位元素優先於非定位元素。那麼當我們有多個時呢?

嘗試將以下內容新增到您的 CSS 中,使第一段也成為絕對定位的

css
p:nth-of-type(1) {
  position: absolute;
  background: lime;
  top: 10px;
  right: 30px;
}

此時,您將看到第一段被著色為青檸色,移出了文件流,並稍微向上移動了一些。它也堆疊在原始的.positioned段落下方,這兩個段落重疊的地方。這是因為.positioned段落是源順序中的第二個段落,並且源順序中較後的定位元素優先於源順序中較早的定位元素。

您可以更改堆疊順序嗎?是的,您可以透過使用z-index屬性來實現。“z-index”是指 z 軸。您可能還記得課程中前面的一些內容,我們討論過網頁使用水平(x 軸)和垂直(y 軸)座標來計算背景影像和陰影偏移等內容的位置。對於從左到右執行的語言,(0,0) 位於頁面(或元素)的左上角,x 軸和 y 軸分別向右和向下延伸頁面。

網頁也有 z 軸:一條假想的線,從螢幕表面朝向您的臉部(或您喜歡放在螢幕前面的任何其他東西)。z-index值會影響定位元素在此軸上的位置;正值將它們向上移動到堆疊中,負值將它們向下移動到堆疊中。預設情況下,所有定位元素的z-index都為auto,實際上為 0。

要更改堆疊順序,請嘗試將以下宣告新增到您的p:nth-of-type(1)規則中

css
z-index: 1;

您現在應該看到青檸色的段落位於頂部

請注意,z-index僅接受無單位的索引值;您不能指定希望一個元素在 Z 軸上向上移動 23 畫素——它不這樣工作。較高的值將位於較低值之上,使用什麼值由您決定。使用 2 或 3 的值將與使用 300 或 40000 的值產生相同的效果。

注意:您可以在 5_z-index.html (檢視原始碼) 中檢視此內容的示例。

固定定位

現在讓我們來看一下固定定位。它的工作原理與絕對定位完全相同,但有一個關鍵區別:絕對定位將元素相對於其最近的已定位祖先(如果沒有則為初始包含塊)固定在適當位置,而固定定位通常將元素相對於視口可見部分固定在適當位置。(如果元素的祖先之一是固定包含塊,因為其 transform 屬性 的值不是 none,則會出現例外情況。)這意味著您可以建立有用的固定在適當位置的 UI 專案,例如始終可見的持久導航選單,無論頁面滾動多少。

讓我們構建一個簡單的示例來說明我們的意思。首先,從您的 CSS 中刪除現有的 p:nth-of-type(1).positioned 規則。

現在更新 body 規則以刪除 position: relative; 宣告並新增一個固定高度,如下所示

css
body {
  width: 500px;
  height: 1400px;
  margin: 0 auto;
}

現在,我們將為 h1 元素新增 position: fixed; 並將其置於視口頂部。將以下規則新增到您的 CSS 中

css
h1 {
  position: fixed;
  top: 0;
  width: 500px;
  margin-top: 0;
  background: white;
  padding: 10px;
}

需要 top: 0; 使其貼上到螢幕頂部。我們為標題賦予與內容列相同的寬度,然後賦予白色背景以及一些填充和邊距,以便內容不會在其下方可見。

如果儲存並重新整理,您將看到標題保持固定的有趣效果——內容似乎向上滾動並在其下方消失。但是請注意,某些內容最初是如何在標題下被裁剪的。這是因為已定位的標題不再出現在文件流中,因此其餘內容向上移動到頂部。我們可以透過將所有段落向下移動一點來改進這一點。我們可以透過在第一個段落上設定一些頂部邊距來實現。現在新增此內容

css
p:nth-of-type(1) {
  margin-top: 60px;
}

您現在應該可以看到完成的示例

注意:您可以在 6_fixed-positioning.html (檢視原始碼) 中檢視此內容的示例。

粘性定位

還有另一個可用的位置值稱為 position: sticky,它比其他值更新一些。這基本上是相對定位和固定定位的混合體。它允許已定位的元素像相對定位一樣工作,直到滾動到某個閾值(例如,距視口頂部 10px),然後它會變成固定定位。

基本示例

例如,可以使用粘性定位使導航欄隨著頁面滾動,直到某個點,然後貼上到頁面頂部。

css
.positioned {
  position: sticky;
  top: 30px;
  left: 30px;
}

滾動索引

position: sticky 的一個有趣且常見的用法是建立一個滾動索引頁面,其中不同的標題在到達時會貼上到頁面頂部。此類示例的標記可能如下所示

html
<h1>Sticky positioning</h1>

<dl>
  <dt>A</dt>
  <dd>Apple</dd>
  <dd>Ant</dd>
  <dd>Altimeter</dd>
  <dd>Airplane</dd>
  <dt>B</dt>
  <dd>Bird</dd>
  <dd>Buzzard</dd>
  <dd>Bee</dd>
  <dd>Banana</dd>
  <dd>Beanstalk</dd>
  <dt>C</dt>
  <dd>Calculator</dd>
  <dd>Cane</dd>
  <dd>Camera</dd>
  <dd>Camel</dd>
  <dt>D</dt>
  <dd>Duck</dd>
  <dd>Dime</dd>
  <dd>Dipstick</dd>
  <dd>Drone</dd>
  <dt>E</dt>
  <dd>Egg</dd>
  <dd>Elephant</dd>
  <dd>Egret</dd>
</dl>

CSS 可能如下所示。在正常流中,<dt> 元素將與內容一起滾動。當我們向 <dt> 元素新增 position: sticky 以及 top 值為 0 時,支援的瀏覽器會在標題到達該位置時將其貼上到視口頂部。然後,每個後續標題在向上滾動到該位置時將替換上一個標題。

css
dt {
  background-color: black;
  color: white;
  padding: 10px;
  position: sticky;
  top: 0;
  left: 0;
  margin: 1em 0;
}

粘性元素相對於具有“滾動機制”的最近祖先而言是“粘性”的,這由其祖先的 overflow 屬性決定。

注意:您可以在 7_sticky-positioning.html (檢視原始碼) 中檢視此示例。

測試你的技能!

您已閱讀完本文,但您還記得最重要的資訊嗎?在繼續之前,您可以找到一些進一步的測試來驗證您是否保留了這些資訊——請參閱 測試您的技能:定位

總結

我相信您玩基本定位玩得很開心。雖然它不是用於整個佈局的理想方法,但它適合許多特定的目標。

另請參閱