CSS规范 > 8 盒模型 Box Model

2017-07-20: 关于外边距折叠, 推荐问题: https://segmentfault.com/q/10…

8 盒模型 Box Model

URL: http://www.w3.org/TR/CSS2/box…

Translator : HaoyCn

Date: 15th of Aug, 2015

译者注:本译文仅择精要部分翻译了规范,主要描述了盒模型结构,以及重点分析外边距折叠。个人水平有限,欢迎指正!

CSS盒模型所描述的矩形盒由文档树内的元素生成,根据视觉格式化模型布局。

8.1 盒尺寸 Box Dimensions

每个盒都有一个内容区域 Content (如,文本,图片等)以及可选的围绕在周围的内边距、边框和外边距区域;每个区域的大小由本文后述的属性指定。下图展示了这些区域的关联以及用于描述外边距、边框和内边距的各部分的术语。

《CSS规范 > 8 盒模型 Box Model》” /></span></p>
<p>外边距、边框和内边距可以被分解到上、右、下、左各部分(如,在上图中, <code> LM </code> 表示左外边距, <code> RP </code> 表示右内边距, <code> TB </code> 表示上边框等)。</p>
<p>四种区域(内容、内边距、边框、外边距)的边界被称作一个“边缘 <code> Edge </code> ”,因此每个盒有四种边缘:</p>
<p><strong>内容边缘 <code> Content Edge </code> 或内边缘 <code> Inner Edge </code></strong></p>
<p>内容边缘围绕着由盒的宽和高所指定的矩形,该矩形通常由元素的已渲染内容 <code> Rendered Content </code> 所决定。四个内容边缘规定了盒的内容盒 <code> Content Box </code> 。</p>
<p><strong>内边距边缘</strong></p>
<p>内边距边缘围绕着盒的内边距。如果内边距宽度为0,则内边距边缘即是内容边缘。四个内边距边缘规定了盒的内边距盒 <code> Padding Box </code> 。</p>
<p><strong>边框边缘</strong></p>
<p>边框边缘围绕着盒的边框。如果边框宽度为0,则边框边缘即是内边距边缘。四个边框边缘规定了盒的边框盒 <code> Border Box </code> 。</p>
<p><strong>外边距边缘或外边缘</strong></p>
<p>外边距边缘围绕着盒的外边距。如果外边距宽度为0,则外边距边缘即边框边缘。四个外边距边缘规定了盒的外边距盒 <code> Margin Box </code> 。</p>
<p>每个边缘都可以被分解成上、右、下、左边缘。</p>
<p>盒内容区域的尺寸——即内容宽度 <code> Content Width </code> 和内容高度 <code> Content Width </code> ——由这些因素所决定:生成盒的元素是否设置了 <code> width </code> 和 <code> height </code> 属性;盒是否包含了文本或其他盒;盒是否为表格;等等。盒的宽度和高度将在视觉格式化模型详述一章中讨论。</p>
<p>盒的内容、内边距以及边框区域的背景样式由生成盒的元素的 <code> background </code> 属性所规定。外边距的背景始终为透明。</p>
<h3>8.2 外边距、内边距和边框的例子</h3>
<p>下例展示了外边距、内边距和边框如何交互。HTML文档:</p>
<pre><code><!DOCTYPE HTML PUBLIC

该文档结果为文档树中(省略其他关系)一个 ul 元素及其两个 li 子元素。

下面的第一图展示了例子的结果。第二图展示了 ul 元素及其 li 子元素的外边距、内边距和边框之间的关系。(图片不成比例)

