视觉格式化模型(visual formatting model) CSS布局

前面我们已经学习了盒模型(box model),知道了元素会被渲染成一个个盒子。那么这些盒子在屏幕上的位置又是怎么放置的呢?这就是我们现在要学习的——CSS 视觉格式化模型(visual formatting model)。视觉格式化模型是 CSS 布局的一个基础理论体系,需要你有一定的 CSS 功底,所以一时半会是很难掌握的,但是只要你一掌握,对于 CSS 布局就会豁然开朗。(建议整个 CSS 布局学完后再重新细读深入下。)

盒子的位置摆放

默认情况下,盒子按照元素在 HTML 中的先后位置从左至右自上而下一个接着一个排列摆放。如下图:

在图中我们可以看到,有些元素的盒子被渲染为完整的一行,如h1、p、div;而有些元素的盒子则被渲染为水平排列,直到该行被占满然后换行,如span、a、strong。

这是因为不同的盒子使用的是不同的格式化上下文(formatting context)来布局,每个格式化上下文都拥有一套不同的渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。(就如我们参加结婚喜宴一样,有父母长辈席,好友席,同事席,甚至前男/女朋友席等,不同的身份坐到对应位置即可。)

格式化上下文(formatting context)

我们常见的两个格式化上下文分别为:块格式化上下文(block formatting context 简称 BFC)和行内格式化上下文(inline formatting context 简称 IFC)

BFC

块级盒(block-level boxes)

当元素的 CSS 属性 display 的计算值为 block,list-item,table,flex 或 grid 时,它是块级元素。视觉上呈现为块,竖直排列。典型的如 <div> 元素,<p> 元素等都是块级元素。

每个块级元素至少生成一个块级盒,称为主要块级盒(principal block-level box)。一些元素,比如<li>,生成额外的盒来放置项目符号,不过多数元素只生成一个主要块级盒。

块级盒参与 BFC,被渲染为完整的一个新行。

渲染规则

默认根元素(html 元素)会创建一个 BFC,其块级盒子元素将会按照如下规则进行渲染:

  • 块级盒会在垂直方向,一个接一个地放置,每个盒子水平占满整个容器空间
  • 块级盒的垂直方向距离由上下 margin 决定,同属于一个 BFC 中的两个或以上块级盒的相接的 margin 会发生重叠
  • BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此
  • 计算 BFC 的高度时,浮动元素也参与计算

除此之外,还有其他方法可以创建一个新的 BFC,具体可参看:块格式化上下文。除此之外,flexbox 布局和 grids 布局中的 item 都会创建一个新的 BFC。

具体渲染规则及效果可参看:块格式化上下文

更多关于 BFC 相关内容可参看:

IFC

行内级盒(inline-level boxes)

当元素的 CSS 属性 display 的计算值为 inline,inline-block,inline-table,inline-flex 或 inline-grid 时,它是行内级元素。视觉上它将内容与其它行内级元素排列为一行,直到该行被占满然后换行。典型的如段落内容,文本或图片,都是行内级元素。

注:由于目前几乎所有资料都将行内元素当做行内元素,所以前面的课程我们也遵循这个美丽的错误。严格来说,行内元素不包括 inline-block 的,行内级元素才包括。我们要理解其中的区别,知晓这个美丽的错误。

行内级元素生成行内级盒,参与行内格式化上下文(inline formatting context),被渲染为水平排列, 直到当行被占满然后换行。

行内级盒分为行内盒(inline boxes)和原子行内级盒(atomic inline-level boxes)。前者由非置换元素且 display 值为 inline 的元素生成;后者由行内级置换元素,或 display 值为 inline-block, inline-table, inline-flex, inline-grid 的元素生成。

每一行排列的行内级盒都可以看做由一个匿名的行盒包裹,如下图(使用了两种灰色背景色来模拟):

渲染规则

