框和布局

KB005: CSS 层叠 中已经介绍了 CSS 的重要之处。CSS 可以说是页面表现的基础, CSS 可以控制布局,控制元素的渲染。

布局是讲在电影画面构图中,对环境的布置、人物地位的调度、人物之间的关系、人物和景物的关系等的安排。大同小异,CSS 的布局也是一样。

CSS 的布局,包含两个大部分:

  • 元素:元素及其组成,类似电影布局中人物的高矮胖瘦、衣着配饰等,以及场景中的桌椅板凳,物品等等。
  • 定位:元素的位置, 类似电影场景的中对环境的设置,人物作为元素,他们之间的关系会影响其在场景中的位置。

总的说来,CSS 的布局比电影场景布局简单的多,因为 CSS 中要控制的元素都是死的,而人是活的有思想的(无思想的道具除外~~)。

元素和框模型

观察页面的构成元素,其中包括 SPAN DIV TABLE INPUT IMG 等等。

仔细观察每个元素,它们的形状都是矩形的,严格的说,元素形成了一个矩形的区域,这个区域就是 CSS 中最基本的布局要素, 常被称作 "box",你可以在很多 W3C CSS2.1 规范的原文中看到 "box" 这个字眼。本篇文章要讲的主要内容, 就是关于 "box" 组成及其变化的一系列规则,也就是今天要讲的内容:"Box Module",通常被译作“盒子模型”,有的地方被译作“框模型”。 因为 W3C 的很多地方用到了 "box" 这个词,有些地方译作“盒子”不大通顺,权且统统译作“框”。

本部分主要包括两部分:框的组成以及相关特性( property ),外边距折叠( Collapsing margins )。

框的构成以及相关 CSS 特性( property )

结构

为了给文档树中的各个元素排版定位(布局),浏览器会根据渲染模型1为每个元素生成四个嵌套的矩形框, 分别称作 content box、padding box、border box 和 margin box,它们是不可分割的,并可能会重合, 这就是 CSS 规范中描述的“框模型”(box model)。它是以 CSS 的角度去看一个元素被渲染后的抽象形态。 是一个元素自身的构成部分,不同于布局:多个元素在页面上的定位。


注:padding、border 和 margin 区域都包括 top、right、bottom、left 四部分。如图所示("LM" 代表 left margin,"RP" 代表 right padding,"TB" 代表 top border……)。

上面的大框,代表一个元素生成的矩形区域( box ),每一个 box 都包括一个 content 区域(元素的内容,如文本,图形等)以及环绕其四周的 padding (元素的内边距,填充部分)、border (元素的边框) 和 margin (元素的外边距) 区域。

注:

  1. 元素在页面上定位及布局的规则,包括 'position' 和 'float' 等等,详见: W3C CSS2.1 -- 9 Visual formatting model
边界

上述四个区域(content、 padding、border 和 margin)分别有他们自己的边界,细化来说,每个区域都有 top、right、bottom、left 四个边界。

  • Content 边界/内边界:Content 边界环绕在由该元素的宽和高决定的一个矩形上,这个尺寸通常由该元素渲染后的内容决定。 这四个 content 边界组成的矩形框就是该元素的 content box。
  • Padding 边界:Padding 边界环绕在该元素的 padding 区域的四周,顾名思义,填充背景色,在此范围内有效。如果 padding 的宽度为0, 则 padding 边界与 content 边界重合。这四个 padding 边界组成的矩形框就是该元素的 Padding box。
  • Border 边界:Border 边界环绕在该元素的 border 区域的四周,如果 border 的宽度为0,则 border 边界与 padding 边界重合。 这四个 border 边界组成的矩形框就是该元素的 border box。
  • Margin 边界/外边界:Margin 边界环绕在该元素的 margin 区域的四周,如果 margin 的宽度为0,则 margin 边界与 border 边界重合。 这四个 margin 边界组成的矩形框就是该元素的 margin box。

一个简单的例子,来自 W3C 官方:

<!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>
<LI class="withborder">Second element of list is
a bit longer to illustrate wrapping.</LI>
</UL>
</BODY>
</HTML>

示意图:

相关 CSS 特性:padding、margin 和 border1
1). margin

'margin' 是 'margin-top', 'margin-right', 'margin-bottom', 'margin-left' 的简写,表明 margin 的大小范围。 它的值可以是 宽度值、百分比值或 'auto' 这3者之一,注意:宽度值必须带有单位。

