透徹理解塊級元素的寬度
作者按:又翻出來一篇5年前(2006年12月28日)寫的關於盒模型的文章,都不知道參考了哪本書了。只能憑印象感謝 Eric Meyer 的《CSS權威指南(第2版)》(The Definitive Guide, 2nd Edition)——因為當時作為練習剛翻譯完這本書。
內容提要 透徹掌握CSS視覺化模型的原理,可以讓我們準確判斷某個意外行為到底是因為CSS樣式問題,還是CSS解析引擎問題。本文要討論的要點是,當
margin-left
、width
和margin-right
這三個屬性分別取auto值或大於0的值,進而形成不同組合的情況下,如何確定塊級元素中各個組成部分的寬度。
塊級元素和行內元素
CSS把處在正常文件流中的不同html元素區分為塊級元素(block element)和行內元素(inline element)。一般來說,所謂塊級元素就是指當它們顯示在瀏覽器中時,會在自身前後各插入一個空行,而使自身在頁面中佔據一個相對獨立的塊狀區域的元素。因此,HTML文件中連續的塊級元素的典型顯示方式就是“堆疊”。塊級元素的例子有h1
到h6
、div
、p
等。而行內元素則是指以自身所包含的內容決定在頁面中佔據空間的大小,並且可以與其他行內元素共處一行的元素。行內元素的典型顯示方式就是“連線”。行內元素的例子有a
、img
、span
、input
等。對於行內元素,又可以進一步分為可替換行內元素和不可替換行內元素,兩者的區別在於元素中所包含的內容是否直接顯示在頁面中。不可替換的行內元素,如a
元素中的連結文字會直接顯示在網頁中;而可替換的行內元素,如img
,當它在網頁中顯示時會被其src
屬性指向的影像替代。本文討論的是塊級元素,有關行內元素的更多內容請參考其他資料。
正常文件流 指的是HTML文件元素在進行內容佈局時所遵循的從左到右、從上到下的表現方式。這種文件流佈局的方式對於某些語言可能會有所不同(比如從右往左閱讀的語言)。HTML中的大多數元素都處在正常的文件流中,而一個元素要脫離正常流的唯一途徑就是浮動或定位。
塊級元素的寬度
塊級元素的寬度是指塊級元素內容區、左右內邊距、左右邊框和左右外邊距的寬度之和。而塊級元素內容區的寬度由該元素的width
屬性來表示(或設定)。
圖1簡單的盒模型示意圖
有一個簡單的規則,就是塊級元素的寬度總是等於其父元素內容區的寬度。如果一個div
元素的父元素是body
,那麼這個div
元素的寬度就等於body的寬度,也就是瀏覽器中視窗的寬度。一個處在正常文件流中的塊級元素,其寬度是由七個部分共同決定的。可以稱為塊級元素的水平“七屬性”,它們分別是:
margin-left
border-left
padding-left
width
padding-right
border-right
margin-right
圖2 塊級元素的水平“七屬性”
如圖2所示,塊級元素在水平方向上的寬度是由七個CSS屬性共同決定的。例如,一個div元素中包含一個p元素。而div
元素的寬度是500px,那麼這個p
元素內容區的寬度(width
)加上其左右內邊距、左右邊框和左右外邊距之和就等於500px。這個計算過程用公式表示,就是:
margin-left +
border-left +
padding-left +
width +
padding-right +
border-right +
margin-right
= 500px
自動水平屬性如何決定塊級元素的寬度
在塊級元素的水平七屬性中,只有三個屬性可以使用auto
(自動)值,如圖3所示。
圖3 可以取auto
值的水平屬性
也就是說,只有margin-left
、width
和margin-right
這三個屬性可以使用auto值。這正是本文要討論的核心問題,即在上述三個屬性分別取不同的auto值和長度值,形成不同組合的情況下,相應塊級元素盒子中各部分的寬度是如何確定的?
在掌握了各種組合的可能性和相應結果的基礎上,我們就可以在遇到意外的情況時,對到底是CSS樣式的問題,還是CSS解析引擎的問題作出正確的判斷。並根據判斷來決定是修改CSS樣式、向瀏覽器提供商報告bug,還是採取過濾或hack手段來解決問題。
現在舉例子說明,假設有如下簡單的html程式碼:
<div>
<p> </p>
</div>
而相應有8種可能的CSS規則:
1. p { margin-left:auto;width:auto;margin-right:auto; }
2. p { margin-left:50px;width:auto;margin-right:auto; }
3. p { margin-left:auto;width:auto;margin-right:50px; }
4. p { margin-left:50px;width:auto;margin-right:50px; }
5. p { margin-left:auto;width:200px;margin-right:auto; }
6. p { margin-left:50px;width:200px;margin-right:auto; }
7. p { margin-left:auto;width:200px;margin-right:50px; }
8. p { margin-left:50px;width:200px;margin-right:50px; }
將這8種可能的CSS規則應用到上面的標記以後,會得到如圖3所示的結果(圖中為父元素div
新增了邊框,而為了表示內容區的寬度,也為p
元素新增了背景)。
圖4 自動寬度的8種可能性
下面,我們就來逐一分析這8種情況:
第一種情況:
規則是 p { margin-left:auto;width:auto;margin-right:auto; }
即,三個屬性全都取auto
值。如圖3所示,結果是p
元素的內容區的寬度和父元素div
的寬度相等。根據前面的公式(此例未考慮左右邊框和內邊距,假設它們全取預設值0)我們知道,此時的margin-left:auto
和margin-right:auto
等同於margin-left:0
和margin-right:0
。或者說此時的左右外邊距都等於0。
第二種情況:
規則是 p { margin-left:50px;width:auto;margin-right:auto; }
即,把左外邊距明確設定為50畫素,width
和margin-right
的值仍然是auto
。如圖3所示,結果是p
元素的內容區寬度等於div
元素的寬度減去50畫素。也就是說,此時左外邊距是50畫素,而margin-right:auto
相當於margin-right:0
,即右外邊距為0。
第三種情況:
規則是 p { margin-left:auto;width:auto;margin-right:50px; }
與第二種情況類似,只不過是把右外邊距而不是左外邊距明確設定為50畫素。圖3所示的結果告訴我們,此時右外邊距是50畫素,而左外邊距為0。 (以上三種情況,值為auto的外邊距都被重置為預設值0)
第四種情況:
規則是 p { margin-left:50px;width:auto;margin-right:50px; }
這次是把左、右外邊距都明確地設定為50畫素,而只有width
屬性是auto
。如圖3所示,結果是p
元素內容區的寬度等於div
的寬度減去(50+50=)100畫素。也就是說,50畫素的左、右外邊距是有效的。p
元素內容區在左右外邊距之間以自動適應的寬度值補足了div
元素的寬度。
第五種情況:
規則是 p { margin-left:auto;width:200px;margin-right:auto; }
這次把左、右外邊距都設定為auto
,而把width
明確地設定為200畫素。如圖3所示,結果是p
元素的內容區寬度就是設定的200畫素,而且,由於左右外邊距同為auto
,使得p
元素在div
元素中水平居中。這種情況也是網頁佈局中最常用的居中塊級元素居的主要手段。
第六種情況:
規則是 p { margin-left:50px;width:200px;margin-right:auto; }
這次margin-left
和width
分別明確設定成了50px和200px,只有右外邊距的值是auto
。從圖3中可以看到,結果是p
元素的內容區就是設定的200畫素,而左外邊距也是設定的50畫素。但右外邊距此時在前兩個部分之後以自動適應的寬度值補足了div
元素的寬度。
第七種情況:
規則是 p { margin-left:auto;width:200px;margin-right:50px; }
與第六種情況相似,但這次是左外邊距在後兩個部分之前以自動適應的寬度值補足了div
元素的寬度。
第八種情況:
規則是 p { margin-left:50px;width:200px;margin-right:50px; }
這是一種典型的情況,即三個屬性都明確地設定相應的值。從圖3的結果中我們看到,只有左外邊距和p
元素內容區的寬度是設定的值。右外邊距雖然也明確設定了50畫素的值,但實際情況就像是使用了auto
的第六種情況一樣。實際上,在三個屬性都明確設定了值,但其中一個值在沒有解的情況下--即在不能滿足三者之和等於div
元素寬度的情況下--在從左往右閱讀的語言中,會把右外邊距重置為自動適應的寬度值,也就是auto
。
小結
通過對以上8種可能情況的逐一分析,我們可以得出如下結論:
- 在
width
屬性的值設定成auto
的情況下,塊級元素內容區的寬度取決於左右外邊距是否明確設定了值。如果左右外邊距值都是auto
,則左右外邊距的值都會被重置為預設的值0;如果左右外邊距中只有一個值是auto
,則該值被重置為0,另一個值有效;如果左右外邊距都設定了明確的值,兩個值都將有效,此時元素內容區的寬度就是父元素的寬度減去左右外邊距後的值。需要說明的是,左右外邊距的預設值是0,這意味著如果沒有在CSS規則中宣告margin-left
或者margin-right
,它們就會使用預設值0。 - 在
width
屬性的值設定為大於0的值的情況下,塊級元素內容區的寬度就是由width
屬性設定的值。此時,左右外邊距的值如果都是auto
,則會使塊級元素在其父元素中居中;如果左右外邊距中只有一個值是auto
,則明確設定的值有效,auto
值會自動適應剩餘的寬度;如果左右外邊距都設定了明確的值,那麼在從左往右閱讀的語言中,會把右外邊距的值重置為auto
。
(注:本文所說“設定明確的值”,是指設定了大於0的值)
以下是今天(2012年1月17日)在Chrome中做的一個測試的截圖。
相關文章
- 子元素固定寬度 父元素寬度被撐開
- 採用絕對定位之後能夠讓塊級元素寬度自適應
- 在pos:a元素不設定寬度的情況下,他的最大寬度是受父元素的寬度所限制的。
- 如何獲取寬度自適應的元素的width寬度值
- (高階)居中沒有寬度的元素
- 透徹理解輾轉相除法
- html塊級元素HTML
- CSS的塊級元素和行內元素CSS
- js拖動調整元素寬度JS
- 不定寬度下,元素的垂直居中,水平居中
- js如何獲取元素的高度和寬度JS
- 如何設定span元素的寬度和高度
- 如何用css設定span元素的寬度CSS
- jQuery如何獲取元素的寬度和高度jQuery
- 塊級元素和行內元素
- 行內元素和塊級元素
- 根據id獲取元素的寬度的方法
- 回撥函式透徹理解Java函式Java
- 塊級元素和行內元素的區別
- CSS 設定 span 元素 寬度與高度CSS
- HTML 塊級元素和內聯元素HTML
- HTML_行內元素、塊級元素、空元素HTML
- CSS基礎——塊級元素、塊級盒子以及BFCCSS
- HTML的行內元素與塊級元素的區別?HTML
- flutter 父級寬度不固定,子集多個元素自動填充的佈局方案方法Flutter
- jQuery動態設定div元素的高度和寬度jQuery
- CSS塊級/內聯元素CSS
- 02 CSS塊級元素和行內元素CSS
- JavaScript動畫方式改變元素寬度和高度JavaScript動畫
- 透徹理解Java併發的等待佇列——ConditionJava佇列
- 高併發,你真的理解透徹了嗎?
- 偽元素需要將其設定為塊級元素或者塊級內聯元素才能設定尺寸
- 行級元素左右邊距及塊級元素上下邊距
- 塊級元素與內聯元素相互轉換
- 內聯元素和塊級元素相互轉換
- CSS 塊級元素和行內元素和行內塊元素 及其相互轉換CSS
- 透過案例對SparkStreaming透徹理解三板斧之二Spark
- 塊級元素和行內元素分別有哪些