星光不问赶路人、岁月不负有心人
前言
假如你想使用 CSS 实现准确布局、处理元素排列,那么理解盒模型的基本原理是关键。
最近面试发现很多工作两三年甚至四五年的小伙伴并不能把盒模型的基本原理说明白,盒模型不仅仅就只是标准盒模型和替代(IE)盒模型,他还包括了很多别的概念。所以有了此篇文章,希望对正在阅读的你有所帮助。
详解
如果你是想仔细的回顾一下盒模型,那么就按顺序阅读,你一定会彻底搞懂盒模型的。如果你只是想回答面试题,那么请直接跳过详解去看总结。
显示类型
在了解盒模型之前咱们需要先了解一下什么是显示类型。显示类型分为内部显示类型和外部显示类型,比如咱们熟知的块级盒子和内联盒子就是由外部显示类型来决定的,而内部显示类型,它决定了盒子内部元素是如何布局的。
内部显示类型
内部显示类型决定了盒子内部元素是如何布局的,默认情况下是按照 正常文档流 布局。
那么正常文档流是如何布局的呢?
一个块级元素的内容宽度是其父元素的 100%,其高度与其内容高度一致。内联元素的 height width 与内容一致,无法设置内联元素的 height width。如果想控制内联元素的尺寸,需要为元素设置display: block; 或者 display: inline-block; inline-block 混合了 inline 和 block 的特性。
同时元素之间也是相互影响的,正常布局流是一套在浏览器视口内放置、组织元素的系统。默认情况下,块级元素按照基于其父元素的排列顺序(默认值:horizontal) 的块流动方向放置,且每个块级元素会在上一个元素下面另起一行,它们会被设置好的 margin 分隔,自上而下排列。块级元素是垂直于组织的。
内联元素的表现和块级元素有所不同,它们不会另起一行。只要在其父级块级元素的宽度内有足够的空间,它们与其他内联元素、相邻的文本内容(或者被包裹的)被安排在同一行。如果空间不够,溢出的文本或元素将移到新的一行。
如果两个相邻的元素都设置了 margin 并且两个 margin 有重叠,那么更大的设置会被保留,小的则会消失,这就是我们常见的外边距叠加。
那么非默认情况下又有哪些布局呢?
通过使用 display 属性值可以更改内部显示类型。 如果为一个元素设置 display: flex,那么这个元素的外部显示类型是 block,但是内部显示类型则已经被修改为了 flex。 该盒子的所有直接子元素都会成为 flex 元素,会根据 弹性盒子(Flexbox )规则进行布局。
外部显示类型
外部显示类型决定盒子是块级盒子还是内联盒子。块级盒子(Block box)和 内联盒子(Inline box)是我们在 CSS 中广泛地使用两种“盒子”。这两种盒子会在页面流(page flow)和元素之间的关系方面表现出不同的行为。
块级盒子
一个盒子如果被定义成块级盒子会表现出以下行为:
- 盒子会在内联的方向上扩展并占据父容器在该方向上的所有可用空间,在绝大数情况下意味着盒子会和父容器一样宽
- 每个盒子都会换行
- width 和 height 属性可以发挥作用
- 内边距(padding), 外边距(margin)和 边框(border)会将其他元素从当前盒子周围“推开”
内联盒子
一个盒子如果被定义成内联盒子会表现出以下行为:
- 盒子不会产生换行。
- width 和 height 属性将不起作用。
- 垂直方向的内边距、外边距以及边框会被应用但是不会把其他处于 inline 状态的盒子推开。
- 水平方向的内边距、外边距以及边框会被应用且会把其他处于 inline 状态的盒子推开。
PS:我们可以通过对盒子 display 属性的设置,比如 block 或者 inline ,来控制盒子是块级盒子还是内联盒子。
盒模型
了解了内部显示类型、外部显示类型和块级盒子、内联盒子以后,咱们就可以进入本文的主题:CSS盒模型。
完整的CSS盒模型应用于块级盒子,内联盒子只使用盒模型中定义的部分内容。
CSS盒模型的每个部分:margin、border、padding和content,合在一起就创建了我们在页面上看到的内容。
CSS盒模型又分为两种:标准盒模型和IE盒模型,其中IE盒模型也有很多别的名称,比如:替代盒模型、怪异盒模型等。
首先先看一下在CSS中组成一个块级盒子都需要哪些东西:
- Content box(内容): 这个区域是用来显示内容,大小可以通过设置 width 和 height.
- Padding box(内边距): 包围在内容区域外部的空白区域; 大小通过 padding 相关属性设置。
- Border box(边框): 边框盒包裹内容和内边距。大小通过 border 相关属性设置。
- Margin box(外边距): 这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过 margin 相关属性设置。
标准盒模型
在标准盒模型中,如果给盒子设置 width 和 height,实际上设置的是内容(content box)的宽高, padding 和 border 加上设置的宽高一起才是整个盒子的大小。举个例子:
假设为一个div元素定义了 width、height、margin、border和padding:
div {
width: 350px;
height: 150px;
margin: 25px;
padding: 25px;
border: 5px solid black;
}
那么标准盒模型的宽度为:410px (350 + 25 + 25 + 5 + 5),高度为:210px (150 + 25 + 25 + 5 + 5)。因为标准盒模型的宽和高是由:内容(content box)+ 内边距(padding)+ 边框(border)的总和来决定的。
PS:需要注意的是 margin 不计入实际大小,但它会影响盒子在页面中所占的空间。
替代(IE)盒模型
IE盒模型和IE浏览器其实没有多大的关系,并不是IE浏览器没了就没有IE盒模型了。
IE盒模型只是一种盒模型的叫法。在chrome中我们也可以使用IE盒模型,只需要设置 box-sizing: border-box 属性就可以开启IE盒模型。那么为什么把这种盒模型叫做IE盒模型呢?这只是一个历史问题,因为在很早以前IE低版本的浏览器默认使用的都是IE盒模型,且不可切换,所有有了这个爱称。但后来IE8及其以上版本默认盒模型都使用了标准盒模型。身在“和平年代”的你,可能永远体会不到曾经的前辈们,写一个盒子模型都要写兼容,因为相同的代码他在不同浏览器中显示出来的样式完全不一样。
在IE盒模型中,元素的宽高就是内容(content box)的宽高,(width = 350px, height = 150px)。
总结
最后总结一下:
- CSS的每一个盒子模型都有自己的内部显示类型和外部显示类型。
- 内部显示类型决定了盒子内部元素的布局,例如是正常布局还是弹性盒子布局。
- 外部显示类型决定了盒子是块级盒子还是内联盒子,其中通过设置dispaly属性的值(block或者inline)可以把盒子改变为块级盒子或者内联盒子。
- 完整的CSS盒模型应用于块级盒子,其组成部分为:内容(content)、内边距(padding)、边框(border)和外边距(margin)。
- CSS盒模型分为标准盒模型和IE盒模型。标准盒模型中元素的宽高为:内容(content)+ 内边距(padding)+ 边框(border),而IE盒模型中元素的宽高就是内容的宽高,因为内边距和边框的值是包含在所设置的width和height里面的。
- 最后IE盒模型并不是独属于IE浏览器的,只是因为在很早以前IE低版本的浏览器默认使用的都是IE盒模型。 在chrome中我们也可以使用IE盒模型,通过设置 box-sizing 属性的值就可以切换盒模型。
- box-sizing 属性有三个值,分别是:content-box、border-box和inherit,content-box为默认值,默认为标准盒模型,border-box为IE盒模型,inherit为继承父元素的 box-sizing 属性。
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。