歡迎關注我的公眾號:前端偵探
分享一個關於絕對定位的實戰開發經驗。
在普遍的認知下,絕對定位好像都是伴隨著偏移屬性(left
/right
/top
/bottom
)一起出現的,相信大家都寫過這樣的CSS
,如下
el{
position: absolute;
left: 0;
top: 0;
}
其實,有些情況下是可以不需要偏移量的,不僅實現上更加簡潔,適應性也更強,甚至還能實現加上偏移量反而實現不了的佈局,一起看看吧,相信會有不一樣的體會
一、絕對定位的特性
談到絕對定位佈局,大家可能會馬上就會想到這些特性:
- 不佔用空間
- 脫離文件流
第一條沒什麼問題,確實不會佔用空間。現在來看第二條,真的完全脫離文件流了嗎?假設有這樣一個佈局
<p>
歡迎關注前端偵探
</p>
然後生成一個偽元素,設定成絕對定位
p::after{
content: 'A';
position: absolute;
color: red;
}
在不設定任何偏移的情況下,可以看到,絕對定位元素始終跟隨在文字後面,也就是說,現在仍然處於文件流中,如下
如果僅設定一個方向,比如left
p{
position: relative;
}
p::after{
content: 'A';
position: absolute;
color: red;
left: 0;
}
那麼,在水平方向上,絕對定位元素始終位於最左邊,而垂直方向上,仍然保持著跟隨文件的特性,只是單方向的
如果兩個方向上都設定了,這也是我們最常見的寫法
p::after{
content: 'A';
position: absolute;
color: red;
left: 0;
top:0
}
那麼,這個元素位置就完全固定了,真正的脫離了文件流
綜上所述,絕對定位元素,只有在設定了偏移時才會脫離文件流,如果只設定了一個方向上的,那麼在另外一個方向上仍然保留著文件流特性,或者這麼說,絕對定位元素仍然保持在原來的位置,並且不佔空間,除非設定了偏移才會真正固定定位
瞭解了這些,下面來看幾個實際案例
二、左上角的標籤
大家可能經常會碰到這樣的“角標”效果
現在簡單實現一下,假設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
的情況下,由於不佔空間,所以也不影響其他元素,效果如下
因此,像這種場景下,設定偏移量和父級定位可以說都是多餘的
/*以下是多餘的*/
.item{
position: relative;
}
.item::before{
left: 0;
top: 0;
}
如果你的專案中也有這樣的佈局,趕緊最佳化一下吧,當然僅限於“左上角”的標籤,如果是其他方位的,按傳統實現即可
完整 demo 可以訪問以下任意連結:
三、文字重疊
有時候在做文字特效時,不可避免需要重疊文字,比如文字外描邊效果
大家可能都知道,文字描邊其實是居中描邊的
.text{
-webkit-text-stroke: 6px rgb(51, 51, 51);
}
這樣會帶來一個問題,當描邊慢慢變大時,會覆蓋文字顏色
為了解決這個問題,我們需要用到兩層文字,在底下放描邊,上面放文字顏色,示意如下
而這裡兩層重疊的文字就需要用到絕對定位了,假設HTML
是這樣的
<p class="text" data-title="前端偵探">前端偵探</p>
這裡加另一個data-title
屬性,用來生成偽元素,關鍵實現如下
.text::before{
content: attr(data-title);
position: absolute;
}
只需要將::before
設定絕對定位即可,注意是::before
,無需任何其他偏移屬性,文字就預設重疊了,而且由於是絕對定位,層級也自動變高
從這裡也可以看出,在絕對定位中,::before
要比::after
要好用的多!
關於文字修飾效果可以參考以前這篇文章:CSS和SVG實現文字漸變、描邊、投影
完整 demo 可以訪問以下任意連結:
四、多個元素水平垂直堆疊居中
再來看一個這樣的例子,有多個尺寸不定的元素或者圖片,需要堆疊居中,示意如下
最簡單的方式就是,父容器設定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
}
有個問題是,由於是逐層巢狀結構,導致 層級越深,點選範圍越小,就像這樣
那麼,如何做成通欄都可以點選呢?
這時,我們可以建立一個偽元素,並設定絕對定位,但是只需要設定水平方向上的偏移量,這樣在水平方向上位置就是固定的(相對於外層父級),而垂直方向上,仍然處於預設位置,也就是跟隨容器本身,關鍵實現如下
.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;
}
效果是這樣的
這樣就非常完美了,而且除了這種方式,好像找不到其他更好的解決方案了,有其他解決方案歡迎留言討論
完整 demo 可以訪問以下任意連結:
六、最後總結一下
舉了這麼多例子,其實無非就是想強調一下,在使用絕對定位時並不一定需要left
或者top
這樣的偏移量,不僅程式碼更加精簡,有時還能達到意想不到的效果,下面總結一下
- 絕對佈局的特性是不佔空間,但不一定完全脫離文件流,只有在設定了偏移時才會脫離文件流
- 如果只設定了一個方向上的偏移量,那麼在另外一個方向上仍然保留著文件流特性
- 在絕對定位中,
::before
要比::after
要好用的多,因為::before
預設就是初始位置,可以很輕易的實現重疊效果
然後就是實戰了,根據上面這些案例,相信大家對絕對定位一定有了新的認識,多多使用吧~最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤
歡迎關注我的公眾號:前端偵探
本文參與了SegmentFault 思否寫作挑戰賽,歡迎正在閱讀的你也加入。