1. 程式人生 > >轉 -- 可替換元素、不可替換元素、包含塊、塊級格式化上下文、匿名盒

轉 -- 可替換元素、不可替換元素、包含塊、塊級格式化上下文、匿名盒

平時在工作中,總是有一些元素之間的邊距與設定的邊距好像不一致的情況,一直沒明白為什麼,最近仔細研究了一下,發現裡面有學問:垂直元素之間的margin有有互相重疊的情況;新建一個BFC後,會阻止元素與外界元素的重疊現象。

  先了解幾個概念:可替換元素、不可替換元素(non-replaced element)、包含塊(containing block)、塊級格式化上下文(BFC)。

      可參考css2.1 中文規範

 

1、可替換元素與不可替換元素

  根據css1 中所述:所謂可替換元素就是瀏覽器根據元素的標籤和屬性,來決定元素的具體顯示內容。例如瀏覽器會根據<img>標籤的src屬性的值來讀取圖片資訊並顯示出來,而如果檢視(x)html程式碼,則看不到圖片的實際內容;又例如根據<input>標籤的type屬性來決定是顯示輸入框,還是單選按鈕等。html中的<img>、<input>、<textarea>、<select>、<object>都是替換元素。而現在,這個概念已經發生了變化,在新的規範中,html5涉及到的<video>、<canvas>、<menu>元素也被認為是替換元素。因此可以把“替換”理解為“嵌入”

   替換元素就可以理解為需要一些外部內容來嵌入它的空間的元素。

  而不可替換元素(non-replaced element)就是不需要外部內容來填充它的空間的元素。

 

2、包含塊(containing block

  在 CSS2.1 中,很多框的定位和尺寸的計算,都取決於一個矩形的邊界,這個矩形,被稱作是包含塊( containing block )。 一般來說,(元素)生成的框會扮演它子孫元素包含塊的角色;我們稱之為:一個(元素的)框為它的子孫節點建造了包含塊。包含塊是一個相對的概念,每個框關於它的包含塊都有一個位置,但是它不會被包含塊限制;它可以溢位(包含塊)。包含塊上可以通過設定 ‘overflow’ 特性達到處理溢位的子孫元素的目的。

3、塊級元素和行內級元素

      塊級元素:當元素的CSS屬性displayblocklist-item或 table時,它是塊級元素 block-level。塊級元素會生成塊級盒,塊級盒參與塊格式化上下文

     行內級元素:當元素的 CSS 屬性 display 的計算值為 inlineinline-block 或 inline-table 時,稱它為行內級元素

 

4塊級格式化上下文(BFC)

  BFC,英文全稱叫做Block Formatting contexts,中文叫塊級格式化上下文。可以將它理解為一個箱子,這個箱子中的元素與外部元素隔離,箱子裡的元素不會影響外部的元素,也不受外部元素的影響(利用這個特性可以消除浮動元素對其非浮動的兄弟元素和其子元素帶來的影響)。BFC中只有塊級水平的盒子參與(block-level box:display 屬性為 block, list-item, table 的元素,會生成 block-level box)

BFC佈局規則

l   內部的Box會在垂直方向,一個接一個地放置。

l   Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊

l   每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如 此。

l   BFC的區域不會與float box重疊。

l   BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素。反之也如此。

l   計算BFC的高度時,浮動元素也參與計算。

 

  如何觸發或建立一個BFC?

  W3C中定義: 浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為“visiable”的塊級盒子,都會為他們的內容建立新的BFC(這時這個元素中的內容就同處在一個BFC中)。 

     當給某一元素新增以下樣式中的任意一個時,就觸發了BFC。

        l   float: left/right/inherit  也就是除none以外的浮動元素

        l   position: absolute/fixed 絕對定位元素,fixed是absolute的一個子類,也屬於絕對定位

        l   display: inline-block、table-cell、table-captions 需要注意的是display: table本身不可以觸發BFC,但是由於table會產生匿名盒,而匿名盒的display: table-cell特性會觸發BFC,產生新的格式化上下文。(匿名盒:CSS引擎自動生成的盒子,沒有名字,不能被 CSS 選擇符選中,不能被 CSS 選擇符選中意味著不能用樣式表新增樣式。這意味著所有繼承的 CSS 屬性值為 inherit ,所有非繼承的 CSS 屬性值為 initial

       l   overflow: hidden/auto/scroll/inherit

 

 

瞭解了以上概念後,我們再來看margin

margin的用途

margin的基本用途就是控制元素與周圍其他元素的間隔。

margin的用法

margin通過使用單獨的屬性,可以對上、右、下、左的外邊距進行設定。即:margin-top、margin-right、margin-bottom、margin-left;也可以使用簡寫的外邊距屬性同時改變所有的外邊距:margin: top right bottom left;

 

margin的取值

margin的值型別有:auto | length | percentage,

 1、如果設定為auto,取值如下

常規流中的塊級元素的margin設定為auto時,則margin-left、margin-right的值相等。這個可以用來居中一個塊級元素

浮動的元素的margin值為auto時,它的margin-left、margin-right的取值為0

絕對定位的元素的margin值設定為auto時:如果這個元素的left、right、width都是auto,那麼它的margin-left、margin-right的值為0;如果這個元素的left、right、width值不是auto,那麼margin-right、margin-left的值相等;如果只有一個'margin-left'或者'margin-right'有一個是'auto',則根據公式可計算出另外一個margin的值。;除以上這幾種情況外,margin-left和margin-right取值為0

 

W3C規範中提到的margin為auto時的取值規範

css2.1規範中提到的以下元素margin設定為auto'的水平方向的'margin-left'或者'margin-right'對應的值為'0'

l   內聯的不可替換元素(non-replaced inline element):既是內聯元素,又是不可替換元素,如 span, strong, i, b, em、cite

l   內聯的可替換元素:如:a  

l   浮動的不可替換元素(block元素和inline元素)

l   浮動的可替換元素(block元素和inline元素)

l   常規流中的不可替換的inline-block元素

l   常規流中可替換的inline-block元素

常規流中的塊級不可替換元素、常規流中的塊級可替換元素, 若 margin-left'和'margin-right'都是'auto',那麼它們的應用值相等,(這會讓該元素相對於其包含塊的邊水平居中)。

絕對定位的不可替換元素和絕對定位的可替換元素,取值根據一個公式得出

 'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含塊的寬度。

l   如果'left','width'和'right'全都是'auto':則'margin-left'和'margin-right'的值為0

l   如果'left','width'和'right'都不是'auto':如果'margin-left'和'margin-right'都是'auto,則他們的應用值相等(根據這個規則可以使絕對定位的元素水平居中)

l   如果'margin-left'或者'margin-right'有一個是'auto',則根據上述公式求出另外一個margin的值

l   除以上規則外,'margin-left'和'margin-right'值為0。

2、設定為length的話很好理解,就是實際設定的值,單位可以是px、em等長度值。另外margin值可以設定為負值。

3、percentage:百分比是由被應用 box 的包含塊containing block的大小所決定。對於 margin-top 和 margin-bottom 也同樣成立。

 

margin外邊距重疊

外邊距重疊指的是,當兩個垂直外邊距相遇時(有可能是同輩或者後輩),它們將形成一個外邊距。重疊後的外邊距的高度計算如下:

兩個相鄰的外邊距都是正數時,重疊結果是它們兩者之間較大的值

兩個相鄰的外邊距都是負數時,重疊結果是兩者絕對值的較大值

兩個外邊距一正一負時,重疊結果是兩者的相加的和。

 

 W3C中提到的邊距重疊必要條件: 

 1、必須是常規文件流(不是float和絕對定位,注意絕對定位包含absolute和fixed)中的塊級盒子,並且處於同一個BFC當中;

 2、沒有行盒-即linebox(行盒由一行中所有的內聯元素所組成), 沒有padding和border將他們隔開; 

 3、都屬於垂直方向上相鄰的外邊距 。      

 

W3C中提到的邊距重疊的幾種情況:

1)       常規文件流中,一個盒子如果沒有上補白(padding-top)和上邊框(border-top),那麼這個盒子的上邊距會和其內部文件流中的第一個子元素的上邊距合併,這個子元素不能包含間隙(clearance:樣式中有clear:right|left|both)。

2)       常規文件流中,一個盒子如果沒有下補白(padding-top)和下邊框(border-top),那麼這個盒子下邊距會跟他的下一個兄弟盒子的的上邊距合併,除非他們之間存在間隙(clearance)。

