CSS進階(12)—— position:absolute如此高深,我當真不懂(上)

以前在探討float屬性的時候就已經提到了position:absolute的概念,絕對定位和浮動在不少方面都具備類似性,包括「塊狀化」,「包裹性」,「破壞性」等等,在理論層面上二者是一對兄弟關係。然而在實際場景中,因爲絕對定位的「破壞性」一般比float的要強,所以會有人以爲絕對定位的元素彷佛跟普通的流體元素徹底玩不到一塊去,事實上,除了衆所周知的須要依託最近的定位祖先節點進行定位,絕對定位元素還有不少「不脫離文檔流的特性」,這在本章的「非依賴性絕對定位」中會深刻探索。瞭解了絕對定位的一些基本信息後,下面就來深刻探索一下高深莫測的絕對定位吧!css

1.absolute的包含塊

在CSS世界裏,元素的大小和定位計算一直都要受包含塊的影響,若是沒有包含塊,那麼元素的信息就會像txt文本同樣,全都顯示在一行,這顯然是不符合咱們的閱讀標準的,一般狀況下咱們但願文本信息能在某些符合常理的狀況下自動換行,既然能換行,就必需要有包含塊的概念,有經驗的人通常都知道,普通元素的包含塊通常是他的父容器,也就是你設置某個元素的寬度爲100%,那麼指的是相對於父容器的寬度進行計算後獲得的寬度,而絕對定位元素的包含塊是相對於第一個position不爲static的祖先元素進行計算的,因爲包含塊在CSS世界的重要性,CSS規範中有明確的計算規則以下: html

(1)根元素(一般狀況下就是html)被稱爲初始包含塊,其尺寸等同於瀏覽器但是窗口的大小。 瀏覽器

(2)對於position:relative/static(默認)的元素,其包含塊由其最近的塊容器祖先盒的content-box邊界造成。 markdown

(3)對於position:fixed的元素,其包含塊指的是初始包含塊。 編輯器

(4)對於position:absolute的元素,其包含塊由最近的position不爲static的祖先元素的padding-box創建(若是祖先元素爲塊元素)。若是沒有符合條件的包含塊,則包含塊是初始包含塊。 佈局

上面四句話看着普通,實則暗藏玄機。對於純內聯元素,position:relative和static是直接無視的,所以position:relative和static的元素的包含塊不必定是其父容器,這句話有個前提條件是父容器必須爲塊元素,爲了證實這個觀點,咱們能夠來看一個例子加深一下印象。 測試

<!-- 普通元素包含塊 -->
<div>
    <span>你好呀</span>
    <span style="max-width: 200px;">我很好,我有一個子元素
        <div style="width: 50%">我是子元素,我想看看包含塊是誰</div>
    </span>
</div>
複製代碼

理論和實踐再一次統一了,上述例子中,子元素div是以最外層的div做爲本身包含塊,直接無視了本身的父級span內聯標籤。 flex

與常規元素比,absolute元素有兩個比較明顯的特徵: ui

(1)包含塊所在的元素不是父級塊元素,而是最近的position不爲static的祖先元素或根元素。 url

(2)邊界是padding-box而不是content-box。

事實上除了以上兩個明顯的特徵外,absolute元素和普通元素還有一個更大的差別,就是純內聯元素也能夠做爲absolute元素的包含塊,只是規則要相對複雜,且不一樣的瀏覽器有不一樣的規則,所以這兒就避開不談了。好在咱們在使用絕對定位的時候大部分是用塊來進行佈局,跟展現圖文爲主的內聯元素自己就玩不到一塊去,所以咱們就能夠義正詞嚴的不去探索這個特性了。

利用絕對定位元素計算的容器是第一個position不爲static的祖先元素,咱們能夠衍生出一個很是好用的小tips,就是對於絕對定位元素height:100%和height:inherit是有區別的,前者可能基於祖先元素定位,後者單純的繼承了父元素的高度,在某些場景下很是好用。

如今咱們已經「徹底」瞭解了絕對定位元素的「包含塊」是如何產生的了,所以咱們須要經過一個小測試來驗證其實用性。

<!-- 鼠標懸浮展現文字效果 -->
 <div class="icon"></div>
 <style> .icon{ position: relative; width: 16px; height: 16px; background: url('../pic_title_left.png') center; } /*爲了展現更清除不使用鼠標移入事件*/ .icon::after{ content: '圖標'; position: absolute; top: 100%; background: rgba(0,0,0,0.8); color: white; } </style>
