CSS盒模型 - 官方文檔總結

一直對盒模型的瞭解很零碎,學習都來源於各個文章的隻言片語,這樣學來的既不完善,也不持久。最近通讀了w3的官方文檔,對其中的內容進行一點概括吧。css

盒子的概念

盒子模型指的是瀏覽器將文檔流從視覺上渲染爲不一樣矩形框的組合。
瀏覽器將文檔流中的每一個元素都渲染爲一個矩形框,其包含內容區域(如文本、圖片)和可選的margin/border/padding三個區域,中文名爲外邊距、邊框和填充。以下圖所示:
圖片描述html

這四個區域每個均可以劃分爲上下左右4個部分的邊界,如上邊距、下邊距,上邊框、下邊框等。git

內容邊界:包裹着元素寬度和高度肯定的盒子的四個線段組成。
填充邊界:包裹着元素填充區域的四個線段組成,若是填充寬度爲0,則等於內容邊界。
邊框邊界:包裹着元素邊框區域的四個線段組成,若是邊框寬度爲0,則等於填充邊界。
外邊距邊界:包裹着元素外邊距區域的四個線段組成,若是外邊距寬度爲0,則等於外邊距邊界。

其中內容區域的盒子的寬度和高度由幾個因素來進行肯定,是否設置了寬度和高度值,是否包含文本內容或者其餘的盒子,盒子類型是否爲table相關等等。
內容和填充區域的顏色由background屬性來設置,邊框區域的顏色由border-color || color其中一個屬性來設置,外邊距區域的顏色爲transparent透明色。github

實例

下面的插圖展現了margin/border/padding如何被渲染(圖二是更爲詳細的切分):瀏覽器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
  <HEAD>
    <TITLE>Examples of margins, padding, and borders</TITLE>
    <STYLE type="text/css">
      UL { 
        background: yellow; 
        margin: 12px 12px 12px 12px;
        padding: 3px 3px 3px 3px;
                                     /* No borders set */
      }
      LI { 
        color: white;                /* text color is white */ 
        background: blue;            /* Content, padding will be blue */
        margin: 12px 12px 12px 12px;
        padding: 12px 0px 12px 12px; /* Note 0px padding right */
        list-style: none             /* no glyphs before a list item */
                                     /* No borders set */
      }
      LI.withborder {
        border-style: dashed;
        border-width: medium;        /* sets border width on all sides */
        border-color: lime;
      }
    </STYLE>
  </HEAD>
  <BODY>
    <UL>
      <LI>First element of list
      <LI class="withborder">Second element of list is
           a bit longer to illustrate wrapping.
    </UL>
  </BODY>
</HTML>

圖片描述

須要注意的是:app

  1. 內容區域的計算是自上而下的,全部的li元素的內容區域計算都基於ul父元素。
  2. margin盒子包含了content/padding/border/margin四部分的總和,在縱向上會出現margin的合併。
  3. margin的顏色老是透明的,因此顏色會是父元素的透射顏色。

margin屬性

margin屬性包括margin-top/margin-right/margin-bottom/margin-left 和 marginless

margin-top/margin-right/margin-bottom/margin-left
值:<margin-width> || inherit || auto
初始值: 0
適用於:除了table展現類型的全部元素,table類型裏依然適用的有`table-caption/table/inline-table`
繼承: 否
百分比:根據父包裹容器的寬度
計算值:指定的百分比或固定值

須要注意:margin-top/margin-bottom屬性對行間元素不起做用。
若是使用auto,同時父元素具備對應的寬度和高度,將在計算時均分空餘空間達到居中的效果。ide

margin是以上四種屬性的簡寫,若是隻有一個值,則設置全部邊界;兩個值則第一個值爲top/bottom值,第二個值爲left/right值;三個值則第一個值爲top值,第二個值爲left/right值,第三個爲bottom值;四個值則分別對應top/right/bottom/left四個邊界。佈局

body { margin: 2em }         /* all margins set to 2em */
body { margin: 1em 2em }     /* top & bottom = 1em, right & left = 2em */
body { margin: 1em 2em 3em } /* top=1em, right=2em, bottom=3em, left=2em */

margin的邊界合併

