引言
fixed 元素一定是相对视口定位的吗?不一定。举一个例子,如果父元素 transform: scale(1)
了,子元素是 position: fixed
。会发现,子元素是相对这个父元素定位的。
包含块
其实上面这个问题,牵扯到了包含块(containing block)的概念。那么,包含块是用来干嘛的呢?
简单说来,一个元素的尺寸(比如 width
、height
、padding
啥的)或者定位(比如定位元素的 left
、top
属性啥的)通常都是参照它的包含块计算的。可以这么说,在我们日常的 CSS 的使用中,凡是涉及到与布局相关的代码,几乎都在与包含块打交道。
学习包含块之前,可以先记住以下两点:
- 一个元素的包含块通常是该元素的祖先元素。
- 一个元素的包含块为何,只与这个元素的
position
属性值有关。
好了,下面就开始学习了。
元素默认的包含块
position
属性默认值是 static
,或者我们随便写个元素,使用 getComputedStyle
也能知道。
<div id="test"></div>
<script>getComputedStyle(test).position // "static"</script>
那么对于 position:static
元素,它的包含块是啥呢?下面给出了范围:
- 最近的祖先元素,且是一个块元素(block container,比如
display
值为inline-block
、block
、list-item
的这些元素)。或, - 最近的祖先元素,且能创建 BFC 上文下环境 的元素(比如
<table>
元素,Flex 容器,Grid 容器,或是块元素本身)。还有, position: static
元素是参照上述祖先元素的内容区域(content box)计算尺寸或定位的。
这里有两个地方,需要解释一下:
一、第二条括号里的内容,“块状元素本身”,是什么意思呢?
这是说,有些块元素本身就具备创建 BFC 上文下环境能力。比如,inline-block
元素,它既是块元素也能创建 BFC 上下文。
二、相对于 content box 区域计算又是什么意思?
举一个例子:
<div class="parent">
<div class="child"></div>
</div>
<style>
.parent {
width: 400px; height: 200px;
padding: 50px;
}
.child {
width: 50%; height: 50%;
}
</style>
有上面可知,.parent
的内容区域尺寸为:400px × 200px 的(注意,没有包括 padding
部分)。
参照上面的规则,我们可知道 .child
的包含块就是 .parent
,因此 .child
的 width
、height
的百分值就是相对于 400px × 200px 来计算的。所以,.child
的 width
、height
值分别就是 200px
和 100px
。
另外,position
值为 relative
和 sticky
的元素的包含块规则与默认情况(static
)是一样的。
定位元素
postion
值为 absolute
或 fixed
的元素称为“定位元素”。它们之间的的包含块规则有不同也有相同的地方。类似于下面这样:
咱们先讲不同的地方。
各自的规则
absolute 元素
absolute 元素的包含块规则:
- 最近的
position
值为fixed
、absolute
、relative
或sticky
的祖先元素(即position
值不为static
)。 - 是相对于上述祖先元素的
padding
区域(padding box)定位的。
fixed 元素
fixed 元素的包含块规则:
都有的规则
absolute
或 fixed
元素还有共有的包含块规则。满足下列条件之一的祖先元素,也是它们的包含块(相对于 padding 区域)。
transform
的属性值不为none
。perspective
的属性值不为none
。will-change
的属性值为transform
或perspective;
还有在属性值为filter
的时候,不过仅在 Firefox 浏览器中有效。filter
属性值不为none
。contain
的属性值为paint
,即contain: paint
。
通过上面所列的规则,我发现一件有趣的事情。
fixed 元素一定是相对视口定位的吗?
要是在之前,我是这么认为的。要相对视口定位吗?好的,position: fixed
一下吧。因此,也给我造成一种错觉的,就是 fixed 元素就是相对视口定位的。
通过上面的学习,我们知道这并不一定。fixed 元素本质是相对于它的包含块定位的。就是说,如果也能满足上面所列的六条规则之一,也会成为 fixed 元素的包含块。
下面举一个例子:
fixed 元素被包在了一个 transform: scale(1)
元素里。我们来来看看结果(demo 地址):
可以看见,fixed 元素被钳制在了 transform: scale(1)
的容器元素里!所以下次千万别想当然的认为 fixed 元素就一定是相对视口定位的。要看具体情况的。
初始包含块
初始包含块(initial containing block)并不是根(<html>
)元素。初始包含块是指根元素所在的包含块,并且初始包含块具有与视口相同的尺寸。
(正文完)
广告时间(长期有效)
我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个猫奴并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。
(完)