複製代碼

此例中,咱們但願實現一個鼠標移入圖標,顯示提示信息的效果,能夠看到絕對定位元素的寬度被限制在父容器的16px,此時文字的主動換行變成了一種不怎麼好看的「一柱擎天」效果,這就是絕對定位的元素的「包裹性」,所以絕對定位元素的「包裹性」依賴於「包含塊」。要修復問題其實很簡單,只要改變默認的寬度類型就能夠了,添加white-space:nowrap,讓寬度表現從「包裹性」變成「最大可用寬度」,就能夠實現想要的效果了。

下面咱們再來看一下,position:absolute爲何要以padding-box做爲邊界,這其實和overflow隱藏也是padding-box做爲邊界相似,是由實際開發場景決定的。舉個例子,如咱們在開發某個文字欄目的時候,須要兩側有必定的留白,這個留白咱們一般會用padding撐開,而不是margin,由於margin是全透明的,在背景顏色設置上會遇到一些麻煩,固然咱們也不會考慮用border撐開,由於咱們打心底認爲border是用來作邊框的。這時候咱們須要在右上角固定一個圖標,如「博客專家」的圖標,你但願這個圖標放在什麼位置?或者說,右上角的概念是什麼?CSS幫咱們作了取捨,CSS認爲,應該放到padding-box的外邊緣,而不是content-box,事實上這樣看起來確實比較美觀,以下所示

<!-- 圖標固定在右上角的效果 -->
<div class="content">
    <span>假設我個是圖標</span>
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
     我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標
</div>
<style> .content{ position: relative; width: 400px; padding: 20px; border:2px solid #ccc; border-radius: 4px; } .content span{ position: absolute; right: 0; top: 0; line-height: 20px; width: 70px; height: 40px; background: yellow; } </style>
複製代碼

因爲markdown編輯器支持標籤語言,所以咱們能夠直接預覽最終效果以下(小提示:你能夠經過瀏覽器直接檢查下面的元素看到CSS樣式)

假設我個是圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標 我這裏有不少內容,但我須要有一個內邊距,我還要在右上角放個圖標

若是你須要右上角的定義是content,那麼CSS也給你留有一絲餘地,注意不要用right:padding-right,top:padding-top,那樣就太蠢了,並且增長了右上角和padding的耦合性,你徹底可使用border留白來實現這個效果,這個時候就不要請padding幫忙了。

2.具備相對特性的無依賴absolute定位

不少人對於absolute的印象是「徹底破壞文檔流」,這多是CSS歷史上最大的冤假錯案了,這甚至比clear清浮動還冤,畢竟clear清浮動好歹從表現上「清除了浮動」。而absolute則被認爲默認定位在包含塊的左上角。咱們能夠經過一個簡單的例子來驗證一下,一個絕對定位元素在沒有left/r/t/b的狀況下會在定位到哪裏?

<div style="position: relative;background:yellow">
     我是包含塊
     <div style="position: absolute;">我是絕對定位元素</div>
 </div>
複製代碼

不少人會以爲,絕對定位元素會和包含塊內的文字重合在一塊兒顯示,事實上測試結果以下圖所示,因爲markdown編輯器支持標籤語言,所以咱們能夠直接預覽最終效果以下(小提示:你能夠經過瀏覽器直接檢查下面的元素看到CSS樣式)

我是包含塊
我是絕對定位元素

絕對定位元素並無和包含塊的文字發生重合,而是中規中矩的呆在後面,固然絕對定位的「破壞性」依舊存在,能夠看到父容器div的高度不包含絕對定位元素的高度。做者把這種沒有設置left/right/top/bottom屬性值的絕對定位稱爲「無依賴絕對定位」,這種絕對定位屬性擁有兩個顯著特性:1.破壞性,2.相對性。無依賴絕對定位本質上能夠看做是relative相對定位,只是不佔據CSS的尺寸流而已,也就是他在保持破壞性的基礎上,保留了必定的「相對性」。聽起來有一種,先按照相對定位進行計算位置,而後把本身抽離文檔流的定位方式。這種不佔位置的相對定位特性在實際開發的時候實則很是有用,爲了加深你們對這個概念的印象,咱們來舉幾個例子說明。

1)咱們須要實現一張圖的左上角有一個小圖標。這時候咱們僅需用一個樣式就能搞定,而不須要多餘的left,top申明。

