1. 程式人生 > 其它 >【Web前端HTML5&CSS3】11-定位的簡介

【Web前端HTML5&CSS3】11-定位的簡介

定位的簡介

需求分析

按照我們之前所學知識,可以怎麼實現呢?

應該來說不難,很容易實現

CSS
.box2 {
  width: 200px;
  height: 200px;
  background-color: yellow;
  /* 左外邊距、上外邊距 */
  margin-left: 200px;
  margin-top: -200px;
}

.box3 {
  width: 200px;
  height: 200px;
  background-color: orange;
  /* 上外邊距 */
  margin-top: 200px;
}

我們分別給 box2 和 box3 添加了外邊距之後,就可以達到需求效果

當然也可以使用浮動來解決上述問題,但稍微麻煩一點

不管怎樣,問題也是顯而易見。我們實際開發中,頁面上的元素可能很多,這樣改必然是 牽一髮而動全身

那麼僅僅靠我們之前學習的佈局知識,不足以輕鬆應對這種場景

那麼就勢必需要一個方便我們處理這種場景的辦法,它就是定位

定位(position)

定位是一種更加高階的佈局手段

通過定位可以將元素擺放到頁面的任意位置

使用position屬性來設定定位

可選值 含義
static 不開啟定位,元素是靜止的,預設值
relative 開啟元素的相對定位
absolute 開啟元素的絕對定位
fixed 開啟元素的固定定位
sticky
開啟元素的粘滯定位

1. 相對定位

當元素的 position 屬性值設定為relative時,則開啟了元素的相對定位

偏移量(offset)

當元素開啟相對定位以後,可以通過偏移量來設定元素的位置

offset 屬性 含義
top 定位元素和定位位置的上邊距離
bottom 定位元素和定位位置的下邊距離
left 定位元素和定位位置的左側距離
right 定位元素和定位位置的右側距離

定位元素垂直方向的位置由topbottom兩個屬性控制,通常情況下只會使用其中之一

  • top值越大,定位元素越靠下
  • bottom值越大,定位元素靠上

定位元素水平方向的位置由left

right兩個屬性控制,通常情況下只會使用其中之一

  • left越大,定位元素越靠右
  • right越大,定位元素越靠左
CSS
.box2 {
  width: 200px;
  height: 200px;
  background-color: yellow;
  /* 開啟相對定位 */
  position: relative;
  top: -200px;
  left: 200px;
}

我們給 box2 設定相對定位,就得到了我們想要的頁面效果

可以看出,使用了相對定位後,只會移動自身的佈局位置,而不會對已存在的其他元素產生任何影響

相對定位的特點

  1. 當元素開啟相對定位以後,如果不設定偏移量元素,則元素不會發生任何變化(這裡注意,不僅僅是位置)

  2. 相對定位是參照於元素在文件流中的位置進行定位的(可以理解為相對於自身原始位置)

  3. 相對定位會提升元素的層級(表現為可以覆蓋其他元素)

  4. 相對定位不會改變元素的性質:塊還是塊,行內還是行內

Q1:如果給上述三個 div 都設定相對定位,那麼它們的層級關係會是什麼樣的呢?或者說誰會被誰覆蓋呢?

可以看到覆蓋關係是:box3 >> box2 >> box1

我們再稍微調整下 box3 和 box2 的前後位置

會發現覆蓋關係變成了:box2 >> box3 >> box1

可以大概猜測:在頁面文件流中,越靠下的元素開啟相對定位後,其層級越高 (這裡也只是我個人的揣測,待後續學習中驗證)(在後續學習中已得到驗證:沒有設定層級或層級z-index設定相同值時,優先顯示靠下的元素)

Q2:相對定位的第三個特點相對定位會提升元素的層級,是不是就類似於浮動一樣脫離了文件流?

A:我們可以對比下,浮動和相對定位的區別

  • 參考系不同:浮動的參考系是其父元素;相對定位是相對於自身
  • 可移動方向不同:浮動只能左右移動;相對定位是上下左右移動
  • 影響不同:浮動會影響頁面佈局(包括下方元素位置影響和高度塌陷問題);相對定位不對影響頁面佈局
  • 性質不同:浮動會改變元素的性質(不再獨佔一行,其寬高都會被內容撐開);相對定位不會改變元素的性質
  • 文字環繞:浮動不會覆蓋文字;相對定位可以覆蓋文字(這個可以自行驗證,不再贅述)

當然,浮動和相對定位也有其相似之處

  • 浮動和相對定位都是移動位置(貌似是廢話)
  • 浮動和相對定位不會從父元素中移出