当块容器盒(block container box)不包括任何块级盒(block-level boxes)时,就会创建一个行内格式化上下文(IFC)。(一般来说一个块级盒也是一个块容器盒,具体可参看: Block-level elements and block boxes

IFC 中的行内级盒将会按照如下规则进行渲染(规则有点多,大概主要点就是行盒,折行机制,水平对齐方式,垂直高度及垂直对齐方式):

  • 盒子一个接一个地水平摆放,当容器宽度不够时就会换行
  • 在水平方向上,这些盒的外边距、边框、内边距所占用的空间都会被计算,但行内盒的垂直的border,padding 与 margin 都不会撑开行盒的高度
  • 在垂直方向上,这些盒可能会以不同形式来对齐,可通过 vertical-align 来设置,默认对齐为 baseline
  • 每一行将生成一个行盒(line box),包括该行所有的盒子,行盒的宽度是由包含块和存在的浮动来决定
  • 行盒一般左右边都贴紧其包含块,但是会因为浮动盒(float 元素)的存在而发生变化。浮动盒会位于包含块边缘与行盒边缘之间,这样行盒的可用宽度就小于包含块的宽度
  • 当所有盒的总宽度小于行盒的宽度,那么行盒中的水平方向排版由 text-align 属性来决定
  • 当所有盒的总宽度超过一个行盒时,就会形成多个行盒,多个行盒相互之间垂直方向不能分离,不能重叠
  • 当一个行内盒超过行盒的宽度时,它会被分割成多个盒,这些盒被分布在多个行盒里。如果一个行内盒不能被分割(比如只包含单个字符,或word-breaking机制被禁用,或该行内框受white-space属性值为nowrap或pre的影响),那么这个行内盒将溢出这个行盒
  • 当一个行内盒发生分割时,分割处的 margins, borders 和 padding 不会有任何视觉效果(或者其他任何分裂,只要是有多个行盒)
  • 行盒的高度由内部元素中实际高度最高的元素计算出来。每个行盒的高度由于内容不一样,所以高度也可能不一样
  • 在一个行盒中,当他包含的内部容器的高度小于行盒的高度的时候,内部容器的垂直位置可由自己的 vertical-align 属性来确定

注:在 IFC 的环境中,是不能存在块级元素的,如果将块级元素插入到 IFC 中,那么此 IFC 将会被破坏掉变成 BFC,而块级元素前的元素或文本和块级元素后的元素或文本将会各自自动产生一个匿名块盒其包围。

具体行盒高度及垂直对齐方式渲染效果可参看:

更多关于 IFC 相关内容可参看:

其他格式化上下文

除此之外,还有一些其他不同类型的盒子,如下:

  • 表格布局:可以创建一个表格包裹盒(table wrapper box),包括了表格盒(table box)及任何标题盒(caption boxes)。
  • 多列布局:可以在容器盒与内容之间创建列盒(column boxes)
  • 弹性布局:将会创建一个弹性容器盒(flex container box)
  • 网格布局:将会创建一个网格容器盒(grid container box)

而这些盒子也将采用不用的格式化上下文来渲染,如 table formatting context(table 布局)、flex formatting context(flexbox 布局)、grid formatting context(grid 布局)。

更多关于盒子的介绍可参看:

定位方案

上面我们所讨论的其实都是常规流(normal flow)中盒子的摆放。但实际上我们有三种定位方案,分别为:

  • 常规流(normal flow):盒一个接一个排列,不同的盒子采用不同的格式化上下文渲染。
  • 浮动(float):盒将从常规流里提出来,放在当前盒的旁边。
  • 绝对定位(absolute positioning):盒将脱离常规流,其坐标是绝对的(通过 top / bottom / left / right 来设置)。

常规流(normal flow)

默认盒的定位方案就是常规流,但是如果触发了以下任何一个条件,将不会使用常规流:

  • position 的值非 static 或 relative
  • float 的值非 none

在常规流中,不同的盒子将采用不同的格式化上下文渲染,也就是上面所讲的部分。

浮动(float)

对于浮动定位方案, 盒称为浮动盒(floating boxes)。它位于当前行的开头或末尾。这导致常规流环绕在它的周边,除非设置 clear 属性。

要使用浮动定位方案,元素 CSS 属性 position 必须为 static 或 relative,然后 float 不为 none 。如果 float 设为 left, 则浮动定位到当前位置的开始位置,如果设为 right, 则浮动定位到当前位置的最后位置。

具体介绍可学习下面章节:元素浮动——float。

绝对定位(absolute position)

如果元素的属性 position 不是 static 或 relative, 那它就是绝对定位元素。

对于绝对定位方案,盒从常规流中被移除,不影响常规流的布局。 它的定位相对于它的包含块,定位坐标可通过属性 top、bottom、left、right 来设置 。

固定定位元素(fixed positioned element)也是绝对定位元素,它的包含块是视口。当页面滚动时它固定在屏幕上,因为视口没有移动。

具体介绍可学习下面章节:元素定位——position。

参考资料

猜你喜欢

转载自blog.csdn.net/Abudula__/article/details/81987029