margin 非 table 类型的元素,以及 table 类型中 table-caption, table 和 inline-table 这3类。例如 TD TR TH 等,margin 是不适用的。 并且,对于行内非替换元素(例如 SPAN),垂直方向的 margin 不起作用。

<div style="border:1px solid red;">
<span style="margin:100px; background:gray;">ddd</span>
</div>

可以看到,DIV 的上下 border 紧贴着灰色的 SPAN 元素。

另外,垂直方向上的不同元素的相邻的 margin 在某些情况下,会发生折叠的现象。

2). padding

padding 是 'padding-top', 'padding-right', 'padding-bottom', 'padding-left' 的缩写。默认值是 0。

可以应用到的元素:除 display 值是 ‘table-row-group’,‘table-header-group’, ‘table-footer-group’, ‘table-row’, ‘table-column-group’ 和 ’table-column’ 的所有元素。

3). border

border 是 'border- top', 'border-right', 'border-bottom', 'border-left' 的缩写。

border 包含3个部分,’border-width’,’border- color’,’border-style’,分别用来设置它的宽度,颜色和样式。适用于任何元素。

border-width 是 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'。默认值是0。 可用值有‘thin’,‘medium’,‘thick’,以及常用的数值带单位的宽度值。

border-color 是 'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color' 的简写。默认值是 ‘color’ 特性的值。

border-style 是 'border-top-style', 'border-right-style', 'border-bottom-style', 'border-left-style' 的简写。默认值是 none 特性的值。 可用值有:’none’,’hidden’,’dotted’,’dashed’,’solid’,’double’,’groove’,’ridge’,’inset’等。

注:

  1. 详见:W3C CSS2.1 - 8 Box model

外边距折叠( Collapsing margins )1

在介绍 margin 特性的时候,简单的介绍了外边距折叠。

Collapsing margins,即外边距折叠,指的是毗邻的两个或多个外边距 (margin) 会合并成一个外边距。

其中所说的 margin 毗邻,可以归结为以下两点:

  • 这两个或多个外边距没有被非空内容、padding、border 或 clear 分隔开
  • 这些 margin 都处于普通流中2

下面详细的介绍其规则。

注:

  1. 详见:W3C CSS2.1 - 8.3.1 Collapsing margins
  2. 既 in-flow,非浮动元素,非定位元素(即规范内的非 absolutely positioned,这里不写为绝对定位元素是为了避免与样式设定中的绝对定位名词在中文中产生混淆)。
两个或多个毗邻的普通流中的块元素垂直方向上的 margin 会折叠
关键词解析

两个或多个

说明其数量必须是大于一个,又说明,折叠是元素与元素间相互的行为,不存在 A 和 B 折叠,B 没有和 A 折叠的现象。

毗邻

是指没有被非空内容、padding、border 或 clear 分隔开,说明其位置关系。

注意一点,在没有被分隔开的情况下,一个元素的 margin-top 会和它普通流中的第一个子元素(非浮动元素等)的 margin-top 相邻; 只有在一个元素的 height 是 "auto" 的情况下,它的 margin-bottom 才会和它普通流中的最后一个子元素(非浮动元素等)的 margin-bottom 相邻。

示例代码:

<div style="border:1px solid red; width:100px;">
<div style="margin:50px 0; background-color:green; height:50px; width:50px;">
<div style="margin:20px 0;">
<div style="margin:100px 0;">B</div>
</div>
</div>
</div>

效果图:

以上代码中,margin 会把 B 的包含块撑开。

如果一个元素的 height 特性的值不是 auto,那么它的 margin-bottom 和它子元素的 margin-bottom 不算相邻,因此,不会发生折叠。 margin-top 没有此限制,所以是 100px,margin-bottom 没有折叠,只有 50px。

垂直方向

是指具体的方位,只有垂直方向的 margin 才会折叠,也就是说,水平方向的 margin 不会发生折叠的现象。

折叠后 margin 的计算
1). 参与折叠的 margin 都是正值

例子:

<div style="height:50px; margin-bottom:50px; width:50px; background-color: red;">A</div>
<div style="height:50px; margin-top:100px; width:50px; background-color: green;">B</div>

示意图:

在 margin 都是正数的情况下,取其中 margin 较大的值为最终 margin 值。

2). 参与折叠的 margin 都是负值

当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从 0 位置,负向位移。

示例代码:

