position屬性終極解析

position屬性比起其他的基礎屬性來講要復雜一些,我在這試著把里面的門道全部總結出來。

目前position有以下這些值,請把注釋讀三遍:

static:
對象遵循常規流。此時4個定位偏移屬性不會被應用。
relative:
對象遵循常規流,并且參照自身在常規流中的位置通過[top],[right],[bottom],[left]這4個定位偏移屬性進行偏移時不會影響常規流中的任何元素。
absolute:
對象脫離常規流,此時偏移屬性參照的是離自身最近的定位祖先元素,如果沒有定位的祖先元素,則一直回溯到body元素。盒子的偏移位置不影響常規流中的任何元素,其margin不與其他任何margin折疊,而且,絕對定位層的margin:auto``會失效。
fixed:
表現與absolute一致。但偏移定位是以窗口為參考,沒有定位祖先元素的概念。當出現滾動條時,對象不會隨著滾動。
center:
與absolute一致,但偏移定位是以定位祖先元素的中心點為參考。盒子在其包含容器垂直水平居中。(CSS3)
page:
與absolute一致。元素在分頁媒體或者區域塊內,元素的包含塊始終是初始包含塊,否則取決于每個absolute模式。(CSS3)
sticky:
對象在常態時遵循常規流。它就像是relative和fixed的合體,當在屏幕中時按常規流排版,當卷動到屏幕外時則表現如fixed。該屬性的表現是現實中你見到的吸附效果。(CSS3)

上面雖然列了很多值,但是最后的三個值,雖然理想很美好,目前包括Chrome最新版本,和IE11都不支持,所以我干脆劃掉。

現在需要研究的依然是static、relative、absolute、fixed。

研究的過程各種的測試,不多說了,花了我兩個小時測試加寫本文,所以我直接上結論:

名詞解釋:盒子模型

在CSS中,每一個元素都由一個矩形盒子所包含。每一個盒子都會具有一個內容區,內容區被一個內邊距所包裹,內邊距外是盒子的邊框,并且在邊框之外會有一個外邊距用于與其他盒子分隔開來。下圖是我在網上找的。

注意兩個名詞解釋:

容器:最外的寬高范圍,也就是下圖算上top之類的寬高范圍

內容:最內部的寬高范圍

名詞解釋:定位祖先

定位祖先這個詞是跟absolute綁定的,跟relative、fixed、static無關。定位祖先從字面上理解,就是負責定位的祖先。也就是說,祖先的位置決定了absolute的位置。祖先的寬和高等屬性可以被繼承,但是absolute的margin:auto會失效,margin: xxpx是有效的。

定位祖先可以是父元素,也可以不是。

關于定位祖先的更多介紹,看下文。

在沒有設置偏移的前提下,relative、absolute、fixed三者的區別:

先說一句:不設偏移跟偏移設成0是兩碼事。

為什么先討論沒有偏移的前提,因為沒有偏移的前提下,relative、absolute、fixed還是很乖的,行為比較容易理解,跟有偏移的情況有所不同。下面看:

  • relative沒有偏移的前提下表現可以視為static,至少可以先這么簡單的理解,所以,我們經常為了給absolute找一個定位祖先,會給某個祖先元素設個relative。只要別給這祖先設偏移,那么這個祖先該吃吃該喝喝,就當static,所以你找個祖先元素當定位祖先,給它設個relative,通常沒風險,就算給body設個relative,也沒事。
  • absolute和fixed沒有偏移的前提下,它們所在的空間會被下面的元素占據,它們自身的位置由父元素的容器決定。若absolute沒設偏移,則聽爸爸的,有定位祖先也不好使。若設置了偏移之后,absolute眼里就只有定位祖先,爸爸也不一定好使,除非爸爸就是定位祖先。fixed沒設偏移,也聽爸爸的,設了偏移就聽瀏覽器窗口和爸爸的。下面都有介紹。
  • absolute和fixed在表現上的區別:fixed會保持在瀏覽器窗口的固定位置,absolute不是。

