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...
相关文章
相关标签/搜索