你可能不知道的絕對定位

XboxYan發表於2023-02-27
歡迎關注我的公眾號:前端偵探

分享一個關於絕對定位的實戰開發經驗。

在普遍的認知下,絕對定位好像都是伴隨著偏移屬性(left/right/top/bottom)一起出現的,相信大家都寫過這樣的CSS,如下

el{
  position: absolute;
  left: 0;
  top: 0;
}

其實,有些情況下是可以不需要偏移量的,不僅實現上更加簡潔,適應性也更強,甚至還能實現加上偏移量反而實現不了的佈局,一起看看吧,相信會有不一樣的體會

一、絕對定位的特性

談到絕對定位佈局,大家可能會馬上就會想到這些特性:

  • 不佔用空間
  • 脫離文件流

第一條沒什麼問題,確實不會佔用空間。現在來看第二條,真的完全脫離文件流了嗎?假設有這樣一個佈局

<p>
  歡迎關注前端偵探
</p>

然後生成一個偽元素,設定成絕對定位

p::after{
  content: 'A';
  position: absolute;
  color: red;
}

在不設定任何偏移的情況下,可以看到,絕對定位元素始終跟隨在文字後面,也就是說,現在仍然處於文件流中,如下

image.png

如果僅設定一個方向,比如left

p{
  position: relative;
}
p::after{
  content: 'A';
  position: absolute;
  color: red;
  left: 0;
}

那麼,在水平方向上,絕對定位元素始終位於最左邊,而垂直方向上,仍然保持著跟隨文件的特性,只是單方向的

image.png

如果兩個方向上都設定了,這也是我們最常見的寫法

p::after{
  content: 'A';
  position: absolute;
  color: red;
  left: 0;
  top:0
}

那麼,這個元素位置就完全固定了,真正的脫離了文件流

image.png

綜上所述,絕對定位元素,只有在設定了偏移時才會脫離文件流,如果只設定了一個方向上的,那麼在另外一個方向上仍然保留著文件流特性,或者這麼說,絕對定位元素仍然保持在原來的位置,並且不佔空間,除非設定了偏移才會真正固定定位

瞭解了這些,下面來看幾個實際案例

二、左上角的標籤

大家可能經常會碰到這樣的“角標”效果

image.png

現在簡單實現一下,假設HTML是這樣的

<div class="item">
  <img class="cover" src="xxx">
</div>

角標可以透過偽元素生成

.item::before{
  content: '推薦';
  position: absolute;
  font-size: 12px;
  line-height: 16px;
  padding: 2px 4px;
  background: #FDB324;
  color: #fff;
}

注意,這裡用到的是::before,而不是::after,原因在於::before在元素內容之前,本身就位於左上角,如果是::after,預設位置就在img的下方,在設定position: absolute的情況下,由於不佔空間,所以也不影響其他元素,效果如下

image.png

因此,像這種場景下,設定偏移量和父級定位可以說都是多餘的

/*以下是多餘的*/
.item{
  position: relative;
}
.item::before{
  left: 0;
  top: 0;
}

如果你的專案中也有這樣的佈局,趕緊最佳化一下吧,當然僅限於“左上角”的標籤,如果是其他方位的,按傳統實現即可

完整 demo 可以訪問以下任意連結:

三、文字重疊

有時候在做文字特效時,不可避免需要重疊文字,比如文字外描邊效果

image.png

大家可能都知道,文字描邊其實是居中描邊

.text{
    -webkit-text-stroke: 6px rgb(51, 51, 51);
}

這樣會帶來一個問題,當描邊慢慢變大時,會覆蓋文字顏色

image.png

為了解決這個問題,我們需要用到兩層文字,在底下放描邊,上面放文字顏色,示意如下

而這裡兩層重疊的文字就需要用到絕對定位了,假設HTML是這樣的

<p class="text" data-title="前端偵探">前端偵探</p>

這裡加另一個data-title屬性,用來生成偽元素,關鍵實現如下

.text::before{
    content: attr(data-title);
    position: absolute;
}