《CSS规范 > 8 盒模型 Box Model》” /></span></p>
<p>注意:</p>
<ul>
<li>
<p>每个 <code> li </code> 盒的内容宽度是从上到下计算的;所有 <code> li </code> 盒的包含块由 <code> ul </code> 元素创建。</p>
</li>
<li>
<p>每个 <code> li </code> 盒的外边距盒高度由其内容高度加上上下内边距、边框、外边距所决定。需要留意的是 <code> li </code> 盒间的垂直外边距发生了折叠。</p>
</li>
<li>
<p><code> li </code> 盒的右内边距宽度被设为零( <code> padding </code> 属性)。效果如第二图所示。</p>
</li>
<li>
<p><code> li </code> 盒的外边距是透明的——外边距总为透明——所以 <code> ul </code> 的内边距和内容区域的背景颜色(黄)穿透外边距显示了出来。</p>
</li>
<li>
<p>第二个 <code> li </code> 元素指定了虚线边框( <code> border-style </code> 属性)。</p>
</li>
</ul>
<h3>8.3 外边距各属性</h3>
<p>外边距的各属性规定了盒的外边距区域的宽度。 <code> margin </code> 设置所有四个方向的外边距,而其他外边距属性则只设置各自方向宽度。这些属性应用于所有元素,但垂直外边距在非替代行内元素上无效。</p>
<blockquote>
<p>译者注:此处以及下文的各属性介绍均略,可查CSS手册</p>
</blockquote>
<h4>8.3.1 外边距折叠</h4>
<p>在CSS中,两个及以上的(不一定是同胞)盒的相邻外边距可能合并为一个单独的外边距。以这种方式的合并的外边距被称为折叠 <code> Collapse </code> ,合并后的外边距被称为折叠外边距 <code> Collapsed Margin </code> 。</p>
<p>相邻垂直外边距发生折叠,除了:</p>
<ul>
<li>
<p>根元素的盒的外边距不折叠</p>
</li>
<li>
<p>如果一个有空隙的元素的上下外边距相邻,其外边距将同其后同胞的相邻外边距折叠,但不同父块的下外边距折叠。</p>
</li>
</ul>
<p>水平外边距不重叠。</p>
<p>两个外边距为相邻关系,当且仅当:</p>
<ul>
<li>
<p>是同属一个块格式化上下文的文档流内块级盒</p>
</li>
<li>
<p>没有行盒、空隙、内边距和边框分隔它们(注意某些零高度行盒会因此而被忽略(见9.4.2章))</p>
</li>
<li>
<p>盒边缘垂直相邻,也就是说,满足以下形式之一:</p>
</li>
<li>
<p>盒上外边距及其第一个文档流内子盒的上外边距</p>
</li>
<li>
<p>盒下外边距及下一个文档流内的同胞盒的上外边距</p>
</li>
<li>
<p>如果父盒的高度计算值为 <code> auto </code> ,其最后一个文档流内子盒的下外边距及父盒的下外边距</p>
</li>
<li>
<p>如果一个盒不建立新的块格式化上下文、 <code> min-height </code> 计算值为零、 <code> height </code> 计算值为零或 <code> auto </code> 、没有在文档流内的子盒,其上下外边距</p>
</li>
</ul>
<p>如果一个折叠外边距与另一外边距的任何一边相邻,则视二者相邻。</p>
<p>注意:不是同胞或祖先关系的元素也可以产生相邻外边距。</p>
<p>注意:上述规则表明了:</p>
<ul>
<li>
<p>浮动盒的外边距不同其他任何盒折叠(甚至浮动及其文档流内的子元素也不折叠)</p>
</li>
<li>
<p>创建了新的块格式化上下文的元素(如浮动、 <code> overflow </code> 不为 <code> visible </code> 的元素)的外边距不同其在文档流内的子元素外边距折叠</p>
</li>
<li>
<p>绝对定位盒的外边距不同其他任何盒折叠(甚至不同其文档流内的子元素折叠)</p>
</li>
<li>
<p>行内块盒的外边距不同其他任何盒折叠(甚至不同其文档流内的子元素折叠)</p>
</li>
<li>
<p>文档流内块级元素的下外边距始终同其下一个文档流内的块级同胞的上外边距折叠,除非该对同胞之间有空隙。</p>
</li>
<li>
<p>文档流内块元素如果没有上边框和上内边距,其第一个文档流内块级子元素没有空隙,二者的上外边距折叠。</p>
</li>
<li>
<p>文档流内 <code> height </code> 为 <code> auto </code> 、 <code> min-height </code> 为零、没有下内边距和下边框的块盒,如果其最后一个文档流内块级子盒的下外边距没有同一个有空隙的上外边距折叠,二者下外边距折叠。</p>
</li>
<li>
<p>如果某盒的 <code> min-height </code> 属性为零、没有上下边框和上下内边距、其 <code> height </code> 为0或 <code> auto </code> 、没有包含行盒、其所有的文档流内子元素外边距(如果有)折叠,则折叠其外边距。</p>
</li>
</ul>
<p>当两个及以上外边距折叠,合并后的外边距宽度是发生折叠的外边距中的最大宽度。如果发生折叠的外边距中有负数,则为最大正数相邻外边距减去最小负数相邻外边距的绝对值。如果不存在正数外边距,则为零减去最小负数相邻外边距的绝对值。</p>
<p>如果一个盒的上下外边距相邻,则外边距可能穿过盒而折叠 <code> Collapse Through It </code> 。这种情况下,元素的定位取决于它同其他外边距折叠的元素的关系。</p>
<ul>
<li>
<p>如果该元素的外边距同其父元素的上外边距折叠,则该盒的上边框边缘同其父元盒的上边框边缘相同。</p>
</li>
<li>
<p>否则,要么该元素的父元素的外边距不折叠,要么只有父元素的下外边距折叠。上边框边缘位置是假定该元素下边框非零时的位置。</p>
</li>
</ul>
<p>需要注意的是,被折叠穿过的元素的定位对与之外边距折叠的其他元素的定位无影响;其上边框边缘的定位仅用于布局其后代元素。</p>
<h3>8.6 双向上下文 Bidirectional Context 中行内元素的盒模型</h3>
<p>对每个行盒而言,用户代理必须按视觉顺序(而非逻辑顺序)渲染其生成的行内盒的外边距、边框和内边距。</p>
<p>当元素 <code> direction </code> 属性值为 <code> ltr </code> ,元素呈现的第一个行盒的最左生成盒拥有左外边距、左边框和左内边距,而元素呈现的最后一个行盒的最右生成盒拥有右内边距、右边框和右外边距。</p>
<p>当元素 <code> direction </code> 属性值为 <code> rtl </code> ,元素呈现的第一个行盒的最右生成盒拥有右外边距、右边框和右内边距,而元素呈现的最后一个行盒的最左生成盒拥有左内边距、左边框和左外边距。</p>
<h1>译者之思</h1>
<p>译者读毕此文,细心揣摩,将经验和疑问总结如下:</p>
<h3>一、两种盒模型</h3>
<p>本章节描述了W3C的标准盒模型,同时还存在IE6在怪异模式 <code> Quicks Mode </code> 的另一种盒模型。此处简述二者的区别如下——</p>
<p>W3C标准下:盒总宽/高度 = width/height + padding + border + margin</p>
<p>怪异模式下:盒总宽/高度 = width/height + margin = 内容宽/高度 + padding + border + margin</p>
<p>CSS3中, <code> box-sizing </code> 默认为 <code> content-box </code> ,即采用W3C标准盒模型,若取值 <code> border-box </code> 则采用怪异模式盒模型。</p>
<h3>二、不透明的外边距</h3>
<p>CSS规范道:</p>
<blockquote>
<p>盒的内容、内边距以及边框区域的背景样式由生成盒的元素的 <code> background </code> 属性所规定。外边距的背景始终为透明。</p>
</blockquote>
<p>但在根元素 <code> html </code> 上设置了外边距,并规定了背景,该背景仍铺满全屏。</p>
<p>如下CSS:</p>
<pre><code>html {
margin: 50px;
background: #000;
}</code></pre>
<p><code> body </code> 同此理。译者暂不知其因。欢迎读者指教。</p>
<h3>三、有空隙的元素</h3>
<p>外边距折叠中,很多地方叙述了“有空隙的元素”,这是什么意思呢?其意义即是说,该元素清除了浮动。</p>
<p>在翻译视觉格式化模型一章中,W3C给出了清除浮动以及计算空隙宽度的的案例,译者建议读者认真阅读该部分,尤其关注:当空隙为负值时取消外边距折叠的情形。</p>
<p>点此阅读:<a href=http://segmentfault.com/a/119…。