在設置偏移的前提下,relative、absolute、fixed三者的區別:

  • 先說relative,比如給relative設個right: 10px;,那么它和它的孩子們會往左挪10px,然而它的兄弟們會紋絲不動,它的祖先也紋絲不動。
  • 然后說absolute,比如給absolute設個right: 10px;,這時候分為有定位祖先和沒定位祖先兩種情況。
  • 一直說的所謂定位祖先,可以是relative、absolute、fixed其中任意一個。注意,只有后代元素設了偏移,你這個定位祖先才有意義,否則后代元素都聽爸爸的,沒定位祖先什么事。定位祖先通常來講是relative,因為relative不設偏移就跟static似的,思考問題比較簡單。如果自己和祖先都是absolute,也允許。如果定位祖先是fixed,同樣也允許。所以千萬不要以為只有relative可以當定位祖先!先追溯到誰,誰就當定位祖先,不管定位祖先是relative還是absolute還是fixed。定位祖先生效的時候,按定位祖先的容器所在位置當做后代元素偏移的參考。
  • 沒有定位祖先,也就是祖先一直追溯到body標簽也沒找到,這時候就一種情況,就是拿body當定位祖先,偏移以body容器為參考。
  • 最后說fixed,這回情況又不一樣了。具體說,fixed的位置由toprightbottomleft這四個屬性各自有沒有設置、設置了多少,再考慮上父元素的容器位置,總共五大方面來決定,其實也不復雜:
  • 假設只設置top: 10px,那么fixed相對于瀏覽器窗口的上偏移就是10px,左偏移沒有設,就依據父元素的容器位置。這個特性,通常被用于網頁的sidebar區域的內容導航。
  • 假設只設置right: 10px;,那么fixed相對于瀏覽器窗口的右側偏移就是10px,上偏移沒有設,就依據父元素的容器位置。
  • 假設top: 10px;right: 10px;,那么所有祖先元素都跟我不再有關系,我就只跟著瀏覽器窗口。這個特點,通常被用于網頁左右角落的漂浮廣告,另外還有屏幕居中的彈出層等等。
  • 同理,假設只設bottom: 10px,跟top: 10px類似,假設只設left: 10px,跟right: 10px類似,不多說。如果topbottom全有呢?我先說句你神經病,然后告訴你,只有top起效。

relative、absolute、fixed互相嵌套、互為兄弟,會發生什么?

  • 下級元素通常不會影響上級元素。為什么強調“通常”?因為當上級元素不設width/height的時候,下級元素如果是static或者relative,就有可能撐開上級元素,也就“影響了上級元素”。但是,這種撐開其實并不影響下級元素的定位,因為撐開是往右側和下側撐大,定位是基于左上角。
  • 上級元素對下級元素要么沒影響,要么就影響x或y軸,要么就全影響。影響的時候,下級元素的基準坐標就是上級容器的位置,從上級容器的padding內開始計算。當上級元素沒有border和padding,這時也要注意margin疊加現象。
  • 兄弟元素的影響就是占位or不占位,上面有提到。
  • 占位當然好說了,就是我當你不存在,然后占了你的位置,我的位置跟你無關。所以記住,absolute、fixed是“沒有兄弟”的,它們永遠認為自己是獨生子,而且隨時準備當不孝子(一旦設偏移就可能跑出父親的懷抱),所以它們的兄弟也不客氣,也當它們是空氣。兩個兄弟absolute的話就是兩個自以為是的獨生子,也是互相當空氣。兩個兄弟fixed也是如此。
  • 不占位就是relative,那么考慮個復雜情況:兩個兄弟relative之間會發生什么?答案是第二個relative會假設第一個relative沒有偏移,只考慮第一個元素的最外范圍。如果第一個元素有margin范圍,提起margin,我們都知道“margin疊加”現象,這是另外的知識,這里不說,只需知道兩個兄弟relative也會margin疊加。
  • 最后記住兩點特別的用法:第一是absolute的定位祖先,第二是fixed只考慮父元素,就行了。下面專門說說這兩點。

當relative、absolute、fixed為定位祖先元素,absolute為后代元素時,absolute的偏移是怎么計算的?

答:absolute的偏移計算,完全考慮定位祖先的偏移、margin、border、padding,從祖先的內容區開始計算偏移。因為absolute只服定位祖先,親爸爸也沒用,所以祖先內的其他任何文本和元素都會被忽略。

當relative、absolute、fixed為父元素,fixed為子元素,fixed的實際偏移是怎么計算的?

假設fixed有top,那么縱軸就跟父元素無關了,橫軸呢?會計算父元素的left、margin、bottom、padding,也就是說fixed的偏移,是從padding里面的內容區開始計算的。因為fixed以為自己是獨生子,所以父元素內的其他任何文本和元素都會被忽略。

同理,假設fixed有left,那么橫軸就跟relative無關了,縱軸會計算父元素的top、margin、bottom、padding,是從padding里面的內容區開始計算的。因為fixed以為自己是獨生子,所以父元素內的其他任何文本和元素都會被忽略。

relative、absolute、fixed碰巧視覺疊加在一起了,誰在前誰在后?

不復雜不多說,你以為的就是對的。后代元素在前,后寫的在前。由z-index來改變順序。但是,它們三個跟static的區別在于,static的子元素如果溢出父元素,是被隱藏的,而它們三個沒這種說法。

設置了relative、absolute、fixed之后,還設置了float:left;,會怎樣?

float:left;不起作用。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容