理解 CSS 中的定位
CSS 布局不仅仅是一个单独的 CSS 属性或模块。网络上的所有内容都是一个盒子。这些盒子的布局由以下规则决定:
- 盒子尺寸和类型
- 定位方案(正常流、浮动和绝对定位)
- 文档树中元素之间的关系
- 外部信息(例如,视口大小、图像的固有尺寸等)
仅从这些信息中,我们就可以挑选出以下 CSS 模块(包括草稿状态的模块):
- CSS 显示模块级别 3 (CR)
- CSS 盒子模型模块级别 3(WD)
- CSS 定位布局模块级别 3(WD)
- CSS2.1 第 9.5 节 浮动(REC)
我想说的是,如果你想完全掌握用 CSS 构建任何布局的技巧,我建议你了解这些不同的 CSS 模块以及它们之间的交互方式。这确实对我帮助很大。
平心而论,我在 2018 年准备 CSS Day 演讲时确实深入研究过这些内容,当时差不多有 45 分钟都在讨论盒子。所有演讲详情都可以在 Notist 上找到。
定位方案
框生成后,其布局方式取决于其所属的定位方案:
- 正常流量
- 浮点数
- 绝对定位
正常布局是默认布局,其中框一个接一个地排列,不会重叠或侵占彼此的空间。所有框也都位于相同的堆叠上下文中。
浮动的框被视为超出流线范围。当一个框浮动时,它首先会按照正常流线进行布局,然后脱离流线,并尽可能地向左或向右移动(取决于浮动值)。
内容将沿着浮动框的侧面流动。但浮动框仍然与非浮动框位于相同的堆叠上下文中。
绝对定位的框完全脱离了正常流,并且其位置是根据其包含块分配的。
用于计算页面上框位置的定位算法由position
和float
属性决定。我会尽力以一种通俗易懂的方式解释这一点。但首先,让我们分别看一下它们。
该position
物业
此属性有多个值,是sticky
在定位布局模块的第 3 级中添加的,尽管它仍处于工作草案状态,但目前大多数主流浏览器都支持它。
position: static
任何框的默认位置值。这会导致框按正常流向布局,并且 、 和 的属性top
(也bottom
称为框偏移值)将不起作用,因为该框被视为未定位。left
right
position: relative
对框应用使其position
定位,现在、和值将产生一些效果。relative
top
bottom
left
right
该框最初将按照正常流程进行布局,然后根据前面提到的框偏移值,相对于其正常位置进行偏移。
如果此定位框旁边还有其他非定位框,即使存在偏移值,它们也不会受到影响。这意味着可能存在重叠的可能性。
此外,如果偏移导致框溢出,可能会导致滚动,从而影响布局。当一个框变为相对定位后,它将成为其子项的新包含块。
position: sticky
粘性定位框的工作方式与相对定位框类似。区别在于,粘性定位框的偏移量是计算到最近的具有滚动框的祖先框的偏移量,如果不存在这样的祖先框,则计算到视口的偏移量。
不久前,我的朋友勇军问了一个问题:为什么position: sticky
只在盒子上涂抹不足以达到粘性效果?盒子没有任何偏移,所以它的行为就像正常流动一样,因为它确实如此。
只有当偏移值不是 时,auto
框的行为才会开始不同于相对定位的框。规范中的措辞对我来说有点难以理解,但我的理解是,当你应用框偏移值时,粘性框和它的包含框之间会有一个交集。
这个交点被称为粘性约束矩形,用于包含粘性框的位置。规范中使用了“投射在上方/下方/外部”这一术语,但我不确定我的理解是否与规范作者的意图一致。
我所知道的是,当您定义偏移值时,偏移量永远不会将粘性框推到其包含块之外,但是粘性框可以在页面滚动时在包含块内自由移动,因此感觉它被固定在相关边缘。
position: absolute
绝对定位的框相对于其包含块有明确的偏移,并且该框根本不参与正常的布局流。其后面的兄弟元素在更大的布局中不会感知到它的存在。
绝对定位框的内容不会围绕任何其他框流动,并且可能与其他框重叠,并且根据框的堆叠级别,内容可能会因重叠而被遮挡。
position: fixed
固定定位框的行为与绝对定位框类似。关键区别在于,固定定位框的包含块始终是视口。
框偏移值
传统上,大多数开发人员熟悉的框偏移值是top
、和。而且,我认为,说大多数西方bottom
开发人员在编写除水平自上而下之外的模式时不会再三考虑,这并非一概而论。left
right
但是,当你使用从右到左的书写模式,或者垂直书写时,这些物理值(例如 、top
和bottom
)left
就right
变得不那么有意义了。例如,内容的顶部可能不是浏览器视口的物理顶部。
作为一个从小就接触到与西方默认书写系统不同的书写系统的人,这对我来说并不难理解,但对于许多西方人来说可能并非如此。
这就是为什么当我们行业中有影响力的人士开始谈论这些鲜为人知的网络开发方面,特别是在国际化方面时,我会感到很感激,因为他们的影响力更广,可以帮助一些被认为不为人知的东西变得更加主流。
逻辑框偏移值
由于该规范仍处于编辑草案状态,语法未来可能会有所变更。即使现在,当前浏览器的实现也与规范中的内容有所不同,因此请务必仔细查阅MDN:CSS 逻辑属性和值,了解最新的语法。
盒子的物理边和逻辑边的书写方向矩阵及其对应值如下(截至撰写本文时,该表已从规范中删除):
容器的逻辑顶部使用inset-block-start
,而容器的逻辑底部使用inset-block-end
。容器的逻辑左侧使用inset-inline-start
,而容器的逻辑右侧使用inset-inline-end
。
用图表(或者如果你的浏览器支持的话,可以参考实时代码)可能更容易理解。以下是针对horizontal-tb
:
以下是针对的vertical-rl
:
以下是针对的vertical-lr
:
总结
我建议在完整的浏览器窗口中打开这个 CodePen,并尝试使用示例和 CSS 值来了解一切是如何组合在一起的(或者您可以在嵌入中选择 0.5x 选项)。
有很多实用的资源介绍 CSS 定位,所以如果我的解释对你没用,可以直接尝试其他人的文章或规范。从长远来看,自己去弄清楚 CSS 布局的这个重要方面绝对值得付出努力。
- CSS 定位布局模块 3 级工作草案
- MDN:定位
- CSS 位置粘性 - 它如何真正发挥作用!
- 关于 CSS 定位类型你可能不知道的 5 件事
- 高级定位(文章较旧,因此
sticky
此处不再赘述) - CSS 定位 101(文章较旧,因此不在
sticky
此处)