CSS布局(一)

334 阅读8分钟

前言

上一篇文章介绍了CSS盒模型相关的内容。上一篇文章提到“web 页面本质上就是一堆 ‘盒子’ 的组合”,那么这一篇文章就来跟大家分享一下CSS中抽象的盒子是怎样排列在web页面中的。也就是CSS是如何进行页面布局的。如图所示,CSS的布局主要分为正常流布局、浮动布局、定位布局、弹性盒子布局、网格布局和多列布局六种方式。   布局.png 在介绍这六种布局之前,需要先了解和CSS布局有关的几个概念。

  • 层叠上下文(Stacking Context)
  • 层叠水平(Stacking Level)
  • 层叠顺序(Stacking Order)
  • 格式化上下文(Formatting Context)

层叠相关

在 CSS 中,一个非常重要的特征就是层叠。层叠有两层含义,一层是属性上的层叠,一层是空间上的层叠。属性上的层叠定义了如何合并来自多个源的属性值的算法,而空间上的层叠是跟 web 页面中的元素排列相关的。在这里,我们重点关注的是空间上的层叠。
虽然我们在终端设备上看到的 web 页面都是二维平面的结构,但实际上在 CSS 的抽象中,所有的元素都是存在于一个三维空间中,除了 x 轴和 y 轴,还有一个垂直于终端显示屏幕的 z 轴。其中,以屏幕的左上角为坐标原点;屏幕水平方向为 x 轴,并且以右侧为正方向;屏幕的竖直方向为 y 轴,并且以向下为正方向;垂直于屏幕,并且指向观察者的方向为 z 轴。按上述规则建立的直角坐标系如图所示。
三维坐标.png
从这个坐标系的建立很容易想到,x轴和y轴构成了一个二维的平面,这个平面显然就是web页面所在的平面。但是,垂直于web页面所在平面的z轴呢?它代表的含义是什么?
由这个问题,我们引出了第一个概念:层叠上下文

层叠上下文(Stacking Context)

层叠上下文(Stacking Context),是指将HTML元素沿着其相对于用户的一条虚构的z轴排开。 显然,这个说法是相当抽象的。不瞒大家说哈,我第一次看到这么抽象的文字的时候,也是一头雾水。然后呢,就开始翻各位大佬的博客,发现对于层叠上下文这个概念的理解,不同的老师有不同的说法。其中,张鑫旭老师对于层叠上下文的描述特别有意思,也很容易理解: 把[层叠上下文]理解为当官:网页中有很多很多的元素,我们可以看成是真实世界的芸芸众生。真实世界里,我们大多数人是普通老百姓们,还有一部分人是做官的官员。OK,这里的官员就可以理解为网页中的层叠上下文元素。 把它翻译成我们常见的术语就是,网页中的元素有一个层次的概念。其中大部分元素都处在相对的“底层”,是和用户的距离相对较远的;然而有一部分特殊的元素,他在页面中的位置就相对于大部分元素离用户更近,在网页中排列的更加前面。因此,这里把大部分元素比作老百姓(离皇帝比较远);那些特殊的元素就好比做了官,离皇帝(用户)更近了。
说了大佬的理解,我再来说一下我自己的理解。层叠上下文,就类似于PhotoShop里面的图层。大部分元素在相对下面一点的图层,而由于某些原因,我们单独把部分图形单独新建了一个图层(脱离了原本的显示图层),新图层的摆放位置在就图层的前面。

层叠水平(Stacking Level)

层叠水平决定了同一个层叠上下文元素在z轴的顺序。如果说层叠上下文是 html 元素的层叠排列,那么层叠水平就是决定元素究竟该排到什么地方的参数。什么意思呢?根据的把上面层叠上下文比作老百姓当官的例子,那么层叠水平就可以比作当官的职级,一品,二品。显然品级越高,离得皇帝越近。层叠水平越高,那么元素在z轴上的位置就相对靠前,元素离观察者也就越近。
看起来似乎层叠水平和 z-index 属性挺像的。

  • z-index :设定了一个定位元素极其后代元素或flex元素的z-order。当元素之间重叠的时候,z-index较大的元素会覆盖较小的元素在上层显示。 然而,层叠水平和 z-index 并不是一个东西,他俩适用的范围是不一样的。层叠等级是相对于页面的所有元素来说的,而z-index则是相对于脱离了正常文档流的定位元素和flexbox元素而言的。他们两个不能够混为一谈。

层叠顺序(Stacking Order)

层叠相关的最后一个概念就是层叠顺序了。他表示的是元素在看不见的 z 轴上面的排列顺序。如图所示,元素盒子在层叠顺序上下文的顺序依次是:

  • 背景和边框(background/border)
  • 负z-index值
  • 块级盒子
  • 浮动盒子
  • 行内盒子(inline-box)
  • z-index值为0的元素
  • 正z-index值 层叠顺序示意图.png

格式化上下文(Formatting Context)

在文章的最后,我们来唠一唠 CSS 中的格式化上下文相关的内容。格式化上下文是W3C CSS2.1规范中的一个概念,表示页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的相互作用。 说实话,这一大段话看得我头晕。读完了也不是特别明白格式化上下文到底是个什么玩意儿。后来,查阅相关的文档,发现格式化上下文包含块格式化上下文(Block Formatting Context, BFC)和行内格式化上下文(Inline Formatting Context,IFC)两种, 他们分别对应CSS和模型的块盒子和内联盒子。

  • 在块格式化上下文中,盒在垂直方向一个接一个地放置,从包含块的顶部开始。兄弟盒之间的垂直距离有 margin 属性决定。同一个快格式化上下文中的相邻块盒子之间的垂直外边距会合并。
  • 在行内格式化上下文中,盒是从包含块的顶部开始一个挨一个水平放置的。这些盒之间的水平外边距,边框和内边距都有效。盒可能会以不同的方式垂直对齐:以它们的底部或者顶部对齐,或者以它们里面的文本的基线对齐。包含来自同一行的盒的矩形区域叫做行框。 从这些规范中,可以看出格式化上下文就是指正常流文本的排列方式。在正常文档流中,不是块盒子就是行内盒子。因此,在页面中渲染只需要按照对应的盒子的渲染规范进行渲染即可。说白了,其实就是html元素如何在web页面中进行排列而已。  

BFC如何触发

关于这个话题,大漠老师的整理就已经非常详细了,我这里就做个搬运工:

  1. 根元素或包含根元素的元素
  2. 浮动元素(元素的 float 不是 none)
  3. 绝对定位元素(元素的 position 为 absolute 或 fixed)
  4. 行内块元素(元素的 display 为 inline-block)
  5. 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)
  6. 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
  7. 匿名表格单元格元素(元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table)
  8. overflow 值不为 visible 的块元素
  9. display 值为 flow-root 的元素
  10. contain 值为 layout、content或 strict 的元素
  11. 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  12. 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  13. 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
  14. column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。

关于BFC,有一点儿想说的话

BFC这个概念是比较抽象的。说实话,我自己都只是理解个大概。要深究的话还是要多看一看大佬们写的博客,以及深入研究相关的技术文档。我们都还只是在路上。