可以看出,浮動和相對定位的區別是更多的

最後回答一點:浮動脫離了文件流,不再佔據頁面位置;相對定位仍然佔據頁面位置(所以怎麼能夠叫 脫離文件流 呢?)

Q3:相對定位的第四個特點相對定位不會改變元素的性質:塊還是塊,行內還是行內,但是上述例子中元素開啟相對定位後好像就不再獨佔一行了,這個怎麼理解?

A:相比於浮動元素的特點,相對定位不會改變元素的性質其實是一個相對不容易理解的問題。但其實也不難,可以把相對定位認為是元素的靈魂出竅。其位置發生改變以後,佈局並沒有產生影響,因為它的肉體(結構)仍然佔據著原來的那個位置。只是其靈魂(內容)發生了移動。

Q4:相對定位的第四個特點中塊還是塊,行內還是行內,意味著行內元素也可以使用相對定位是嗎?

A:眼見為實,耳聽為虛,直接看示例效果

2. 絕對定位

當元素的position屬性值設定為absolute時,則開啟了元素的絕對定位

絕對定位的特點

  1. 開啟絕對定位後,如果不設定偏移量,元素的位置不會發生變化
  2. 開啟絕對定位後,元素會從文件流中脫離
  3. 絕對定位會改變元素的性質:行內變成塊,塊的寬高被內容撐開(與相對定位相反)
  4. 絕對定位會使元素提升一個層級
  5. 絕對定位元素是相對於其包含塊進行定位的(與相對定位不同)

包含塊(containing block)

正常情況下:

  • 包含塊就是離當前元素最近的開啟了定位的祖先塊元素
  • 如果所有的祖先元素都沒有開啟定位,則html(根元素、初始包含塊)就是它的包含塊
HTML
<body>
  <!-- 如果box1開啟定位,則box2的包含塊是box1,否則就是body -->
  <div class="box1">
    <div class="box2"></div>
  </div>

  <!-- 如果box3開啟定位,則em的包含塊是box3,否則就是body -->
  <div class="box3">
    <span>
      <em>hello</em>
    </span>
  </div>
</body>

示例

HTML
<div class="box2">
  2
  <div class="box3">
    3
    <div class="box4">4</div>
  </div>
</div>
  • 不給 box2、box3 開起定位,box4 的包含塊是html
  • 只給 box3 開啟定位之後,box4 的包含塊是 box3
  • 只給 box2 開啟定位之後,box4 的包含塊是 box2
  • 給 box2、box3 都開起定位之後,box4 的包含塊是 box3

注意:這裡上述的條件是開啟定位,也就是說只要position不是static(預設值),那麼就滿足了其成為包含塊的必要條件

上述示例中,我們給其祖先元素都設定了相對定位。其實改成其他幾種定位方式也是可行的,我們可以看下面示例

這裡就不一一舉例了,大家可以對另外幾種定位方式進行驗證

水平方向的佈局

我們之前說過,水平方向的佈局等式:

margin-left + border-left + padding-left + width + padding-right + border-right + margin-right = 其父元素的寬度

當使用絕對定位時,需要新增leftright兩個值(此時規則和之前一樣,只是多添加了兩個值)

left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 其父元素的寬度

