之前在寫《個人常用的水平居中方法》這篇文章的時候,百分比問題涉及到了包含塊(containing block)這個概念。 今天刷面試題的時候,又看到了containing block這個詞,之前計算百分比考慮了幾種情況(如那些屬性值根據哪個元素計算的),但不知道所謂的‘哪個元素’就是包含塊。系統的看 ...
之前在寫《個人常用的水平居中方法》這篇文章的時候,百分比問題涉及到了包含塊(containing block)這個概念。
今天刷面試題的時候,又看到了containing block這個詞,之前計算百分比考慮了幾種情況(如那些屬性值根據哪個元素計算的),但不知道所謂的‘哪個元素’就是包含塊。系統的看了看MDN中的內容,感覺受益匪淺。大家可以移步去MDN看,我這篇僅僅是在原文基礎上加了個小知識點——client相關值。
一個元素的尺寸和位置經常受其包含塊(containing block)的影響。大多數情況下,包含塊就是這個元素最近的祖先塊元素的內容區,但也不是總是這樣。在本文中,我們來過一遍確定包含塊的所有因素。
當一個客戶端代理(比如說瀏覽器)展示一個文檔的時候,對於每一個元素,它都產生了一個盒子。每一個盒子都被劃分為四個區域:
內容區、內邊距區、邊框區、外邊區
許多開發者認為一個元素的包含塊就是他的父元素的內容區。但事實並非如此。接下來讓我們來看看,確定元素包含塊的因素都有哪些。
包含塊的影響
元素的尺寸及位置,常常會受它的包含塊所影響。對於一些屬性,例如 width, height, padding, margin,絕對定位元素的偏移值 (比如 position 被設置為 absolute 或 fixed),當我們對其賦予百分比值時,這些值的計算值,就是通過元素的包含塊計算得來。
確定包含塊
確定一個元素的包含塊的過程完全依賴於這個元素的 position 屬性:
-
static、relative、sticky:包含塊可能由它的最近的祖先塊元素的內容區的邊緣組成。也可能會建立格式化上下文(比如說 table container, flex container, grid container, 或者是block container 自身)。
-
absolute: 包含塊就是由它的最近的 position 的值不是 static 的祖先元素的內邊距區的邊緣組成。
❗註意以上兩個,一個是內容區、一個是內容邊距區
- fixed:在連續媒體的情況下包含塊是視窗視圖(viewport),分頁媒體下的情況下包含塊是分頁區域(page area)。
如果position值是absolute或fixed,包含塊也可能是由滿足以下條件的最近父級元素的內邊距區的邊緣組成的:
註意:根元素()所在的包含塊是一個被稱為初始包含塊的矩形。
內邊距區相關補充
在原來整理的一篇所有視圖屬性和方法中,提到了clientWidth和clientHeight,這就是本文所指的內邊距區大小。
在chrome和firefox瀏覽器中f12,選取頁面中的元素時,顯示的數據就是內邊距區的寬高。註意不要和元素內容區的width、height混淆。
根據包含塊計算百分值
如果某些屬性被賦予一個百分值的話,它的計算值是由這個元素的包含塊計算而來的。這些屬性包括盒模型屬性和偏移屬性:
-
height、top、bottom:通過包含塊的 height 的值。如果包含塊的 height 值會根據它的內容變化,而且包含塊的 position 屬性的值被賦予 relative 或 static ,那麼,這些值的計算值為 auto。
-
width、left、right、padding、margin 這些屬性由包含塊的 width 屬性的值來計算它的百分值。
這裡特別強調padding和margin講的是上下左右四個都是根據包含塊的width
看到這,我發現之前很零散的知識突然就全部聯繫起來了。這感覺太棒了,一個包含塊,解決了我很多疑問,無論是百分比按照什麼計算,還是元素視圖的應用,都在這篇文章里清晰了起來。昨天還在敲定位元素的各個百分比屬性值是根據什麼計算的打算整理出來發文的,今天就看到這篇文章,太棒了!
示例
Example1
P
標簽設置為靜態定位,所以它的包含塊為
body {
background: beige;
}
section {
display: block;
width: 400px;
height: 160px;
background: lightgray;
}
p {
width: 50%; /* == 400px * .5 = 200px */
height: 25%; /* == 160px * .25 = 40px */
margin: 5%; /* == 400px * .05 = 20px */
padding: 5%; /* == 400px * .05 = 20px */
background: cyan;
}
Example2
在這個示例中,P 標簽的包含塊為
元素,因為body {
background: beige;
}
section {
display: inline;
background: lightgray;
}
p {
width: 50%; /* == half the body's width */
height: 200px; /* Note: a percentage would be 0 */
background: cyan;
}
⭐Example3
這個示例中,P 元素的包含塊是
body {
background: beige;
}
section {
position: absolute;
left: 30px;
top: 30px;
width: 400px;
height: 160px;
padding: 30px 20px;
background: lightgray;
}
/* 再次強調,是根據包含塊的內容區大小(包含padding)計算的。有疑問回上面看內容區表示什麼那塊 */
p {
position: absolute;
width: 50%; /* == (400px + 20px + 20px) * .5 = 220px */
height: 25%; /* == (160px + 30px + 30px) * .25 = 55px */
margin: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
padding: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
background: cyan;
}
⭐Example4
這個示例中,P 元素的 position 為 fixed,所以它的包含塊就是初始包含塊(在屏幕上,也就是 viewport)。這樣的話,P 元素的尺寸大小,將會隨著瀏覽器窗框大小的變化,而變化。
body {
background: beige;
}
section {
width: 400px;
height: 480px;
margin: 30px;
padding: 15px;
background: lightgray;
}
p {
position: fixed;
width: 50%; /* == (50vw - (width of vertical scrollbar)) */
height: 50%; /* == (50vh - (height of horizontal scrollbar)) */
margin: 5%; /* == (5vw - (width of vertical scrollbar)) */
padding: 5%; /* == (5vw - (width of vertical scrollbar)) */
background: cyan;
}
⭐Example5
這個示例中,P 元素的 position 為 absolute,所以它的包含塊是
body {
background: beige;
}
section {
transform: rotate(0deg);
width: 400px;
height: 160px;
background: lightgray;
}
p {
position: absolute;
left: 80px;
top: 30px;
width: 50%; /* == 200px */
height: 25%; /* == 40px */
margin: 5%; /* == 20px */
padding: 5%; /* == 20px */
background: cyan;
}