<div style="height:100px; margin-bottom:-75px; width:100px; background-color: red;">A</div>
<div style="height:100px; margin-top:-50px; margin-left:50px; width:100px; background-color: green;">B</div>

示意图:

3). 参与折叠的 margin 中有正值,有负值

如果,毗邻的 margin 中有正值,同时存在负值会怎样呢?有正有负,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。

示例代码:

<div style="height:50px; margin-bottom:-50px; width:50px; background-color: red;">A</div>
<div style="height:50px; margin-top:100px; width:50px; background-color: green;">B</div>

示意图:

上面的例子最终的 margin 应该是 100 + (-50) = 50px。

4). 相邻的 margin 要一起参与计算,不得分步计算

要注意,相邻的元素不一定非要是兄弟节点,父子节点也可以,即使不是兄弟父子节点也可以相邻。

而且,在计算时,相邻的 margin 要一起参与计算,不得分步计算。

一个复杂的实例:

<div style="margin:50px 0; background-color:green; width:50px;">
<div style="margin:-60px 0;">
<div style="margin:150px 0;">A</div>
</div>
</div>
<div style="margin:-100px 0; background-color:green; width:50px;">
<div style="margin:-120px 0;">
<div style="margin:200px 0;">B</div>
</div>
</div>

错误的计算方式:算 A 和 B 之间的 margin,分别算 A 和其父元素的折叠,然后与其父元素的父元素的折叠,这个值算出来之后,应该是 90px。依此法算出 B 的为 80px;然后,A和B折叠,margin 为 90px。

请注意,多个 margin 相邻折叠成一个 margin,所以计算的时候,应该取所有相关的值一起计算,而不能分开分步来算。

以上例子中,A 和 B 之间的 margin 折叠产生的 margin,是6个相邻 margin 折叠的结果。将其 margin 值分为两组:

  • 正值:50px,150px,200px
  • 负值:-60px,-100px,-120px

根据有正有负时的计算规则,正值的最大值为 200px,负值中绝对值最大的是 -120px,所以,最终折叠后的 margin 应该是 200 + (-120) = 80px。

浮动元素、inline-block 元素、绝对定位元素的 margin 不会和垂直方向上其他元素的 margin 折叠

浮动元素的 margin 在垂直方向上也不会发生 margin 折叠,即使和它相邻的子元素也不会。

<div style="margin-bottom:50px; width:50px; height:50px; background-color:green;">A</div>
<div style="margin-top:50px; width:100px; height:100px; background-color:green; float:left;">
<div style="margin-top:50px; background-color:gold;">B</div>
</div>

示意图:

两个绿色的块儿之间,相距100px,而若 B 和它的浮动包含块发生 margin 折叠的话,金色的条应该位于绿色块的最上方,显然,没有发生折叠。

创建了块级格式化上下文1的元素,不和它的子元素发生 margin 折叠

以 “overflow : hidden” 的元素为例:

<div style="margin-top:50px; width:100px; height:100px; background-color:green; overflow:hidden;">
<div style="margin-top:50px; background-color:gold;">B</div>
</div>

若 B 和它的 "overflow:hidden" 包含块发生 margin 折叠的话,金色的条应该位于绿色块的最上方,否则,没有发生。

示意图:

元素自身的 margin-bottom 和 margin-top 相邻时也会折叠

自身 margin-bottom 和 margin-top 相邻,只能是自身内容为空,垂直方向上 border、padding 为 0。

示例:

<div style="border:1px solid red; width:100px;">
<div style="margin-top: 100px;margin-bottom: 50px;"></div>
</div>

以上代码运行后,我们讲得到的是红色边框的正方形,方框的宽高都应该是 100px,高度不应该是 150px。

示意图:

注:

  1. 既,Block formatting contexts,参考W3C CSS2.1 - 9.4.1 Block formatting contexts

转载:http://www.w3help.org/zh-cn/kb/006/

