嵌套使用 position: fixed 属性的元素会发生什么?

70

好的,我注意到了一件事,但在CSS规范中找不到它。使用position: fixed样式将使元素相对于浏览器视口绝对定位。如果您将一个固定位置的元素放在另一个元素内会发生什么?

类似下面示例的CSS:

.fixed {
  position: fixed;
  width: 100px;
  height: 100px;
  background: red;
}

#parent {
  right 100px;
  padding: 40px;
}

.fixed .fixed {
  background: blue;
}
<div id="parent" class="fixed">
  <div class="fixed"> </div>
</div>

据我所知,该元素相对于其最近的固定定位的父元素进行固定定位。这在所有浏览器中都可以观察到吗?这是一个错误还是故意为之的行为?
到目前为止,我还没有找到有关此主题的任何内容,只有“固定位置使其粘在页面上”的信息。

3
我知道这是一个老话题,但我最近遇到了一个相关的问题。在另一个固定元素内部的固定元素的行为因浏览器而异。以此Codepen 为例。在IE中,右侧的蓝色正方形在红色正方形内部,而在Chrome中则不是。我还有另一个问题,即从DOM中移除子元素时,在IE中该元素将被移除,但仍然显示在屏幕上。如果我能够复制这种行为,我会确保将其添加到此评论中。总之,嵌套固定元素是个坏主意。 - Joe Maffei
6个回答

43
修复和定位是两个不同的概念。它们的位置与绝对定位元素相同:相对于它们的包含块。但与绝对定位元素相比,它们固定在视口上的位置(即滚动时不会移动):

http://www.w3.org/TR/CSS2/visuren.html#propdef-position

盒子的位置是根据“absolute”模型计算的,但除此之外,盒子还相对于某个参考点固定。

定位

如果元素具有'position:fixed',则在连续媒体的情况下,视口建立包含块(...)
如果元素具有'position:absolute',则最近的祖先元素会建立一个具有'position'为'absolute'、'relative'或'fixed'的包含块(...)
这表明,虽然它们的定位算法相同(它们都相对于其包含块进行定位),但固定元素的包含块始终是视口,与绝对定位的元素相反,因此它们应该相对于那个而不是任何绝对或固定定位的元素。
事实上,确实是这样。例如,如果将top:20px添加到.fixed,则两个div将从视口顶部向下偏移20像素。嵌套的固定div不会从其父元素的顶部向下偏移20像素。
在这种情况下你没有看到它的原因是因为你实际上没有设置任何左/上/右/下属性,所以它们的位置是由它们在流中应该有的位置(即它们的 "static position")决定的,正如我的第一个引用所说,这是根据绝对模型完成的。

1
我看到这个并也认为应该是固定在视口上(始终固定),但是......请查看http://noveltybeard.co.cc/tempcssfixed/有两个div,每个都有固定的位置。在FF3.5 Mac上,只要不指定top/left/right/bottom值,我就可以让子元素保持“固定”在父元素的左上角。 - user146570
我在此期间更新了我的帖子。它们是两个不同的东西。它们的“静态位置”(当您没有指定左/上/右/下时)与绝对定位元素一样确定。它们确实固定在视口上,但如果您没有进行任何显式定位,它们的位置将由它们在流中的位置确定。 - mercator
那么这就像我为元素的“普通”位置计算x/y值,并在top:/left:下应用这些坐标,同时使用position: /fixed吗? - user146570
关于固定定位的快速说明:如果您没有提供明确的top/left/bottom/right值,则它们的位置是由它们在流中的位置确定的。但这在ie7中不适用(大惊小怪)。 - 1nfiniti

13

第一个元素

position: fixed;

而内部元素必须是:

position: sticky;


值得注意的是,position: sticky; 的支持还不完整。https://caniuse.com/css-sticky - Hrvoje Golcic
1
太好了。这应该是被接受的答案! - Rasmus
一整年后的2022年2月,sticky现在已经得到了所有主流浏览器的全面支持。请参见@HrvojeGolcic 上面的评论中的链接。 - Studocwho

10

只有当使用了position: fixed的元素的祖先元素中定义了以下任意一种样式规则:filtertransformperspective,并且其值不为none时,该祖先元素就会作为参考坐标系,而不是视口,来确定该元素的位置。

引自MDN

fixed

该元素从文档流中移除,在页面布局中不会留下空间。它的定位相对于由视口建立的初始包含块,但如果它的祖先元素之一具有设置为非nonetransformperspectivefilter属性,则该祖先元素将作为包含块进行定位(请参阅CSS变换规范)。 (请注意,透视和滤镜在形成包含块方面存在浏览器不一致性。)最终该元素的位置由上、右、下和左的值确定。

此值始终创建一个新的层叠上下文。在打印文档中,该元素在每个页面上都放置在相同的位置。


2

简短回答:

如果您有一个带有固定位置的可滚动元素(例如模态框),并且您想使其中一个子元素也固定(例如模态框关闭按钮),那么解决方法如下:您可以使您的元素不可滚动,而是在其中创建一个子元素并使其可滚动(例如模态框内容)。这样,您就可以对要固定的子元素(例如模态框关闭按钮)应用position: absolute,而不是position: fixed

详细回答:

在我的情况下,我有一个display: fixed的模态框,并将overflow: auto应用于它以使其可滚动。然后我想让关闭按钮display: fixed

在Chrome上嵌套display: fixed有效,但在Firefox上无效。因此,我更改了我的结构,从模态框中删除了overflow: auto以使其不可滚动,并使模态框内容可滚动。并且还为关闭按钮添加了position: absolute


2

我认为这不是真正的意图。具有固定定位的元素都是相对于窗口定位的,如果你有一个固定定位元素的子元素,则想要发生什么?您可以通过分别定位两个固定元素或使用其他定位来更改子元素在固定元素内的位置来轻松复制此行为。 :D


1
个人而言,我希望一个固定在固定元素内的元素表现得像任何其他固定元素一样:绝对定位于左/上/右/下坐标。当您滚动页面时,固定元素不会移动。同样,当您滚动其父元素时,固定在固定元素内的元素也不会移动。我可以让Firefox(3.5,Mac)做到这一点,但它并不是没有错误,所以也许我找不到任何关于此的原因! :P - user146570

2

我认为除了w3c所说的内容之外,没有更多的东西:

生成一个绝对定位的元素,相对于浏览器窗口定位。元素的位置是由“left”,“top”,“right”和“bottom”属性指定的。

因此,如果您去掉“padding:40px;”,您将得到两个元素-一个在另一个上方。

与将两个元素都绝对定位于同一父元素(body)的top:0 left:0具有相同效果。


我也是,朋友!请看我对mercator的答案的评论,了解我发现了什么。 - user146570

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接