(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!)
(注2:更多内容请查看我的目录。)
1. 简介
前面在入门文章中讲到了盒模型还有块级元素和行内元素。现在我们来回顾并重新认识一下盒模型。
2. 再看盒模型
首先,要清楚一件事情。CSS框模型描述了为文档树中的元素生成的矩形框,并根据可视化格式模型进行布局。浏览器在解析和渲染页面时会生成DOMTree 和RenderTree(此处会在后面详细讲解)。CSS作用的是RenderTree,而盒模型就是RenderTree的节点。
每个盒子都有一个content area(例如文本,图像等)以及可选的padding area、border area盒margin area。每个区域的大小由下面定义的属性指定。
margin、border、padding、content分别定义了元素四种边,然后每种类型的边的四条边定义了一个盒子,分别是content box、padding box、border box、margin box。如下图所示:
以下四个盒子组成了一个 box:
- content box:必备,由content area和4条content/inner edge组成;
- padding box:可选,由padding和4条padding edge组成。若padding宽度设置为0,则padding edge与content edage重叠;
- border box:可选,由border和4条border edge组成。若border宽度设置为0,则border edge与padding edage重叠;
- margin box:可选,由margin和4条margin/outer edge组成。若margin宽度设置为0,则margin edge与border edage重叠。
是不是很眼熟,是的,如果你还记得box-sizing属性的话。
CSS3中提供了一个新的属性,box-sizing,来控制和模型的表现形式。box-sizing有三个取值,分别是content-box,border-box和inherit。
(注:其实还有一个padding-box,width和height属性包括内容和内边距,但是不包括边框和外边距。只有Firefox实现了这个值,它在Firefox 50中被删除。)
- content-box
默认值,表现形式同W3C标准和模型。 - border-box
表现形式同IE盒模型,常用值,经常在css-reset中设置。 - inherit
规定应从父元素继承box-sizing属性的值。
现在,我们终于明白了。所谓的W3C标准盒模型和IE盒模型只是在设置width和height时所指定的对象不同而已。W3C标准盒模型是content-box,而IE盒模型是 - border-box。
当然,如果没有特殊指定的情况下,我们默认是使用W3C标准盒模型。如果不想指定box-sizing,想让各浏览器都是用W3C标准盒模型,只要在html文件开头指定<!DOCTYPE html>即可。
另外,一个盒子的content area的宽高取决于如下的因素:
- 元素生成的盒子是否有“宽度”和“高度”属性集
- 盒子里是否包含文本或其他盒子
- 盒子是否是table
etc...
盒模型宽高我们会在今后详细讨论。
而一个盒子的content area,padding area和border area的背景由生成元素的background属性指定,而margin area的背景总是透明的。
3. 盒的生成与类型
上面讨论了盒子的基本组成和在不同浏览器中的表现,这一节我们来看一下盒子的类型。这里所描述的是CSS2.2中可生成的盒类型。CSS 视觉格式化模型的一部分工作是从文档元素生成盒。生成的盒拥有不同类型,并对视觉格式化模型的处理产生影响。生成盒的类型取决于 CSS 属性 display。盒的类型会影响其在视觉格式化模型中的表现。
3.1 块级元素Block-level Elements与块盒Block Boxes
块级元素是指源文档中以块(如段落)的形式被格式化,生成主要块级盒(principal block-level box)的元素。display 属性取以下值会让一个元素成为块级元素: block 、 list-item 以及 table 。
块级盒(Block-level Boxe)是参与块格式化上下文( Block Formatting Context )的盒。每个块级元素生成一个主要的块级盒( principal block-level box)。 一些元素,比如li和list-item,生成额外的盒来放置项目符号,这些额外的盒会相对于主要盒来摆放。不过多数元素只生成一个主要块级盒。
主要的块级盒( principal block-level box)将包含其后代盒和生成的内容,同时参与定位体系 (Positioning Scheme )。
在CSS 2.2中,块级盒(block-level box)也是一个块容器盒 (block container box),除非它是一个表盒(table box)或替换元素(replaced elemen)的主盒(principal box)。一个块容器盒 (block container box)要么只包含块级盒(block-level box),要么只建立一个内联的格式化上下文(Inline Formatting Context)并因此只包含行内级盒(Inline-level Boxes)。
一个主盒(principal box)是块容器盒 (block container box)的元素是一个块容器元素(block container element)。display取如下值时可以是一个非替换元素(non-replaced element)生成一个块容器(block container):'block', 'list-item' 和 'inline-block'。并非所有的块容器盒都是块级盒:非替换的行内块(non-replaced inline blocks) 和非替换的表格单元格 (non-replaced table cells) 也是块容器但不是块级的。
既是块级盒(block-level box)同时也是块容器盒 (block container box)的盒称作块盒(block box) 。
这三个术语,“块级盒”、“块容器盒”、“块盒”在意义明确时可简称为“块”(block)。
3.2 匿名块盒(Anonymous block boxes)
有时需要添加补充性盒,这些盒称为匿名盒(anonymous boxes), 它们没有名字,不能被 CSS 选择符选中。
不能被 CSS 选择符选中意味着不能用样式表添加样式。这意味着所有继承的 CSS 属性值为 inherit ,所有非继承的 CSS 属性值为 initial 。
块容器盒要么只包含行内级盒,要么只包含块级盒。但通常文档会同时包含两者。在这种情况下,将创建匿名块盒来包含毗邻的行内级盒。
<div>
Some inline text
<p>followed by a paragraph</p>
followed by more inline text.
</div>
该段代码将创建两个匿名块盒,一个包含 <p> 前面的文本 (Some inline text), 一个包含 <p> 后面的文本(followed by more inline text), 结构如下:
结果如下所示:
和 <p>元素不同, 开发者不能控制这两个匿名盒。对于可继承属性, 它们将取 <div> 的属性值, 比如 font-size。对于非继承属性,值为初始值 ,比如没有指定 background-color, 值为初始值即 transparent,于是 <div> 背景可见。而 <p> 可以指定 background-color 。类似的,这两个匿名盒文本是一样的颜色。如下:
<style>
div {
background-color: green;
font-size: 30px;
}
p {
background-color: red;
}
</style>
另一种将创建匿名块盒的情况是,一个行内盒包含了一个或几个块盒。当一个行内盒 inline box 包含一个文档流内 In-flow 的块级盒,这个行内盒(及在同一行盒的 Line Box 它的行内祖先)会在该块级盒(及其连续的或者中间只被可折叠空白、脱离文档流元素分隔的块级同胞)的周围打断,把行内盒分离成两个盒(甚至一边为空也如此),各在块级盒一边。在打断之前和打断之后的行盒 Line Box 都被匿名块盒包含,并且该块级盒成为匿名块盒的同胞。当这样的行内盒受到相对定位影响,任何产生的移动同样影响到包含在其中的块级盒。如下:
<body>
<p>
This is anonymous text before the SPAN。
<span>This is the content of SPAN.</span>
This is anonymous text after the SPAN。
</p>
</body>
p 元素包含一段匿名文本 C1 ,接着是一个块级元素,随后又是另一段匿名文本 C2 。结果是一个代表 body 的块盒,它包含了围绕 C1 一个匿名块盒、 span 的块盒,和围绕 C2 的另一个匿名块盒。原来的行内盒p被分割消失了。
当一个元素导致了匿名块盒的生成,则该元素上设置的属性一样能应用于该元素生成的盒和该元素的内容。例如,在上面例子中,如果在 p 元素上设置了边框,则这个边框将画在 C1 (在行的结尾开)和 C2 (在行的结尾闭)周围。
<style>
p {
display: inline;
border: 1px solid red;
}
span {
display: block;
}
</style>
style保持不变,再来看一下两种情况:
<body>
<p>
This is anonymous text before the SPAN。
<span>This is the content of SPAN.</span>
This is anonymous text after the SPAN。
<span>This is the content of SPAN.</span>
<span>This is the content of SPAN.</span>
This is anonymous text after the SPAN。
</p>
</body>
以及
<body>
<p>
This is anonymous text before the SPAN。
<span>This is the content of SPAN.</span>
</p>
</body>
和
<body>
<p>
<span>This is the content of SPAN.</span>
</p>
</body>
说明如果行内盒包含多个块盒,并且这些块盒之间没有夹杂内容,将在这些块盒前后创建匿名块盒,即使其前后内容为空。
3.3 行内级元素Inline-level Elements和行内盒Inline Boxes
行内级元素(Inline-level Elements)是在源文档中那些不为其内容形成新的块的元素,其内容以行形式分布(如,段落内强调文本,行内图片等等)。“display”属性取以下值时产生一个行内级元素(inline-level element): 'inline'、'inline-table'和'inline-block'。行内级元素(inline-level element)生成行内级盒 (Inline-level Boxes) ,而这些盒会参与行内格式化上下文 (Inline Formatting Context) 。
一个行内盒是行内级盒,且其内容参与了该行内盒的行内格式化上下文。一个 display 值是 inline 的不可替换元素会生成一个行内盒。那些不是行内盒的行内级盒(例如可替换的行内级元素 Replaced Inline-level Elements 、行内块元素 inline-block 、行内表格元素 inline-table )被称为原子行内级盒 Atomic Inline-level Boxes ,因为它们以单一不透明盒的形式来参与它们的行内格式化上下文。
我们用下面的例子来看一下它们的区别:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
em {
display: inline;
}
</style>
</head>
<body>
<div style="width:6em;">
<span>em之前的行内盒</span>
<em>em形成的行内盒</em>
<span>em之后的行内盒</span>
</div>
</body>
</html>
结果如下:
发现em的内容参与了em生成行内盒的行内格式化上下文。
再看以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
em {
display: inline-block;
}
</style>
</head>
<body>
<div style="width:6em;">
<span>em之前的行内盒</span>
<em>em形成的原子行内级盒</em>
<span>em之后的行内盒</span>
</div>
</body>
</html>
em生成的原子行内级盒作为一个单一不透明盒与span生成的行内盒区别开来。
3.4 匿名行内盒 Anonymous Inline Boxes
任何直接包含在块容器元素中的文本(不在内联元素内)都必须作为匿名行内元素处理。
一个HTML文档如下:
<p>Some <em>emphasized</em> text</p>
p 产生一个块盒,其中包含了一些行内盒。 emphasized 的盒是一个由行内元素 em 生成的行内盒,但其他盒( some 和 text 的)是由块级元素 p 生成的行内盒。后面这种盒被称作匿名行内盒,因为它们没有相关的行内级元素,没法被选择。这些匿名行内盒继承所有可继承的属性,非继承的属性取初始值(initial value)。在上面例子中,匿名行内盒的 color 从 p 那里继承,但 background 为 transparent 。
空白内容,根据 white-space 属性,如果可被折叠则不会产生任何匿名行内盒。
注:
- 如果可根据上下文来清晰界定一个匿名盒的类型,则匿名行内盒和匿名块盒都可被简称为匿名盒。
- 在格式化表格时,还会有更多类型的匿名盒出现。
3.5 插入盒Run-in boxes
插入盒,由 display:run-in 定义,根据上下文来决定其为块盒还是行内盒。属性根据插入盒的最终状态(行内级还是块级)应用于其上。
4. 影响盒子类型的display属性
看下表是CSS2.2的定义,CSS3的内容我们会在今后讲解。
该属性与“float”和“position”相结合,共同确定了为元素生成的盒的类型(三者关系会在今后讲解)。其值如下:
- block
元素会生成一个块盒(block box) - inline-block
元素会生成一个行内级块容器(inline-level block container),其本身作为一个独立的原子行内级盒参与流布局,就像一个替换元素一样。而其内部内容则按照块盒进行格式化。 - inline
生成行内盒 - list-item
这个值会导致一个元素(例如,HTML中的LI)生成一个主块盒(principal block box)和一个标记盒(marker box)。 - none
元素不出现在格式化结构中(也就是说,在视觉媒体中元素既不产生盒也不影响布局)。其后代元素也不产生任何盒:该元素及其内容会被从格式化结构中完全移除。对后代元素设定 display 属性不能覆盖这个表现。 - table, inline-table, table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, table-caption
使元素表现像一个表格元素一样。
请注意,尽管“display”的初始值是“inline”,但用户代理的默认样式表中的规则可能会覆盖这个值。
参考
https://www.w3.org/TR/css3-box/
https://www.w3.org/TR/CSS22/box.html
https://www.w3.org/TR/CSS22/visuren.html
http://www.w3.org/TR/CSS2/visuren.html
什么是BFC
CSS规范 > 9 视觉格式化模型 Visual Formatting Model
MDN-视觉格式化模型
CSS魔法堂:重新认识Box Model、IFC、BFC和Collapsing margins