视觉格式化模型
之前介绍的 CSS 属性值的计算是 CSS 的第一个重点,另外一个就是本文的主题——视觉格式化模型(Visual Formatting Model)。
什么是视觉格式化模型?
盒子模型规定了单个盒子的规则,而视觉格式化模型则规定了如何将这些盒子放置在页面上。视觉格式化模型,你也可以将其理解为布局规则:视觉格式化模型大体将页面中盒子的排列分为了三种方式:常规流、浮动和绝对定位。
常规流布局
常规流,也可以叫做文档流、普通文档流或者常规文档流,是浏览器默认的布局方式,它规定了盒子在页面中的排列方式。总体规则是——块盒独占一行,行盒水平依次排列。
包含块(Containing Block)
每个盒子都有它的包含块,包含块决定了盒子的排列区域。绝大部分情况下,盒子的包含块,就是它父元素的内容盒。
块盒
- 每个块盒的总宽度(content + padding + border + margin)必须等于包含块宽度。
- 宽度的默认值是 auto,auto 就代表吸收剩余空间的能力。
- magin 的默认值是 0,但可以设置为 auto。
- width 和 margin 同时为 auto 时,width 会优先获得 auto ,margin 会优先获得
0
。 - 若 content + padding + border + margin 的总宽度仍然不够,则 margin-right 会自动获得 auto,吸收剩余空间。
- 在常规流中,块盒可以通过
width 固定; margin-left: auto; margin-right: auto;
实现水平居中。
- 每个块盒垂直方向上的 auto 值。
- height: auto 时,块盒的高度由内容决定。
- margin: auto 时,块盒的垂直方向上的 auto 值会自动获得 0。
- 百分比取值
- padding 、margin 、width 的百分比取值,都是相对于包含块的宽度。
- 高度的百分比需要考虑包含块的高度是否取决于子元素的高度。
- 如果父元素的高度取决于子元素的高度,比如父元素的高度是 auto 或者没有设置高度,那么子元素的高度百分比是无效的。
- 如果父元素的高度不取决于子元素的高度,比如父元素的高度是固定的,那么子元素的高度百分比是有效的。
提示
父元素的 width 是 600px,height 是 1000px。子元素的 margin-top 是 50%,那么子元素的 margin-top 的值是 300px,而不是 500px。
- 常规流里块盒的边距合并。
- 相邻垂直外边距会取最大值合并。
- 父子元素的垂直外边距合并
.parent {
height: 300px;
margin-top: 30px;
}
.child {
height: 100px;
margin-top: 30px;
}
/*子元素紧贴着父元素父子元素的垂直外边距合并为30px*/
.parent {
height: 300px;
margin-top: 30px;
padding-top: 30px;
}
.child {
height: 100px;
/* margin-top: 30px; */
}
浮动
应用场景
- 文字环绕
- 横向排列
基本特点
- 修改 float 属性值为 left,元素向上向左浮动,修改为 right,元素向上向右浮动。
- float 的默认值是 none,不浮动。
- 浮动元素必定为块盒。
- 浮动元素的包含块是父元素的内容盒。
盒子尺寸
- 常规流 width 为 auto 时,吸收包含块剩余空间。浮动元素 width 为 auto 时,宽度由内容决定。
- 浮动元素和常规流元素的高度为 auto 时都是由内容决定。
- 常规流 margin 为 auto 时,在 width 吸收完空间之后,吸收剩余空间。浮动元素 margin 为 auto 时,会自动变为 0。
- 边框、内边距、百分比设置,和常规流一样——都是相对于包含块的宽度。
盒子排列
- 左浮动的盒子靠上靠左排列。
- 右浮动的盒子靠上靠右排列。
- 浮动盒子会避开常规流块盒。
- 常规流块盒在排列时,会忽视浮动盒子。
- 行盒在排列时,会避开浮动盒子。
- 不会发生外边距合并。
- 浮动盒子的顶边不得高于上一个盒子的顶边。
- 如果剩余空间不足以放下浮动盒子,则该盒子向下移动,直到空间足够进行浮动。
Q : 图片设置浮动达到的文字环绕效果,根据以上条件 p 元素是块盒,为什么里面的文字会环绕而不是被覆盖?
A : 浏览器对于直接被块盒包裹的文字会生成一个行盒,该行盒叫匿名行盒。行盒会避开浮动盒子,所以文字会环绕浮动盒子。但是 p 元素的空间占据是不会被浮动盒子避开的,所以 p 元素空间会被浮动盒子覆盖。
高度坍塌
高度坍塌的根源:常规流盒子高度自动计算,不会考虑内部的浮动盒子。解决高度坍塌的方法:清除浮动。
clear 属性
- 默认值是 none,不清除浮动。
- left,清除左浮动。该元素必须在左浮动元素的下方。
- right,清除右浮动。该元素必须在右浮动元素的下方。
- both,清除左右浮动。
- inherit,继承父元素的 clear 属性值。
开发中,可以在浮动元素后面添加一个空元素,设置 clear 属性值为 both,清除浮动。
/* Method 1 在浮动元素后面添加一个div并设置样式 */
.clearfix {
clear: both;
}
/* Method 2 使用伪元素清除浮动 */
.clearfix::after {
content: "";
display: block;
clear: both;
}
定位
- 手动控制元素在包含块中的精确位置。
- 默认值:static,可以按照不定位理解。
- 一个元素只要 position 的值不是 static,认为该元素是定位元素。
- 定位元素除了 relative 以外,都是脱离常规流的。
- 一个脱离了文档流的元素:
- 文档流中的元素摆放会忽略该元素。
- 文档流中元素计算自然高度会忽略该元素。
相对定位
- 相对定位的元素不会脱离文档流,只是相对于原来的位置进行偏移。
- 相对定位的元素会在常规流中占据原来的位置,但是在视觉上会发生偏移。也就是说,偏移的盒子不占据其他盒子空间,不影响其他盒子的排列。
绝对定位
- 宽高为 auto,由内容决定。
- 包含块变化:找祖先元素中第一个定位元素,该元素的填充盒为包含块。如果没有定位元素,则包含块是整个网页(初始化包含块)。
固定定位
- 其他情况和绝对定位一样,但是包含块是视口(浏览器的可视窗口)。
定位下的居中
某个方向居中:
- 定宽或定高;
- 水平或垂直距离为 0;
- 水平或垂直 margin: auto;
绝对定位或固定定位的元素,margin 吸收剩余空间
多个定位元素的重叠
详细的内容需要参考 层叠上下文。
简单来说,可以设置 z-index 属性来控制定位元素在 z 轴上的堆叠顺序。z-index 的值越大,元素在 z 轴上的位置越靠上,元素越靠近用户。
警告
- z-index 只能应用于定位元素,即 position 属性值不是 static 的元素。
- z-index 的值可以是负数,但是常规流元素和浮动元素会覆盖它。
补充
- 绝对定位元素一定是块盒。
- 绝对定位和固定定位的元素一定不是浮动元素。
- 不存在外边距合并现象。