重拾CSS规范之从盒类型谈起

今天要写的不是CSS标准盒模型和IE盒模型,那个烂大街了。今天要深入探讨的是CSS去控制页面布局背后的那一套规则,页面就是由很多个各式各样的盒组成的,那我们就聊这个。这个是对后面的BFC以及定位模式的一个铺垫,基础很重要!!!

术语普及

盒: 每个元素都会生成一个盒,用来容纳后代(生成的盒)和自己生成的内容(比如说一段文字)。所以我们可以把一个页面看做是由一个个的盒子堆砌而成的,只是这些盒子也分种类,就像这个社会在视觉上由男人和女人构成。
块级元素: displayblock/table/list-item 的元素。
块级盒: 块级元素生成的盒
块容器盒: 块级盒同时也是块容器盒,除了表格盒与可替换元素。顾名思义,块容器盒就是它要容纳后代和它自身的内容。这里面我发现了一个很有趣的事儿,可替换元素,它们都是通过 value/src 之类的属性来控制内容显示,可能正是因为它们 无法添加后代元素(或者必须添加特定子元素) 的特性所以才不算是块容器盒的。
内联级元素: displayinline/inline-block/inline-table 的元素。
内联级盒: 内联级元素生成的盒。但是只有 inline 元素生成的盒才叫做内联盒,它区别于 inline-block 元素的内联级块盒。
行盒: 内联格式化上下文中,包含来自同一行的盒的矩形区域叫做行盒
可替换元素: 浏览器根据元素的标签和它的属性来决定元素的具体显示内容。比如 <img> <input> <textarea> <select> <object>

内联元素的一个小特性

这里单独把内联元素给拿出来了,内联元素必须要区别于内联级元素,内联元素只是指 diaplayinline 的元素。

margin-top,margin-bottom 对内联元素无效。
padding-top,padding-bottom 对内联元素有效,但它们不能对布局产生任何影响。

上面第一句话比较容易理解,第二句话可能需要通过例子辅助理解。

Image losted

上图中 padding-toppadding-bottom 会影响到块级元素 content 区域位置,会让块级元素的空间真正意义上的变大,进而影响其他元素的位置。但是再看内联元素这边,我们可以看出来 padding 确实存在,但是它没有起到任何影响,没有能够让内联元素占据的空间变大,布局上没有对元素自身起到任何影响,更别提对其他元素产生影响了。可能唯一的作用就是设置 background 的时候, padding 能起到作用。

匿名盒

CSS为了方便布局,它规定:一个块容器盒要么只包含块级盒,要么只包含内联级盒。

匿名块盒

我们来看看CSS会如何对待这段代码:

1
2
3
4
5
<div>
<span>我是span内的文字</span>
<p>我是p内的文字</p>
我是没有任何标签包含的文字
</div>

大家好,我是 div ,我是一个块容器盒,我发现我的儿子 p 生成了块级盒,那么我其他的儿子也必须都是块级盒。sorry, span 龟儿子,麻烦你变个身,变成块级盒。卧槽,’我是没有任何标签包含的文字’ 这段文本不太好处理啊,他又不是我儿子,不好直接命令他。

幸好老子灵机一动,要不我干脆认他做个干儿子。

div:“文本小孩儿,你愿意做我的干儿子吗?”

文本:“我愿意,爸爸!”

div:“真是个好孩子。但是呢,今天这情况,你们都必须要有一个块级盒,你其他的哥哥们自己会生产,看你小子啥也不会,爸爸就送你一个吧,不过这个盒子无名无分,我们就叫它匿名块盒”

准备工作都做好了,再来看看他们家的家谱吧!

Image losted

我们可以看到,上面 span 也变成块级盒了,那我们是不是像对待块级元素一样给它设置宽高呢?当然不能!!!所以说,上面的图片是错误的!!!

其实呢, span 这小子作弊了,它明明只是猴子派来的逗逼,当然不能像猴子一样变身,那层块级盒(block box)是它老爸发放的作战物资——匿名块盒。所以呢,真实的情况是:它自己本身只能产生内联盒,然后在它外面还会包裹着一个匿名块盒。

那我们来看一看正确的家谱:

Image losted

正是因为匿名盒的存在, span 和那段小文本也能够像块级元素一样,单独占据一整行。

那再有一个问题,几个内联元素在一起,它们明明是同一行排列啊,并没有像块级元素一样换行显示。其实呢,多个内联元素在一起,匿名块盒会把相邻的内联盒“打包”,一起包裹起来。

匿名内联盒

任何被直接包含在一个块容器元素中(不在一个内联元素里面)的文本,必须视为一个匿名内联元素。

再来看一段代码:

1
2
3
4
<p>
<span>我是span中的文字我是span中的文字我是span中的文字</span>
我是没有任何标签包含的文字
<p>

大家好,我是 p 元素,我今天看了看我的儿子们,不容易啊,一个块级盒也木有昂,按照CSS当年定下的规矩,这样的情况下,本王必须建立内联格式化上下文(IFC)来安置这群傻孩子。

span 好说啊,自己本身就生成了内联级盒,麻烦的就是这个没有任何标签包围的文本了。咱们还用老方法行不行(⊙v⊙)

p:“文本小孩儿,你愿意做我的干儿子吗?”

文本:“我愿意,爸爸!”

p:“真是个好孩子。但是呢,今天这情况,你们都必须要有一个内联级盒,你其他的哥哥们自己会生产,看你小子啥也不会,爸爸就送你一个吧,不过这个盒子无名无分,我们就叫它匿名内联盒”

闲话不多说,看家谱:

Image losted

我们可以看到如果一个行盒无法容纳下某个内联盒,这个内联盒就会分割开来放在多个行盒中。注意一下在换行(分割)的地方,是没有竖直线的,表示内联盒未结束,而且 margin,padding 值在这里是不会体现出来的, margin-left,margin-right,padding-left,padding-right 值只存在于内联盒的开始和结束的地方。

热评文章