3)       常規文件流中,height為auto的盒子的下邊距會與它的最後一個子元素的下邊距合併;

4)      常規文件流中,一個盒子的高度為0並且最小高度也為0,且不包含常規文件流的子元素,並且自身沒有建立新的BFC的,那麼它自身的上邊距和下邊距會合並。

 

根據上面的條件,不發生外邊距重疊的情況有以下幾種:

1)       水平方向上永遠不會發生外邊距合併     

2)       垂直方向上,建立了新的BFC的元素與它的子元素的外邊距不會重疊(注意區別:BFC內部的子元素與子元素之間邊距是會發生摺疊)

3)       一個浮動的元素不與任何元素的外邊距產生重疊,包括其父元素及子元素及兄弟元素;(分析:浮動元素脫離了常規文件流,且建立了BFC,他不會影響周圍其他元素、也不會被其他元素影響)

4)        overflow設定為hidden|scroll|auto的元素不會與它的子元素的外邊距重疊;(分析:overflow不是visible的元素建立了BFC,他不會影響周圍其他元素、也不會被其他元素影響)

5)       絕對定位的元素不與任何元素的外邊距產生重疊(包括其父元素及子元素及兄弟元素)(分析,脫離了常規文件流,且建立了BFC,他不會影響周圍其他元素、也不會被其他元素影響)

6)       行內塊級(inline-block)元素不與任何元素的外邊距產生重疊(包括其父元素及子元素及兄弟元素)(分析:行內塊級元素不符合發生邊距重疊的第一個必要條件‘塊級盒子’,塊級盒子的display屬性必須是以下三種之一:'block', 'list-item', 和 'table')

     外邊距重疊產生的影響

   盒子的顯示大小= border +content+padding+正margin 值。負的 margin 值不會影響 box 的實際大小,但是負的 top 或 left 值會引起 box 的向上或向左位置移動,如果是 bottom 或 right 只會影響下面 box 的顯示的參考線。

     下面是給div元素設定margin:-10px 20px -30px 40px的例子;(借鑑別人的例子)

 

 如果還不清楚,可以參考網上幾篇有關margin的文章

1、 你是否徹底瞭解margin屬性

                                                                                       

2由淺入深漫談margin屬性  

                                                                                       

3關於margin的一些問題 

                                                                                       

4深入理解BFC和Margin Collapse

另外一篇文章介紹了負margin的幾個用途,我知道你不知道的負margin

什麼時候用margin,什麼時候用padding

  何時應當使用margin:需要在border外側新增空白時。空白處不需要背景(色)時。上下相連的兩個盒子之間的空白,需要相互抵消時。如15px + 20px的margin,將得到20px的空白。

  何時應當時用padding:需要在border內測新增空白時。空白處需要背景(色)時。上下相連的兩個盒子之間的空白,希望等於兩者之和時。如15px + 20px的padding,將得到35px的空白。