當發生過度約束時

  • 如果 9 個值中沒有auto,則自動調整right值以使等式滿足(之前 7 個值是margin-right
  • 如果 9 個值中有auto,則自動調整auto的值以使等式滿足

可設定auto的值:margin-left/margin-right /width /left /right

因為leftright的值預設是auto,所以如果沒有設定leftright,當等式不滿足時,則會自動調整這兩個值

水平居中

HTML
<style>
  .box1 {
    width: 500px;
    height: 500px;
    background-color: #bfa;
    position: relative;
  }

  .box2 {
    width: 100px;
    height: 100px;
    background-color: orange;
    /* 左右外邊距設定為auto */
    margin-left: auto;
    margin-right: auto;
    /* 絕對定位 */
    position: absolute;
    left: 0;
    right: 0;
  }
</style>

<div class="box1">
  <div class="box2"></div>
</div>

垂直方向的佈局

垂直方向佈局的等式的也必須要滿足

top + margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom + top = 其父元素的高度

垂直居中

CSS
.box2 {
  width: 100px;
  height: 100px;
  background-color: orange;
  /* 左右外邊距設定為auto */
  margin-top: auto;
  margin-bottom: auto;
  /* 絕對定位 */
  position: absolute;
  top: 0;
  bottom: 0;
}

水平垂直居中

目前,我們可以根據絕對定位進行元素的水平垂直雙方向居中,所以這個方法只是其中之一

CSS
.box2 {
  width: 100px;
  height: 100px;
  background-color: orange;
  /* 左右外邊距設定為auto */
  margin: auto;
  /* 絕對定位 */
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

小結

  • 水平佈局等式:left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 其父元素的寬度
  • 垂直佈局等式:top + margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom + top = 其父元素的高度
  • 上述等式的過度約束規則與《06-盒模型》中介紹的規則基本一致
  • 只是在沒有auto時,會自動調整top/bottom/left/right

3. 固定定位

將元素的position屬性設定為fixed,則開啟了元素的固定定位

固定定位的特點

固定定位也是一種絕對定位,所以固定定位的大部分特點都和絕對定位一樣

唯一不同的是,固定定位永遠參照於瀏覽器的視口(viewport,可視視窗)進行定位,不會隨網頁的滾動條滾動

示例

我們再給body設定一個較大的高度,讓瀏覽器滾動起來,看下效果

會發現,box4 並沒有因為滾動而發生未知的變化,這也驗證了上述知識,同時也應該明白了視口的概念

我們再對比下絕對定位

相信到這裡,大家應該又進一步地理解了固定定位與絕對定位的區別

因為固定定位跟絕對定位除了具有上述差別之後,其他的特點跟絕對定位是一樣的,所以這裡便不再贅述了

4. 粘滯定位

將元素的position屬性設定為sticky,則開啟了元素的固定定位

這次,我們換個方式,直接來看粘滯定位的效果

大家可以看到,右側邊欄部分在一定的情況下是固定的,滾動到上方一定位置開始發生變動

  • 該元素是根據文件流進行定位的,即相對於包含塊進行偏移
  • 偏移量不會影響任何其他元素的位置
  • 粘性元素總是“粘”到其最近的具有“滾動機制”的祖先元素(當overflowhiddenscrollautooverlay時建立),即使該祖先不是最近的實際滾動祖先

這裡可能最後一點比較難理解,彆著急,我們接著往下看

示例

我們拿之前的w3cschool頂部導航欄進行下魔改

CSS
/* 設定一個高度 */
body {
  height: 3000px;
}

.menu {
  width: 1211px;
  height: 48px;
  background-color: #e8e7e3;
  margin: 100px auto;
  /* 開啟粘滯定位 */
  position: sticky;
  top: 10px;
}

因為在視訊中老師並沒有對sticky屬性做過多的介紹,只是要求我們瞭解一下,因為在實際開發中,也是結合 js 去實現的,所以我這裡同樣也就不再深入帶大家一起看了

粘滯定位的特點

  • 粘滯定位和相對定位的特點基本一致(視訊中說是和相對定位一致,不過我對比了一下,很多特點是不同的,感覺倒是和固定定位更相似,這裡存疑)
  • 不同的是粘滯定位可以在元素到達某個位置時將其固定

需要注意的是,sticky屬性並不相容 IE(PS:不過微軟官方已經宣佈將在 2022 年停止對 IE 的維護,IE 將成為歷史。雖然我們經常詬病 IE,但作為當年瀏覽器的一霸,在廢棄多年後,不知道還會不會有所懷念,畢竟它代表著我們不斷逝去的青春)

5. 幾種定位的對比

我們通過上面的學習,知道position屬性有五個可選值

static是預設值,即不開啟定位,所以我們只需要對比 4 種定位方式即可

定位方式 是否不設定偏移量,元素不會發生改變 是否脫離文件流 是否改變元素性質 是否提升元素層級 參考系
relative(相對定位) × × 參照於元素在文件流中的位置
absolute(絕對定位) × 參照於其包含塊
fixed(固定定位) × 參照於瀏覽器的視口
sticky(粘滯定位) × 參照於瀏覽器的視口

6. 補充:元素層級

對於開啟了定位元素,可以通過z-index屬性來指定元素的層級

  • z-index需要一個整數作為引數,值越大元素的層級越高,元素的層級越高越優先顯示
  • 如果元素的層級一樣,則優先顯示靠下的元素
  • 祖先的元素的層級再高,也不會蓋住後代元素

示例

HTML
<style>
  div {
    font-size: 40px;
  }

  .box1 {
    width: 200px;
    height: 200px;
    background-color: #bfa;
    position: absolute;
    top: 0;
    left: 0;
  }

  .box2 {
    width: 200px;
    height: 200px;
    background-color: orange;
    position: absolute;
    top: 50px;
    left: 50px;
  }

  .box3 {
    width: 200px;
    height: 200px;
    background-color: salmon;
    position: absolute;
    top: 100px;
    left: 100px;
  }

  .box4 {
    width: 100px;
    height: 100px;
    background-color: skyblue;
    position: absolute;
    bottom: 0;
    left: 0;
  }
</style>

<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">
  3
  <div class="box4">4</div>
</div>

存疑問題

Q:浮動也有層級概念嗎?如果有,浮動和定位的層級關係是什麼樣的?

A:null / none / undefined 調了一下,出現幾種現象

  • float設定z-index多大都沒用,還是會被覆蓋
  • 預設情況,沒有設定z-index或設定z-index大小 ≥0 時,浮動層級沒有定位的層級高
  • 設定z-index<0 時,浮動層級可以定位的層級高

浮動層級(不知道有沒有這個概念,本身就是存疑問題,現在這種情況看起來應該是沒有這個概念了)

7. 總結

一般情況下,

  • 頁面的整體結構大多采用浮動、塊進行佈局
  • 頁面某些模組結構一般採用定位進行微調

8. 練習:京東輪播圖

css 程式碼

CSS
/* 整體居中 */
.box {
  width: 590px;
  height: 470px;
  /* 水平垂直雙方向居中 */
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

/* ======輪播圖Start====== */

.img_list li {
  /* 每個輪播圖絕對定位,讓其重疊 */
  position: absolute;
}

.img_list li:nth-child(1) {
  /* 目前還沒有學習js,暫時做成靜態切換層級 */
  z-index: 1;
}

/* 全域性影象大小 */
.img_list img {
  /* 我這裡之所以要設定寬高,是因為下載的圖片大小不全是一樣大的 */
  /* 但是一般情況下,這些圖片都會裁剪成統一大小,所以可以不用設定 */
  width: 590px;
  height: 470px;
}

/* ======輪播圖End====== */

/* ======輪播圓Start====== */

.circle_list {
  height: 20px;
  /* 開啟絕對定位 */
  position: absolute;
  bottom: 20px;
  left: 30px;
  z-index: 2;
  /* 參考京東原網頁,整體字型設定樣式,這種設定方式還不太懂 */
  /* 其實也可以不設定,不過每個輪播圓之間的間距跟原來就不太一樣了 */
  font-size: 0;
  text-align: center;
}

/* 輪播圓細節 */
.circle_list .circle {
  /* 這裡設定display: inline-block; 也是一樣的 */
  float: left;
  height: 8px;
  width: 8px;
  background-color: rgba(255, 255, 255, 0.4);
  margin-right: 4px;
  /* 畫圓,這個按照課程中的畫法,按照網頁原始碼調出來的有點問題 */
  background-clip: content-box;
  border: 3px transparent solid;
  border-radius: 50%;
}

/* 輪播圓懸浮效果 */
.circle_list .circle:hover,
.circle_list .circle:nth-child(1) {
  background-color: #fff;
  border: 3px rgba(0, 0, 0, 0.1) solid;
}

/* ======輪播圓End====== */

html 程式碼

HTML
<div class="box">
  <ul class="img_list">
    <li>
      <a href="#"><img src="assets/lbt/1.jpg" alt="" /></a>
    </li>
    <li>
      <a href="#"><img src="assets/lbt/2.jpg" alt="" /></a>
    </li>
    <li>
      <a href="#"><img src="assets/lbt/3.jpg" alt="" /></a>
    </li>
    <li>
      <a href="#"><img src="assets/lbt/4.jpg" alt="" /></a>
    </li>
    <li>
      <a href="#"><img src="assets/lbt/5.jpg" alt="" /></a>
    </li>
    <li>
      <a href="#"><img src="assets/lbt/6.jpg" alt="" /></a>
    </li>
    <li>
      <a href="#"><img src="assets/lbt/7.jpg" alt="" /></a>
    </li>
    <li>
      <a href="#"><img src="assets/lbt/8.jpg" alt="" /></a>
    </li>
  </ul>
  <!-- 我這裡結構並沒有完全按照課程中的結構來,但實現效果是一樣的 -->
  <ul class="circle_list">
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
    <li class="circle"></li>
  </ul>
</div>

別忘了,引入reset樣式

效果

等到後面學習了 js,就可以實現自動輪播了,到時候再補充完善

主要運用

  • 水平垂直雙方向居中(水平垂直方向等式)
  • absolute開啟絕對定位,使其重疊,達到隱藏效果
  • z-index設定層級,實現圖片輪播
  • border-radius畫圓,transparent邊框透明,background-clip:content-box隱藏邊框