CSS 框模型( Box module )的更多相关文章

  1. KB006: CSS 框模型( Box module )

    框和布局 在 KB005: CSS 层叠 中已经介绍了 CSS 的重要之处.CSS 可以说是页面表现的基础, CSS 可以控制布局,控制元素的渲染. 布局是讲在电影画面构图中,对环境的布置.人物地位的 ...

  2. CSS 框模型

    CSS 框模型 CSS 框模型概述 CSS 内边距 CSS 边框 CSS 外边距 CSS 外边距合并 一,CSS 框模型 (Box Model) 规定元素框处理元素内容.内边距.边框 和 外边距 的方 ...

  3. CSS框模型(框模型概述、内边距、边框、外边距、外边距合并)

    CSS 框模型概述 CSS 框模型 (Box Model) 规定了元素框处理元素内容.内边距.边框 和 外边距 的方式. 元素框的最内部分是实际的内容,直接包围内容的是内边距.内边距呈现了元素的背景. ...

  4. CSS 框模型——规定了元素框处理元素内容、内边距、边框和外边距的方式

    转自:http://www.w3school.com.cn/css/css_boxmodel.asp 要知道在父元素:float, rel, abs位置情况下,box模型的变换情况,请见:http:/ ...

  5. CSS学习总结2:CSS框模型

    1.CSS框模型概述 CSS框模型规定了元素框处理元素内容.内边框.边框和外边框的方式. 元素框的最内部分是实际的内容,直接包围内容的是内边距.内边距呈现了元素的背景.内边距的边缘是边框.边框以外是外 ...

  6. CSS框模型:一切皆为框 — 从行框说起

    一 行框 看图说话 css 行框 各部分详解 上图代表了框模型中的行框.line-height 属性设置行间的距离(行高).该属性会影响行框的布局.在应用到一个块级元素时,它定义了该元素中基线之间的最 ...

  7. css盒模型(Box Model)

    所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用. CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和 ...

  8. CSS| 框模型-定位及相關屬性

    CSS 定位 (Positioning) 属性允许你对元素进行定位. CSS 定位和浮动 CSS 为定位和浮动提供了一些属性,利用这些属性,可以建立列式布局,将布局的一部分与另一部分重叠,还可以完成多 ...

  9. css框模型

    元素的背景是内容.内边距和边框区的背景. css中:width 和 height 指的是内容区域的宽度和高度.增加内边距.边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸. bootstr ...

随机推荐

  1. 利用GBDT模型构造新特征

    [本文链接:http://www.cnblogs.com/breezedeus/p/4109480.html,转载请注明出处] 我的博客主营地迁至github,欢迎朋友们有空去看看:http://br ...

  2. Windows 8 一起学习

    收藏慢慢看 http://www.devdiv.com/Windows_Phone-windows_-thread-130302-1-1.html

  3. Java学习笔记七——数组工具类Arrays

    数组工具类Arrays Java提供的Arrays类里包含的一些static修饰的方法可以直接操作数组.若将里面的方法用熟的话,那开发效率会大大提高.下面介绍其中的方法. List<T> ...

  4. 查看Linux内存状况的命令及工具

    1.cat  /proc/meminfo cat  /proc/<pid>/statm  和 cat  /proc/<pid>/status  获取特定的进程的内存信息: 2. ...

  5. 开源的EtherCAT Master简介

    EtherCAT的主站开发是基于EtherCAT机器人控制系统的开发中非常重要的环节.目前常见开源的主站代码为的RT-LAB开发的SOEM (Simple OpenSource EtherCAT Ma ...

  6. 连接MySQL数据库(android、php、MySQL)

    管理MySQL数据库最简单和最便利的方式是PHP脚本.运行PHP脚本使用HTTP协议和android系统连接.我们以JSON格式编码数据,因为Android和PHP都有现成的处理JSON函数. 下面示 ...

  7. Visual Studio 2010中的stdafx.h和targetver.h两个头文件是有什么用?

    来自百度~stdafx.h中没有函数库,只是定义了一些环境参数,使得编译出来的程序能在32位的操作系统环境下运行. Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程 ...

  8. Paxos算法细节详解(一)--通过现实世界描述算法

    Paxos分析 最近研究paxos算法,看了许多相关的文章,概念还是很模糊,觉得还是没有掌握paxos算法的精髓,所以花了3天时间分析了libpaxos3的所有代码,此代码可以从https://bit ...

  9. 使用IronPython给.Net程序加点料

    开发的时候,经常被策划频繁变动的方案而苦恼.这时候就想要加入点动态语言来辅助一下. 在考虑用动态语言之前也曾想过使用动态加载dll的方式,实现基础接口来调用.在卸载的时候遇到了问题,虽可以通过应用程序 ...

  10. 高性能网站架构设计之缓存篇(2)- Redis C#客户端

    在上一篇中我简单的介绍了如何利用redis自带的客户端连接server并执行命令来操作它,但是如何在我们做的项目或产品中操作这个强大的内存数据库呢?首先我们来了解一下redis的原理吧. 官方文档上是 ...