Skip to content

视觉格式化模型

之前介绍的 CSS 属性值的计算是 CSS 的第一个重点,另外一个就是本文的主题——视觉格式化模型(Visual Formatting Model)。

什么是视觉格式化模型?

盒子模型规定了单个盒子的规则,而视觉格式化模型则规定了如何将这些盒子放置在页面上。视觉格式化模型,你也可以将其理解为布局规则:视觉格式化模型大体将页面中盒子的排列分为了三种方式:常规流、浮动和绝对定位。

常规流布局

常规流,也可以叫做文档流普通文档流或者常规文档流,是浏览器默认的布局方式,它规定了盒子在页面中的排列方式。总体规则是——块盒独占一行,行盒水平依次排列。

包含块(Containing Block)

每个盒子都有它的包含块,包含块决定了盒子的排列区域。绝大部分情况下,盒子的包含块,就是它父元素的内容盒。

块盒

  1. 每个块盒的总宽度(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; 实现水平居中。
  2. 每个块盒垂直方向上的 auto 值。
    • height: auto 时,块盒的高度由内容决定。
    • margin: auto 时,块盒的垂直方向上的 auto 值会自动获得 0。
  3. 百分比取值
    • padding 、margin 、width 的百分比取值,都是相对于包含块宽度
    • 高度的百分比需要考虑包含块的高度是否取决于子元素的高度
      • 如果父元素的高度取决于子元素的高度,比如父元素的高度是 auto 或者没有设置高度,那么子元素的高度百分比是无效的。
      • 如果父元素的高度不取决于子元素的高度,比如父元素的高度是固定的,那么子元素的高度百分比是有效的。

提示

父元素的 width 是 600px,height 是 1000px。子元素的 margin-top 是 50%,那么子元素的 margin-top 的值是 300px,而不是 500px。

  1. 常规流里块盒的边距合并。
  • 相邻垂直外边距会取最大值合并。
  • 父子元素的垂直外边距合并
CSS
.parent {
    height: 300px;
    margin-top: 30px;
}
.child {
    height: 100px;
    margin-top: 30px;
}
/*子元素紧贴着父元素父子元素的垂直外边距合并为30px*/
CSS
.parent {
    height: 300px;
    margin-top: 30px;
    padding-top: 30px;
}
.child {
    height: 100px;
    /* margin-top: 30px; */
}

浮动

应用场景

  1. 文字环绕
  2. 横向排列

基本特点

  1. 修改 float 属性值为 left,元素向上向左浮动,修改为 right,元素向上向右浮动。
  2. float 的默认值是 none,不浮动。
  3. 浮动元素必定为块盒。
  4. 浮动元素的包含块是父元素的内容盒。

盒子尺寸

  1. 常规流 width 为 auto 时,吸收包含块剩余空间。浮动元素 width 为 auto 时,宽度由内容决定。
  2. 浮动元素和常规流元素的高度为 auto 时都是由内容决定。
  3. 常规流 margin 为 auto 时,在 width 吸收完空间之后,吸收剩余空间。浮动元素 margin 为 auto 时,会自动变为 0。
  4. 边框、内边距、百分比设置,和常规流一样——都是相对于包含块的宽度。

盒子排列

  1. 左浮动的盒子靠上靠左排列。
  2. 右浮动的盒子靠上靠右排列。
  3. 浮动盒子会避开常规流块盒。
  4. 常规流块盒在排列时,会忽视浮动盒子。
  5. 行盒在排列时,会避开浮动盒子。
  6. 不会发生外边距合并。
  7. 浮动盒子的顶边不得高于上一个盒子的顶边。
  8. 如果剩余空间不足以放下浮动盒子,则该盒子向下移动,直到空间足够进行浮动。

Q : 图片设置浮动达到的文字环绕效果,根据以上条件 p 元素是块盒,为什么里面的文字会环绕而不是被覆盖?

A : 浏览器对于直接被块盒包裹的文字会生成一个行盒,该行盒叫匿名行盒。行盒会避开浮动盒子,所以文字会环绕浮动盒子。但是 p 元素的空间占据是不会被浮动盒子避开的,所以 p 元素空间会被浮动盒子覆盖。

高度坍塌

高度坍塌的根源:常规流盒子高度自动计算,不会考虑内部的浮动盒子。解决高度坍塌的方法:清除浮动

clear 属性

  • 默认值是 none,不清除浮动。
  • left,清除左浮动。该元素必须在左浮动元素的下方。
  • right,清除右浮动。该元素必须在右浮动元素的下方。
  • both,清除左右浮动。
  • inherit,继承父元素的 clear 属性值。

开发中,可以在浮动元素后面添加一个空元素,设置 clear 属性值为 both,清除浮动。

CSS
/* Method 1 在浮动元素后面添加一个div并设置样式 */
.clearfix {
    clear: both;
}

/* Method 2 使用伪元素清除浮动 */
.clearfix::after {
    content: "";
    display: block;
    clear: both;
}

定位

  • 手动控制元素在包含块中的精确位置。
  • 默认值:static,可以按照不定位理解。
  • 一个元素只要 position 的值不是 static,认为该元素是定位元素。
  • 定位元素除了 relative 以外,都是脱离常规流的。
  • 一个脱离了文档流的元素:
    • 文档流中的元素摆放会忽略该元素。
    • 文档流中元素计算自然高度会忽略该元素。

相对定位

  • 相对定位的元素不会脱离文档流,只是相对于原来的位置进行偏移。
  • 相对定位的元素会在常规流中占据原来的位置,但是在视觉上会发生偏移。也就是说,偏移的盒子不占据其他盒子空间,不影响其他盒子的排列。

绝对定位

  • 宽高为 auto,由内容决定。
  • 包含块变化:找祖先元素中第一个定位元素,该元素的填充盒为包含块。如果没有定位元素,则包含块是整个网页(初始化包含块)。

固定定位

  • 其他情况和绝对定位一样,但是包含块是视口(浏览器的可视窗口)。

定位下的居中

某个方向居中:

  1. 定宽或定高;
  2. 水平或垂直距离为 0;
  3. 水平或垂直 margin: auto;

绝对定位或固定定位的元素,margin 吸收剩余空间

多个定位元素的重叠

详细的内容需要参考 层叠上下文

简单来说,可以设置 z-index 属性来控制定位元素在 z 轴上的堆叠顺序。z-index 的值越大,元素在 z 轴上的位置越靠上,元素越靠近用户。

警告

  1. z-index 只能应用于定位元素,即 position 属性值不是 static 的元素。
  2. z-index 的值可以是负数,但是常规流元素和浮动元素会覆盖它。

补充

  • 绝对定位元素一定是块盒。
  • 绝对定位和固定定位的元素一定不是浮动元素。
  • 不存在外边距合并现象。