在CSS裏,兩個相鄰元素(並不必定是兄弟元素)的外邊距將會發生合併爲一個外邊距,這個過程咱們成爲collapse。這個過程只會發生在垂直方向上的margin,合併結果是全部外邊距的最大值。
邊界合併的設置是爲了元素佈局的合理展現,如段落間的距離不會成爲頂部的兩倍。
邊界的合併適用於margin-top/margin-bottom,不只僅包括兄弟元素的合併,還有父子元素甚至自身的上下邊距合併。
注意:只有普通文檔流中塊框的垂直外邊距纔會發生外邊距合併。行內框、浮動框或絕對定位之間的外邊距不會合並。
下圖展現margin合併的效果圖(來源於w3school文檔):
兄弟元素外邊距合併:
圖片描述學習

父子元素外邊距合併:
圖片描述

自身元素外邊距合併:
圖片描述

另外官方文檔裏關於合併還有不少的特殊狀況,再也不一一說明,粘貼源文檔:

Adjoining vertical margins collapse, except:

Margins of the root element's box do not collapse.
If the top and bottom margins of an element with clearance are adjoining, its margins collapse with the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block.
Horizontal margins never collapse.

Two margins are adjoining if and only if:

both belong to in-flow block-level boxes that participate in the same block formatting context

no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for this purpose.)
both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
 - top margin of a box and top margin of its first in-flow child
 - bottom margin of box and top margin of its next in-flow following sibling
 - bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
 - top and bottom margins of a box that does not establish a new block formatting context and that has zero computed 'min-height', zero or 'auto' computed 'height', and no in-flow children

A collapsed margin is considered adjoining to another margin if any of its component margins is adjoining to that margin.

Note. Adjoining margins can be generated by elements that are not related as siblings or ancestors.

Note the above rules imply that:

 - Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children).
 - Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
 - Margins of absolutely positioned boxes do not collapse (not even with their in-flow children).
 - Margins of inline-block boxes do not collapse (not even with their in-flow children).
 - The bottom margin of an in-flow block-level element always collapses with the top margin of its next in-flow block-level sibling, unless that sibling has clearance.
 - The top margin of an in-flow block element collapses with its first in-flow block-level child's top margin if the element has no top border, no top padding, and the child has no clearance.
 - The bottom margin of an in-flow block box with a 'height' of 'auto' and a 'min-height' of zero collapses with its last in-flow block-level child's bottom margin if the box has no bottom padding and no bottom border and the child's bottom margin does not collapse with a top margin that has clearance.
 - A box's own margins collapse if the 'min-height' property is zero, and it has neither top or bottom borders nor top or bottom padding, and it has a 'height' of either 0 or 'auto', and it does not contain a line box, and all of its in-flow children's margins (if any) collapse.

When two or more margins collapse, the resulting margin width is the maximum of the collapsing margins' widths. In the case of negative margins, the maximum of the absolute values of the negative adjoining margins is deducted from the maximum of the positive adjoining margins. If there are no positive margins, the maximum of the absolute values of the adjoining margins is deducted from zero.

If the top and bottom margins of a box are adjoining, then it is possible for margins to collapse through it. In this case, the position of the element depends on its relationship with the other elements whose margins are being collapsed.

If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as the parent's.
Otherwise, either the element's parent is not taking part in the margin collapsing, or only the parent's bottom margin is involved. The position of the element's top border edge is the same as it would have been if the element had a non-zero bottom border.
Note that the positions of elements that have been collapsed through have no effect on the positions of the other elements with whose margins they are being collapsed; the top border edge position is only required for laying out descendants of these elements.

順便講一個常見的bug:垂直外邊距合併問題常見於第一個子元素的margin-top會頂開父元素與父元素相鄰元素的間距。其緣由爲父元素和第一個子元素的外邊距進行合併,並選取其最大值,即第一個元素的上邊距,致使撐開父元素上邊距。解決方案爲:設置父元素的border或padding將子元素控制在父元素content內部,防止發生margin合併,即給外部div設置一個透明的1像素的border-top便可。

.outer-box{
  border-top:1px solid transparent;
}

Padding屬性

padding屬性包括padding-top/padding-right/padding-bottom/padding-left 和 padding

padding-top/padding-right/padding-bottom/padding-left
值:<padding-width> || inherit
初始值: 0
適用於:除了`table-row-group/table-header/group/table-footer-group/table-row/table-column-group/table-column`的全部元素
繼承: 否
百分比:根據父包裹容器的寬度
計算值:指定的百分比或固定值

