iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 12
4
自我挑戰組

前端新手進化史系列 第 12

Containing block

文章將陸續整理並更新至個人部落格


每個元素會生成零(display: none 時)至多個盒子(例如 display 為 list-item 時),盒子(box)可以裝盒子,不同的盒子會依據它所屬的格式化上下文(formatting context)類型來排列,不同的格式化上下文有不同的佈局規則。在正式介紹格式化上下文之前,需要先了解包含塊(Containing block)是什麼,它攸關元素的位置寬高內外距的計算。

包含塊 Containing block

每個元素會生成一個盒子,甚至多個盒子,而盒子的位置尺寸會以它的包含塊(containing block)為基準來計算。例如在元素設定寬度(width)、高度(height)、內距(padding)、外距(margin)這些屬性時,若屬性值給予百分比,將會以元素的包含塊為基準去做計算,再例如,使用 position 屬性時,也是以包含塊作為參考定位

[W3C]對於包含塊的定義為:

A rectangle that forms the basis of sizing and positioning for the boxes associated with it (usually the children of the box that generated it). Notably, a containing block is not a box (it is a rectangle), however it is often derived from the dimensions of a box. If properties of a containing block are referenced, they reference the values on the box that generated the containing block.

一個元素的尺寸和位置會受到其包含塊的影響,包含塊是一個矩形(rectangle),一個由內容區(content area)或內距邊緣(padding edge)所圍繞的範圍。


如何尋找包含塊:

  • 根元素 <html> 的包含塊稱為初始包含塊(initial containing block)。

  • 若元素 position 屬性值為 staticrelativesticky,包含塊為距離它最近祖先塊元素格式化上下文(formatting context)的內容區邊緣組成。

    • 若元素 position 屬性為 absolute,包含塊為距離它最近position 屬性值不是 static(即為fixed、absolute、relative 或 sticky)的祖先元素內距邊緣組成。
  • 若元素 position 屬性為 fixed,包含塊為 viewport

  • 如果 position 屬性是 absolutefixed,包含塊也可能是由滿足以下條件的最接近祖先元素的內容區邊緣組成:

    • transform 屬性值不為 none
    • contain 屬性值不為 none

註:若祖先塊元素皆無 position 屬性為非 static,則最後將以根元素 <html> 為參考定位。


來看幾個例子吧

例 1.

找出 <p> 的包含塊,並且計算出 <p> 最終的寬、高、內距與外距。

在此例子中,因為 <p> 的 position 值為預設的 static,故其包含塊為距離它最近的塊元素 <section> 的內距邊緣所圍範圍。<p> 的 width、 height、margin 與 padding 皆會以 <section> 為基準來計算。

需特別注意的是,marginpadding 是以包含塊寬度為基準

<body>
  <section>
    <p>This is a paragraph!</p>
  </section>
</body>
section {
  display: block;
  width: 400px;
  height: 160px;
}

p {
  width: 50%;   /* == 400px * .5 = 200px */
  height: 25%;  /* == 160px * .25 = 40px */
  margin: 5%;   /* == 400px * .05 = 20px */
  padding: 5%;  /* == 400px * .05 = 20px */
}


例 2.

現在將 <section> 改為 display: inline。
找出 <p> 的包含塊,並且計算出 <p> 最終的寬度。

在此例子中,<p> 的 position 依舊是預設的 static,但是 <section> 不再是塊容器,沒有形成一個格式化上下文,故 <p> 的包含塊為 <body> 內距邊緣所圍範圍。

<p> 的寬度將以 <body> 為基準計算。

<body>
  <section>
    <p>This is a paragraph!</p>
  </section>
</body>
section {
  display: inline;
}

p {
  width: 50%;     /* == half the <body>'s width */
  height: 200px;  /* Note: a percentage would be 0 */
}


例 3.

包含塊有內距(padding)。
找出 <p> 的包含塊,並且計算出 <p> 的最終寬度、高度、外距與內距。

在此例中,P元素的包含塊是 <section>,因為 <section> 的 position 值非 static。
<p> 百分值會受其包含塊 <section> 的 padding 所影響。若將包含塊的 box-sizing 值設置為 border-box,就可以避免這個問題。

<body>
  <section>
    <p>This is a paragraph!</p>
  </section>
</body>
section {
  position: absolute;
  left: 30px;
  top: 30px;
  width: 400px;
  height: 160px;
  padding: 30px 20px;
}

p {
  position: absolute;
  width: 50%;   /* == (400px + 20px + 20px) * 50% = 220px */
  height: 25%;  /* == (160px + 30px + 30px) * 25% = 55px */
  margin: 5%;   /* == (400px + 20px + 20px) * 5% = 22px */
  padding: 5%;  /* == (400px + 20px + 20px) * 5% = 22px */
}



包含塊的介紹就告一段落囉!
明天見~

/images/emoticon/emoticon25.gif


此文章為學習筆記,如有錯誤,麻煩告知,非常感謝!



參考資源

W3C-Containing blocks
MDN-Layout and the containing block
每天來點 CSS Specification-Visual Formatting Model - 定義、containing block


上一篇
番外篇 - 胡搞 box-shadow (下)
下一篇
視覺格式化模型-Box generation(上)
系列文
前端新手進化史30
0
Askie Lin
iT邦新手 5 級 ‧ 2019-09-27 20:59:36

讚啦包含塊,前端一定要知道的 containing block 被你解釋得好清楚 /images/emoticon/emoticon34.gif

yachen iT邦新手 5 級 ‧ 2019-09-28 01:31:06 檢舉

...Askie大神講話要憑良心啊/images/emoticon/emoticon16.gif

0
RURU Tseng
iT邦新手 4 級 ‧ 2019-09-27 22:06:02

/images/emoticon/emoticon42.gif

說得超精細的,推推~~

yachen iT邦新手 5 級 ‧ 2019-09-28 01:32:35 檢舉

看RU~大師的鐵人寫鐵人/images/emoticon/emoticon01.gif

Titangene iT邦新手 5 級 ‧ 2019-09-29 21:46:37 檢舉

竟然沒把 Ru 大師的經典放在參考資源

/images/emoticon/emoticon15.gif

yachen iT邦新手 5 級 ‧ 2019-09-29 23:47:46 檢舉

哈哈哈哈已補!!/images/emoticon/emoticon12.gif

0
Titangene
iT邦新手 5 級 ‧ 2019-09-27 23:03:15

長知識了

/images/emoticon/emoticon07.gif

看更多先前的回應...收起先前的回應...
yachen iT邦新手 5 級 ‧ 2019-09-28 01:34:20 檢舉

今天是什麼風把三位大神吹來了...
/images/emoticon/emoticon32.gif

我是隔壁村.平凡.不會打怪.樸實鄉民 跟著來看熱鬧! 推推

Titangene iT邦新手 5 級 ‧ 2019-09-29 00:34:51 檢舉

你是同村.不平凡.狂升等.GM 根本是來湊熱鬧 XD

yachen iT邦新手 5 級 ‧ 2019-09-29 11:01:35 檢舉

集滿四位大神~!/images/emoticon/emoticon64.gif

我要留言

立即登入留言