什麼是containing block?
如果幹巴巴的問一個前端什麼是containing block。大部分都不知所云。官方示意如下:
The size and position of an element are often impacted by its containing block. Most often, the containing block is the content area of an element's nearest block-level ancestor, but this is not always the case. In this article, we examine the factors that deterime an element's containing block.
簡單來說就是——無特殊情況下,containing block(包含塊)就是最近的塊元素的content area(內容區)。
什麼是內容區?
以這個經典的盒模型圖:
最內部的即為內容區。
我們平時用到過嗎?
這個概念雖然可能不熟悉,但是實際上我們經常用到:
/*
<div class="outer">
<div class="inner"></div>
</div>
*/
.outer {
width: 200px;
box-sizing: border-box;
}
.inner {
width: 80%;
}
複製程式碼
inner的寬度是多少呢?毫無疑問,是160px。那稍微加一點戲,如果outer增加一條屬性padding: 50px
,這時候inner的寬度是多少?
很多人會遲疑一下,因為不知道背後的原理,只能根據經驗推斷,如果經驗老道,會給出正確答案:80px。
實際上,這些百分比值的運作原理都是通過包含塊來計算出最後結果。再回想一下之前的規範,包含塊是最近的塊元素的內容區,就可以很清晰的理解padding值在這個例子中起的作用了。
元素的尺寸和位置經常受其包含塊的影響。
特殊情況
如果敏感的人看到這可能會產生一個疑惑,如果把例子改成這樣?
.outer {
position: relative;
width: 200px;
padding: 50px;
box-sizing: border-box;
}
.inner {
position: absolute;
width: 80%;
}
複製程式碼
這時候inner width又是多少呢?是160px。
好不容易剛消化的知識就給了當頭一棍。。。然後回想一下平時用的時候好像確實是這樣!
所以規範提到了無特殊情況下,而特殊情況是:
- 如果position是absolute,包含塊就是它最近的position值不是static的元素的padding area。
- 如果position是fixed,包含塊就是檢視。
- 如果position是absolute或fixed,包含塊是最近的滿足下列條件的元素的padding area:
- transform或perspective值不是none
- filter值不是none
- will change值包含transform、perspective、或filter(只有Firefox有效)
position: fixed
瞭解了包含塊的規範,可以更好的理解平時常用的一些特性的執行原理。而特殊情況的最後一點,其實還有一些場景可以利用。
比如如下場景:
引入了一個三方ui庫,內部有一個彈窗元件,很正常的使用了fixed定位,那它的包含塊就是檢視了。如果這時,需要將它的位置進行調整,那怎麼辦?
可以利用transform/perspective/filter
來改變這個彈窗所在的內容塊,從而起到定位的作用。
contain
理解了包含塊,能夠將特性運用到一些特定場景中,已經說明知識點消化的足夠好了。但是下面的彩蛋知識點,還需要一點運氣才能獲得~因為它並沒有在包含塊的MDN文件中被提及。
chrome率先實現了一個實驗特性contain
。它允許開發者宣告當前元素和它的內容儘可能的獨立於 DOM 樹的其他部分。從而使得瀏覽器在重新計算佈局、樣式、繪圖或它們的組合的時候,只會影響到有限的 DOM 區域,而不是整個頁面。
在它的可選值中,paint的作用是使得該元素的子孫節點不會超出它的邊緣。
那父元素contain: paint
和子元素position: fixed
結合會如何呢?
實驗結果是,fixed的元素表現得像是父元素設定了transform/perspective/filter
一樣,說明它的包含塊被contain: paint
屬性所影響。
MDN文件中沒提到,那是Chrome意外實現了一個彩蛋嗎?
確認了規範以後證實,Chrome並不是xjb實現的~
The element acts as a containing block for absolutely positioned and fixed positioned descendants.