参考
- MDN中对The box model的讲解(English)
- 杭州饥人谷前端课程
1. 通俗理解盒模型
通俗的或专业的说,盒(box)的实质是容器(container)。既然是容器,我们就可以将它拿碗来类比。下图是一张丑丑的宜家碗(图来自网络):
宜家碗当我们计算一个桌子上能放几碗饭、多少饭时,我们通常会计算这样几个因素:
- 碗的直径
- 碗的厚度
- 碗与碗之间的距离
虽然例子有点牵强,但这非常有助于我们理解盒模型。回到正题中。在学过HTML之后,我们发现html标签(tag)的实质是内容容器,也就可以类比为一个一个的碗。CSS盒模型正是基于这种假设展开的。
怎样类比呢?
- 内容(content)放到碗中。
- 剩下的事情就是看是装在薄薄的不锈钢碗还是装在厚瓷大碗中,当然,你愿意的话也可以放在厚重的重庆火锅里。(设置碗的厚度)
- 最后就是摆桌子啦,摆成一桌满汉全席还是一桌地摊般凌乱,全看怎么摆(设置碗与碗的距离)
而在网页中,负责摆桌子的就是css。
这样一来就很容易理解了。
2. 两种“碗”--块级盒子(Block box) 和 内联盒子(Inline box)
在CSS中我们通用两种碗--块级盒子与内联盒子1。这两种盒子在页面流(page flow)中的表现是不同的,也就是两种盒子在页面中的显示方式不同。
块级盒子的特征如下1:
- 每个元素占一行。比如并排的10个
<div>
元素就会占据10行。 - 会在行内扩展,以填充所有可用空间。这就意味着,大多数情况下块级盒子会和元素一样宽。
- 可以使用
width
和height
指定宽度与高度。 - 指定
padding
、margin
、border
属性会将其他盒子“推开”。
第二条也就是说,每个块级元素会尽可能地占据一整行,不论实际内容如何。
常见的块级盒子标签有:
<div>
<h1> ~ <h6>
<p>
内联盒子的特征如下1:
- 从左到右,盒子不会换行。
-
width
和height
无用。 - 垂直方向的
padding
、margin
、border
属性不会“推开”其他盒子。 - 水平方向的
padding
、margin
、border
属性才会“推开”其他盒子。
常见的内联盒子标签有:
<a>
<span>
除了上两者之外,还有一种结合类型:inline-block
。特征如下:
- 与
inline
相似,从左到右不换行 - 与
block
相似,可以使用width
与height
3. 正式理解盒模型
那么什么是盒模型呢?回想第一部分所举的“碗”的例子。一个碗,我们可以计量它的直径(半径)、厚度、两碗间距离。同样的,一个盒(box),我们可以计量的部分如下:
-
content box:这个区域是用来显示内容的,大小可以通过设置
width
和height
。类比:用来装米饭的部分 -
padding box:包围在内容区域外部的空白区域; 大小通过
padding
相关属性设置。类比:在碗上还套了个袋 -
border box:边框盒包裹内容和内边距。。大小通过
border
相关属性设置。类比:碗的厚度 -
margin box:这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过
margin
相关属性设置。类比:两碗距离。
可以在浏览器(Chrome、Edge、Firefox,前俩某种程度上是一回事)中按F12用开发者工具查看盒模型。如下图:
image.png在使用时,我们可以使用两种盒模型:
-
content-box
:内容是盒子的边界 -
border-box
:border
是盒子的边界
一般情况下用后者,计量省事的多。有两个计算公式要记得:
-
content-box
的width
:content的宽度 -
border-box
的width
:content + padding + border
俩例子:
例1:content-box
可以看出,光内容就占了100px
的宽度。
例2:border-box
内容+padding+border共计100px
。
4. margin合并与阻止它
如果在父子元素与兄弟元素指定了margin元素的大小,则会发生margin合并现象。举个例子说明,我们在word排版时,会指定段与段之间的距离,指定段前0.5行,段后0.5行,这样一来两段便可以相距1行。但在CSS中,实际效果是如果这样指定的话,两段相距的是0.5行。原因是发生了margin合并。
那么,如何阻止margin合并现象的发生呢?
在css中,发生margin合并有两种情况:
- 父子合并(学过面向对象编程的都懂,也就是子元素继承父元素的margin)
- 兄弟合并(如上面的设置段间距的例子)
取消也分为上两种情况。
父子合并的阻止合并的方法有如下:
- 可以用
padding
或border
挡住 - 也可以用
overflow : hidden
挡住 - 还可以用
display: flex
兄弟合并的方法如下:
inline-block
网友评论