今天要写的不是CSS标准盒模型和IE盒模型,那个烂大街了。今天要深入探讨的是CSS去控制页面布局背后的那一套规则,页面就是由很多个各式各样的盒组成的,那我们就聊这个。这个是对后面的BFC以及定位模式的一个铺垫,基础很重要!!!
术语普及
盒: 每个元素都会生成一个盒,用来容纳后代(生成的盒)和自己生成的内容(比如说一段文字)。所以我们可以把一个页面看做是由一个个的盒子堆砌而成的,只是这些盒子也分种类,就像这个社会在视觉上由男人和女人构成。
块级元素:display
为block/table/list-item
的元素。
块级盒: 块级元素生成的盒
块容器盒: 块级盒同时也是块容器盒,除了表格盒与可替换元素。顾名思义,块容器盒就是它要容纳后代和它自身的内容。这里面我发现了一个很有趣的事儿,可替换元素,它们都是通过value/src
之类的属性来控制内容显示,可能正是因为它们 无法添加后代元素(或者必须添加特定子元素) 的特性所以才不算是块容器盒的。
内联级元素:display
为inline/inline-block/inline-table
的元素。
内联级盒: 内联级元素生成的盒。但是只有inline
元素生成的盒才叫做内联盒,它区别于inline-block
元素的内联级块盒。
行盒: 内联格式化上下文中,包含来自同一行的盒的矩形区域叫做行盒
可替换元素: 浏览器根据元素的标签和它的属性来决定元素的具体显示内容。比如<img> <input> <textarea> <select> <object>
。
内联元素的一个小特性
这里单独把内联元素给拿出来了,内联元素必须要区别于内联级元素,内联元素只是指 diaplay
为 inline
的元素。
margin-top,margin-bottom
对内联元素无效。padding-top,padding-bottom
对内联元素有效,但它们不能对布局产生任何影响。
上面第一句话比较容易理解,第二句话可能需要通过例子辅助理解。
上图中 padding-top
和 padding-bottom
会影响到块级元素 content
区域位置,会让块级元素的空间真正意义上的变大,进而影响其他元素的位置。但是再看内联元素这边,我们可以看出来 padding
确实存在,但是它没有起到任何影响,没有能够让内联元素占据的空间变大,布局上没有对元素自身起到任何影响,更别提对其他元素产生影响了。可能唯一的作用就是设置 background
的时候, padding
能起到作用。
匿名盒
CSS为了方便布局,它规定:一个块容器盒要么只包含块级盒,要么只包含内联级盒。
匿名块盒
我们来看看CSS会如何对待这段代码:
|
|
大家好,我是 div
,我是一个块容器盒,我发现我的儿子 p
生成了块级盒,那么我其他的儿子也必须都是块级盒。sorry, span
龟儿子,麻烦你变个身,变成块级盒。卧槽,’我是没有任何标签包含的文字’ 这段文本不太好处理啊,他又不是我儿子,不好直接命令他。
幸好老子灵机一动,要不我干脆认他做个干儿子。
div:“文本小孩儿,你愿意做我的干儿子吗?”
文本:“我愿意,爸爸!”
div:“真是个好孩子。但是呢,今天这情况,你们都必须要有一个块级盒,你其他的哥哥们自己会生产,看你小子啥也不会,爸爸就送你一个吧,不过这个盒子无名无分,我们就叫它匿名块盒”
准备工作都做好了,再来看看他们家的家谱吧!
我们可以看到,上面 span
也变成块级盒了,那我们是不是像对待块级元素一样给它设置宽高呢?当然不能!!!所以说,上面的图片是错误的!!!
其实呢, span
这小子作弊了,它明明只是猴子派来的逗逼,当然不能像猴子一样变身,那层块级盒(block box)是它老爸发放的作战物资——匿名块盒。所以呢,真实的情况是:它自己本身只能产生内联盒,然后在它外面还会包裹着一个匿名块盒。
那我们来看一看正确的家谱:
正是因为匿名盒的存在, span
和那段小文本也能够像块级元素一样,单独占据一整行。
那再有一个问题,几个内联元素在一起,它们明明是同一行排列啊,并没有像块级元素一样换行显示。其实呢,多个内联元素在一起,匿名块盒会把相邻的内联盒“打包”,一起包裹起来。
匿名内联盒
任何被直接包含在一个块容器元素中(不在一个内联元素里面)的文本,必须视为一个匿名内联元素。
再来看一段代码:
|
|
大家好,我是 p
元素,我今天看了看我的儿子们,不容易啊,一个块级盒也木有昂,按照CSS当年定下的规矩,这样的情况下,本王必须建立内联格式化上下文(IFC)来安置这群傻孩子。
span
好说啊,自己本身就生成了内联级盒,麻烦的就是这个没有任何标签包围的文本了。咱们还用老方法行不行(⊙v⊙)
p:“文本小孩儿,你愿意做我的干儿子吗?”
文本:“我愿意,爸爸!”
p:“真是个好孩子。但是呢,今天这情况,你们都必须要有一个内联级盒,你其他的哥哥们自己会生产,看你小子啥也不会,爸爸就送你一个吧,不过这个盒子无名无分,我们就叫它匿名内联盒”
闲话不多说,看家谱:
我们可以看到如果一个行盒无法容纳下某个内联盒,这个内联盒就会分割开来放在多个行盒中。注意一下在换行(分割)的地方,是没有竖直线的,表示内联盒未结束,而且 margin,padding
值在这里是不会体现出来的, margin-left,margin-right,padding-left,padding-right
值只存在于内联盒的开始和结束的地方。