定位和层叠上下文
布局
块级上下文
层叠上下文
布局与包含块
一个元素的尺寸和位置经常受其**包含块(containing block)**的影响。大多数情况下,包含块就是这个元素最近的祖先块元素的内容区,但也不是总是这样。在本文中,我们来过一遍确定包含块的所有因素。
当一个客户端代理(比如说浏览器)展示一个文档的时候,对于每一个元素,它都产生了一个盒子。每一个盒子都被划分为四个区域:
- 内容区
- 内边距区
- 边框区
- 外边距区
许多开发者认为一个元素的包含块就是他的父元素的内容区。但事实并非如此。接下来让我们来看看,确定元素包含块的因素都有哪些。
包含块的影响
在学习如何确定元素包含块之前,先了解一下它的重要性。
元素的尺寸及位置,常常会受它的包含块所影响。对于一些属性,例如 width
, height
, padding
, margin
,绝对定位元素的偏移值 (比如 position
被设置为 absolute
或 fixed
),当我们对其赋予百分比值时,这些值的计算值,就是通过元素的包含块计算得来。
确定包含块
确定一个元素的包含块的过程完全依赖于这个元素的 position
属性:
- 如果
position
属性为static
、**relative
** 或sticky
,包含块可能由它的最近的祖先块元素(比如说inline-block
,block
或list-item
元素)的内容区的边缘组成,也可能会建立格式化上下文(比如说a table container
,flex container
,grid container
, 或者是the block container
自身)。 - 如果
position
属性为absolute
,包含块就是由它的最近的position
的值不是static
(也就是值为fixed
,absolute
,relative
或sticky
)的祖先元素的内边距区的边缘组成。 - 如果
position
属性是 **fixed
**,在连续媒体的情况下(continuous media
)包含块是 viewport ,在分页媒体(paged media)下的情况下包含块是分页区域(page area
)。 - 如果 position 属性是**
absolute
或fixed
**,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:transform
或perspective
的值不是none
will-change
的值是transform
或perspective
filter
的值不是none
或will-change
的值是filter
(只在Firefox
下生效).contain
的值是paint
(例如:contain: paint;
)
注意: 根元素(
<html>
)所在的包含块是一个被称为初始包含块的矩形。他的尺寸是视口 viewport (for continuous media) 或分页媒体 page media (for paged media).
根据包含块计算百分比值
如上所述,如果某些属性被赋予一个百分值的话,它的计算值是由这个元素的包含块计算而来的。这些属性包括盒模型属性和偏移属性:
- 要计算
height
top
及bottom
中的百分值,是通过包含块的height
的值。如果包含块的height
值会根据它的内容变化,而且包含块的position
属性的值被赋予relative
或static
,那么,这些值的计算值为 auto。 - 要计算
width
,left
,right
,padding
,margin
这些属性由包含块的width
属性的值来计算它的百分值。
示例:
1 | <body> |
例一:position:static
这个示例中,P
标签设置为静态定位,所以它的包含块为 <section>
,因为距离最近的父节点即是她的包含块。
1 | body { |
例二:position:static
在这个示例中,P
标签的包含块为 <body>
元素,因为 <section>
不再是一个块容器,所以并没有形成一个格式上下文。
1 | body { |
例三:position:absolute
这个示例中,P
元素的包含块是 <section
>,因为 <section>
的 position
为 absolute
。P
元素的百分值会受其包含块的 padding
所影响。不过,如果包含块的 box-sizing
值设置为 border-box
,就没有这个问题。
1 | body { |
例四:position:fixed
这个示例中,P
元素的 position
为 fixed
,所以它的包含块就是初始包含块(在屏幕上,也就是 viewport)。这样的话,P 元素的尺寸大小,将会随着浏览器窗框大小的变化,而变化。
1 | body { |
例五:position:absolute
这个示例中,P
元素的 position
为 absolute
,所以它的包含块是 <section>
,也就是距离它最近的一个 transform
值不为 none 的父元素。
1 | body { |