<!-- 圖片定位到左上角 -->
<img src="top1.png" style="position:absolute"><img src="1.jpg">
複製代碼

2)咱們須要實現一些帶上標的文字,vertical-align中也有上標下標屬性,但因爲內聯元素會佔據位置,會影響元素的居中顯示,一般狀況下咱們仍是會藉助到絕對定位不佔位置的特性去實現下圖的效果。

<!-- 文字定位到右上角 -->
<div class="container">
    <div class="li">
        <div class="word">普通導航</div>
    </div>
    <div class="li">
        <div class="word">熱門導航
         	<span class="icon">hot</span>
        </div>
    </div>
    <div class="li">
        <div class="word">新導航
         	<span class="icon">new</span>
        </div>
    </div>
</div>
<style> .container{ margin: auto; background: #ccc; } .li{ display: inline-block; width: 200px; text-align: center; } .word{ padding: 20px; } .icon{ position: absolute; color: red; margin: -6px 0 0 4px; font-size: 12px; } </style>
複製代碼
普通導航
熱門導航 hot
新導航 new

3)最後一個例子是一個比較經常使用的登錄註冊提示功能。

<!-- 登陸註冊提示 -->
<div class="container">
    <div class="line">
        <label>用戶名</label>
        <div>
            <input type="text" placeholder="請輸入用戶名">
            <i>*用戶名不正常</i>
        </div>
    </div>
    <div class="line">
        <label>密碼</label>
        <div>
            <input type="text" placeholder="請輸入密碼">
            <i>*密碼不支持</i>
        </div>
    </div>
    <div class="line">
        <label>手機號</label>
        <div>
            <input type="text" placeholder="請輸入手機號">
        </div>
    </div>
</div>
 <style type="text/css"> .container{ width: 400px; margin: auto; } .line{ margin:20px 0; } .line label{ font-size: 18px; line-height: 40px; float: left; } .line div{ margin-left: 4em; } .line input{ width: 320px; font-size: 18px; padding: 9px 5px; border: 1px solid #d0d6d9; vertical-align: top; } .line i{ position: absolute; line-height: 40px; margin-left: 20px; color:red; } </style>
複製代碼

除了上述幾種效果以外,無依賴絕對定位還能夠幫助咱們實現下拉框,模擬佔位符等,在這裏就不過多贅述了,舉了三個例子也是爲了幫助你們理解無依賴絕對定位的使用場景。

最後咱們來重點關注一下無依賴絕對定位的「塊狀化」,一般意義上,塊狀化指的是display的計算值是塊狀的,也就是說聲明瞭position:absolute,至關於同時申明瞭display:block,但該元素的位置卻和元素自己的屬性相關。聽起來有點繞,咱們來看一個例子對比一下就明白了。

<!-- 深刻理解無依賴定位 -->
<div style="position: relative;background: yellow">
     我是包含塊
     <span style="position: absolute;">我是絕對定位元素</span>
</div>

<div style="position: relative;background: yellow">
    我是包含塊
    <div style="position: absolute;">我是絕對定位元素</div>
</div>
複製代碼

因爲markdown編輯器支持標籤語言,所以咱們能夠直接預覽最終效果以下(小提示:你能夠經過瀏覽器直接檢查下面的元素看到CSS樣式)

我是包含塊 我是絕對定位元素
我是包含塊
我是絕對定位元素

上面這個例子中,絕對定位元素在未被聲明position:absolute以前,一個是塊級元素,一個是內聯元素,所以一個是換行顯示,另外一個是同行顯示,在聲明瞭absolute後,雖然計算值都變成了block,但其位置仍然跟以前定位的相同。

本章咱們已經深刻了解了絕對定位的包含塊以及「無依賴絕對定位」的特性,下一章咱們來聊聊absolute的流體特性以及absolute和其餘CSS相互之間的愛恨情仇。

不忘初心,方得始終

喜歡博主的童鞋能夠掃描二維碼加博主好友~ 也能夠掃中間二維碼入駐博主的粉絲羣(708637831)~固然你也能夠掃描二維碼打賞並直接包養帥氣的博主一枚。

相關文章
相關標籤/搜索