只需要將::before設定絕對定位即可,注意是::before,無需任何其他偏移屬性,文字就預設重疊了,而且由於是絕對定位,層級也自動變高

從這裡也可以看出,在絕對定位中,::before要比::after要好用的多!

關於文字修飾效果可以參考以前這篇文章:CSS和SVG實現文字漸變、描邊、投影

完整 demo 可以訪問以下任意連結:

四、多個元素水平垂直堆疊居中

再來看一個這樣的例子,有多個尺寸不定的元素或者圖片,需要堆疊居中,示意如下

image.png

最簡單的方式就是,父容器設定flex居中特性,然後子元素直接設定絕對定位,關鍵實現如下

.wrap{
  display: flex;
  justify-content: center;
  align-items: center;
}
.item{
  position: absolute;
}

原因在於,本身元素是居中的,設定絕對定位後,僅僅不佔空間而已,所以後面的元素會堆疊上來而不擠壓,特別適合圖片堆疊展示的效果

完整 demo 可以訪問以下任意連結:

五、自定義水平方向點選範圍

還記得之前這篇文章嗎?CSS 實現樹狀結構目錄

裡面有個小細節也用到了絕對定位,非常巧妙,下面簡單回顧一下:

假設HTML是這樣的

<details>
  <details>
    <summary>
      <span class="tree-item">資料夾1-1</span>
    </summary>
    <details>
      <summary>
        <span class="tree-item">資料夾1-1-2</span>
      </summary>
    </details>
    <details>
      <summary>
        <span class="tree-item">資料夾1-1-3</span>
      </summary>
      <details>
        <summary>
          <span class="tree-item">資料夾1-1-3-1</span>
        </summary>
      </details>
      <details>
        <summary>
          <span class="tree-item">資料夾1-1-3-2</span>
        </summary>
      </details>
    </details>
  </details>
</details>

樹形結構有一個明顯的縮排層級關係,這裡是透過內邊距實現的

details{
  padding-left: 10px
}

image.png

有個問題是,由於是逐層巢狀結構,導致 層級越深,點選範圍越小,就像這樣

Kapture 2022-04-10 at 19.22.22.gif

那麼,如何做成通欄都可以點選呢?

這時,我們可以建立一個偽元素,並設定絕對定位,但是只需要設定水平方向上的偏移量,這樣在水平方向上位置就是固定的(相對於外層父級),而垂直方向上,仍然處於預設位置,也就是跟隨容器本身,關鍵實現如下

.tree{
  /*最外層父級需要設定相對定位*/
  position: relative;
}
.tree-item::before{
    content: '';
    position: absolute;
    left: 10px;
    right: 10px;/*水平方向的尺寸依賴於父級.tree*/
    height: 38px;
    background: #EEF2FF;
    border-radius: 8px;
    z-index: -1;
    opacity: 0;
    transition: .2s;
}
.tree-item:hover::before{
    opacity: 1;
}

效果是這樣的

Kapture 2022-04-10 at 20.02.48.gif

這樣就非常完美了,而且除了這種方式,好像找不到其他更好的解決方案了,有其他解決方案歡迎留言討論

完整 demo 可以訪問以下任意連結:

六、最後總結一下

舉了這麼多例子,其實無非就是想強調一下,在使用絕對定位時並不一定需要left或者top這樣的偏移量,不僅程式碼更加精簡,有時還能達到意想不到的效果,下面總結一下

  1. 絕對佈局的特性是不佔空間,但不一定完全脫離文件流,只有在設定了偏移時才會脫離文件流
  2. 如果只設定了一個方向上的偏移量,那麼在另外一個方向上仍然保留著文件流特性
  3. 在絕對定位中,::before要比::after要好用的多,因為::before預設就是初始位置,可以很輕易的實現重疊效果

然後就是實戰了,根據上面這些案例,相信大家對絕對定位一定有了新的認識,多多使用吧~最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤

歡迎關注我的公眾號:前端偵探

本文參與了SegmentFault 思否寫作挑戰賽,歡迎正在閱讀的你也加入。

相關文章