fixed 元素一定是相对视口定位的吗?

7,913 阅读4分钟

引言

fixed 元素一定是相对视口定位的吗?不一定。举一个例子,如果父元素 transform: scale(1) 了,子元素是 position: fixed。会发现,子元素是相对这个父元素定位的。

image.png

包含块

其实上面这个问题,牵扯到了包含块(containing block)的概念。那么,包含块是用来干嘛的呢?

简单说来,一个元素的尺寸(比如 widthheightpadding 啥的)或者定位(比如定位元素的 lefttop 属性啥的)通常都是参照它的包含块计算的。可以这么说,在我们日常的 CSS 的使用中,凡是涉及到与布局相关的代码,几乎都在与包含块打交道。

学习包含块之前,可以先记住以下两点:

  1. 一个元素的包含块通常是该元素的祖先元素。
  2. 一个元素的包含块为何,只与这个元素的 position 属性值有关。

好了,下面就开始学习了。

元素默认的包含块

position 属性默认值是 static,或者我们随便写个元素,使用 getComputedStyle 也能知道。

<div id="test"></div>
<script>getComputedStyle(test).position // "static"</script>


那么对于 position:static 元素,它的包含块是啥呢?下面给出了范围:

  1. 最近的祖先元素,且是一个块元素(block container,比如 display 值为 inline-blockblocklist-item 的这些元素)。或,
  2. 最近的祖先元素,且能创建 BFC 上文下环境 的元素(比如 <table> 元素,Flex 容器,Grid 容器,或是块元素本身)。还有,
  3. 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 部分)。

image.png

参照上面的规则,我们可知道 .child 的包含块就是 .parent,因此 .childwidthheight 的百分值就是相对于 400px × 200px 来计算的。所以,.childwidthheight 值分别就是 200px100px

image.png

另外,position 值为 relative 和 sticky 的元素的包含块规则与默认情况(static)是一样的。

定位元素

postion 值为 absolute 或 fixed 的元素称为“定位元素”。它们之间的的包含块规则有不同也有相同的地方。类似于下面这样:

image.png

咱们先讲不同的地方。

各自的规则

absolute 元素

absolute 元素的包含块规则:

  1. 最近的 position 值为  fixedabsoluterelativesticky 的祖先元素(即 position 值不为 static)。
  2. 是相对于上述祖先元素的 padding 区域(padding box)定位的。

fixed 元素

fixed 元素的包含块规则:

  • 相对于视口(viewport)定位的。

都有的规则

absolutefixed 元素还有共有的包含块规则。满足下列条件之一的祖先元素,也是它们的包含块(相对于 padding 区域)。

  1. transform 的属性值不为 none
  2. perspective 的属性值不为 none
  3. will-change 的属性值为 transform 或 perspective;还有在属性值为 filter 的时候,不过仅在 Firefox 浏览器中有效。
  4. filter 属性值不为 none
  5. contain 的属性值为 paint,即 contain: paint

通过上面所列的规则,我发现一件有趣的事情。

fixed 元素一定是相对视口定位的吗?

要是在之前,我是这么认为的。要相对视口定位吗?好的,position: fixed 一下吧。因此,也给我造成一种错觉的,就是 fixed 元素就是相对视口定位的。

通过上面的学习,我们知道这并不一定。fixed 元素本质是相对于它的包含块定位的。就是说,如果也能满足上面所列的六条规则之一,也会成为 fixed 元素的包含块。

下面举一个例子:

fixed 元素被包在了一个 transform: scale(1) 元素里。我们来来看看结果(demo 地址):

image.png

可以看见,fixed 元素被钳制在了 transform: scale(1) 的容器元素里!所以下次千万别想当然的认为 fixed 元素就一定是相对视口定位的。要看具体情况的。

初始包含块

初始包含块(initial containing block)并不是根(<html>)元素。初始包含块是指根元素所在的包含块,并且初始包含块具有与视口相同的尺寸。

(正文完)


广告时间(长期有效)

我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个猫奴并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。

(完)