須要注意:margin-top/margin-bottom屬性對行間元素不起做用,且值不能爲負。

margin是以上四種屬性的簡寫,設置的內容和上面一致,元素的個數和含義與margin相同。

border屬性

border屬性包括border-width/border-color/border-style,而其中每個均可以切分爲4塊,如border-left-width/border-top-color。對於不一樣的用戶代理(瀏覽器)會對部分的元素渲染出特定的樣式來,如button,menus等。

border-top-width等
值:<border-width> || inherit || thin || medium || thick
初始值: medium
適用於:全部元素
繼承: 否
百分比:N/A,沒法設置
計算值:絕對值,若是爲none/hidden則轉換爲0

須要注意:thin/medium/thick由不一樣的瀏覽器實現,具體的值不盡相同。

border-top-color等
值:<color> || transparent || inherit
初始值: color的值(字體顏色)
適用於:全部元素
繼承: 否
百分比:N/A,沒法設置
計算值:指定的值或者字體顏色color的值
border-top-style等
值:none || hidden || dotted || dashed || solid || double || groove || ridge || inset || outset || inherit
初始值: none
適用於:全部元素
繼承: 否
百分比:N/A,沒法設置
計算值:指定的值

須要注意:邊框會繪製在全部盒子背景色的上方,在groove/ridge/inset/outset值時,具體的顏色可能會被瀏覽器強制修改,而不只限於border-color屬性。初始值爲none,因此必定要進行設置樣式,不然看不到。

border屬性:    [ <border-width> || <border-style> || <'border-top-color'> ] || inherit

須要注意:border屬性不能像其中三個子屬性同樣分別設置,若是設置其中一個值,則會應用到全部四條邊界上。

margin是以上四種屬性的簡寫,設置的內容和上面一致,元素的個數和含義與margin相同。

下面的兩段樣式只是出現的順序不一樣會顯示出不一樣的效果來,緣由是設置的順序影響到值的覆蓋:

// 左邊框爲雙細線和黑色
blockquote {
  border: solid red;
  border-left: double;
  color: black;
}
// 邊框所有爲實線和紅色
blockquote {
  border-left: double;
  color: black;
  border: solid red;
}

雙向上下文的行間元素的盒模型

在每個行間元素中,瀏覽器須要產生每個盒子按照視覺順序而非邏輯順序(也就是direction設置的方向)進行渲染。
下面的兩句話我實在是看不懂在講什麼,貼出原文:

When the element's 'direction' property is 'ltr', the left-most generated box of the first line box in which the element appears has the left margin, left border and left padding, and the right-most generated box of the last line box in which the element appears has the right padding, right border and right margin.

When the element's 'direction' property is 'rtl', the right-most generated box of the first line box in which the element appears has the right padding, right border and right margin, and the left-most generated box of the last line box in which the element appears has the left margin, left border and left padding.

盒模型相關的周邊問題

  1. inline-block元素之間的小空白
<STYLE type="text/css">
   div {background: #d3cfad;}
   label {background: lightblue;}
 </STYLE>

 <BODY>
  <div>
    <span>第一個元素</span>
    <!-- 這裏的換行和製表符將被轉化爲一個空格 -->
    <span>第二個元素</span>
  </div>
 </BODY>

效果入圖:
圖片描述
緣由爲:HTML 中的換行符、空格符、製表符等合併爲空白符, 字體大小不爲 0 的狀況下, 空白符天然佔據必定的寬度, 所以產生了元素間的空隙.
解決方案:能夠爲inline-block元素設置爲負的margin-left; 或父元素font-size設置爲0, 子元素再從新設置回來等方法。
推薦方案:直接在HTML文檔裏改變文本排列,使行間元素尾標籤和下一個頭便籤間不留任何空格,如

<span>第一個元素</span
><span>第二個元素</span>

由於這樣影響範圍最小,不需任何額外代碼。

參考文獻

  1. w3c官網文檔 - 盒子模型:https://www.w3.org/TR/CSS2/bo...
  2. 你不知道的margin屬性:http://louiszhai.github.io/20...元素之間空白Bug
  3. w3school - CSS外邊距合併:http://www.w3school.com.cn/cs...
相關文章
相關標籤/搜索