如果读者已经掌握清除浮动和空隙的知识,那就让我们来看一个有空隙的情景。

如果一个有空隙的元素的上下外边距相邻,其外边距将同其后同胞的相邻外边距折叠,但不同父块的下外边距折叠。

以下代码中, B 是浮动块,为清除其浮动, C 引入了空隙。

共同CSS:

html,body{padding:0;margin:0;}
/*横线,直观对比折叠情况*/
.line{height:50px;background:red;} 
.mt{margin-top:50px;}
.mb{margin-bottom:50px;}
#B{float:left;width:1px;height:1px;}
#C{clear:both;}

其外边距将同其后同胞的相邻外边距折叠:

HTML:

<body>
   <div id="A">
      <div id="B"></div>
      <div id="C" class="mb"></div>
      <div id="D" class="mb"></div>
      <div class="line"></div>
   </div>
 </body>

渲染结果是, C D 的外边距折叠。

不同父块的下外边距折叠

HTML:

 <body>
   <div id="A" class="mb">
      <div id="B"></div>
      <div id="C" class="mb"></div>
   </div>
   <div class="line"></div>
 </body>

渲染结果是, C 的外边距不同其父元素 A 的外边距折叠。

四、避免盒自身垂直外边距折叠

如果一个盒不建立新的块格式化上下文、 min-height 计算值为零、 height 计算值为零或 auto 、没有在文档流内的子盒,其上下外边距

由此可以得出几种避免盒自身上下外边距折叠的办法,简单列举如下:

  1. 建立新块格式化上下文,如 overflow: hidden

  2. 设置 min-height

  3. 设置固定高 height

  4. 添加文档流内(即非浮动、非绝对定位)子盒

需要注意最后一种办法,子盒要么有边框或内边距,要么有内容,否则父盒的自身垂直外边距同样会折叠。而如果子盒只有垂直外边距,该垂直外边距将同父盒的垂直外边距折叠,而不会阻止父盒自身垂直边距折叠。

    原文作者:残阳映枫红
    原文地址: https://segmentfault.com/a/1190000003099116
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