CSS:position:absolute内部的position:fixed

38
我是一个有用的助手,可以为您翻译文本。
我遇到了一些非常奇怪的行为,并且在我测试的每个浏览器中都不一致。
我的布局相当复杂,但主要问题在这里:
<div id="drop">
  <div id="header"></div>
</div>

#drop具有position:absolutez-index:100

#header具有position:fixed; top:60px;

当我开始向下滚动时,Chrome忽略了position:fixed规则。 如果我从#drop中删除上述任一样式,则Chrome开始遵守position:fixed规则。

在Ubuntu Chrome 23.0.1271.97上无法正常工作,并且在Mac Chrome 25.0.1364.99上看到相同的行为。 我的朋友使用Ubuntu Chrome 25.0.1364.68 beta并且可以正常工作。 我已在firefox上进行了测试,它有点有效(伴随其他症状)

有人听说过这个错误吗? 或者有人可以重现它吗?

编辑

我正在使用openlayers地图作为另一个具有position:fixed的div,如果我删除该图层或将其至少更改为display:none,则此奇怪的错误就会消失。

编辑

注意到在出现这个bug的时候,如果我来回改变缩放级别,那么位置会自动调整到正确的行为。对我来说,这表明了一个webkit问题,它未能执行一些内部回调函数来滚动。

另一个极为奇怪的事情是,我在#header中有几个链接,如果我只点击预期位置,它们就能正常工作,即使div不在那里。总的来说,我注意到只有渲染是有问题的。如果在任何时候我强制浏览器通过调整窗口大小、更改缩放比例或只是选择全部来重新渲染,则标题栏会跳到正确的位置,但不会保持固定。


你是否为固定元素设置了位置值?例如 top:0;left:0;? - lukeocom
是的,抱歉没有提到。我在固定元素上使用了 top:60px;。我会更新原始帖子。 - Mikhail
除了在我的特定示例中发现一个错误依赖项,我也无法重现它。现在正在更新原始帖子。 - Mikhail
2
你的代码中使用了CSS变换吗?因为如果是这样的话,那就是导致position:fixed无法工作的原因。 - Danield
@Danield,OpenLayers使用这些,还有我正在使用的一些jQuery插件。我会看看是否可以禁用它们并更新OP。 - Mikhail
显示剩余4条评论
7个回答

44
你在评论中提到OpenLayers使用CSS变换。既然如此:
带有固定定位的元素将相对于具有变换的元素而不是相对于视口-而不是相对于视口
请查看规范:变换渲染模型 引用块:

指定“transform”属性的值为除“none”之外的其他值会在应用它的元素上建立一个新的本地坐标系统。

.wpr
{
    width: 200px;
    height:1000px;
    background: pink;
    position:relative;
    margin: 0 200px;
    -webkit-transform: translateX(0);
    transform: translateX(0);
}
.fixed
{
    width: 200px;
    height:200px;
    margin: 50px;
    position: fixed;    
    top:0;
    left:0;
    background: aqua;
}
<div class="wpr">
    <div class="fixed"></div>
</div>


2
你刚刚救了我免于可能的噩梦:),我正在使用Bootstrap Affix,并且还在父容器上使用transform,我将摆脱transform并使用jQuery动画:) - ndd
2
谢谢您的回复,我只是想补充一下,在最新版的Chrome中,即使是will-change:transform也会触发这种行为。 - schellmax

4
正如最佳答案所述,这是预期的行为,并且符合规范。CSS transforms 的使用也是其中一个重要组成部分。
在您的情况下,问题出在 OpenLayers 上,但是对于任何使用 will-change: transform 的人来说都适用(可能有很多访问此问题的人)。这已经在 Chromium bug 追踪器上提出过[1],并被标记为 WontFix,因为它是预期的行为。官方评论如下:

这是规范所要求的行为(http://dev.w3.org/csswg/css-will-change/):"如果属性的任何非初始值会导致元素为固定位置元素生成包含块,则将该属性指定为 will-change 必须使该元素为固定位置元素生成包含块。"

这意味着一旦指定了 will-change:transform,您应该能够便宜地添加/删除/更改转换,而不需要重新布置固定位置的后代。

请注意,使用 will-change 的其他值(例如 opacity、top)不会更改固定位置后代的定位。

据我所知,唯一的解决方案是将 will-change 元素的子元素更改为同级元素,以防属性进行级联。
另外,值得一提的是,在我的特定情况下,我可以通过更具体地使用 will-change 属性来修复它。而不是在包含需要 GPU 卸载的性能障碍的 div 上使用它,我直接在有问题的元素上使用。但这是由于我的原始错误代码,所以对于大多数情况都不适用。

1
你需要将header放在父容器drop外部才能使其正常工作。
我几天前也遇到了类似的问题。例如,如果您设置header的z-index,它将达到父drop容器的z-index。由于它已经位于具有另一个z-index的容器内部,header的z-index将无用。
相同的逻辑也适用于位置。

这有点说得通,但如果你所说的那么准确,那么OpenLayers就不会对此产生任何影响。如果我移除OpenLayers(它们在所有div之外),那么我的“header”就能按预期工作了。 - Mikhail

0

我想添加另一个可能的解决方案,因为我曾经苦苦挣扎于Chrome忽略position:fixed很长一段时间,直到我最终找到了罪魁祸首:

-webkit-perspective: 1000;

它来自我使用的一个插件,并导致所有position:fixed元素被忽略。 希望对某些人有帮助。

0
将此添加到父级:
position: fixed;

...并将此传递给子元素:

position: sticky;

0

我认为这是不可能的,我不认为两个位置可以放在同一个地方而不会崩溃。但我认为最好使用JavaScript中的可用高度,我的意思是如果你想要一个外部div来容纳内部div,并且外部div必须覆盖整个屏幕,在js中使用Availheight,这将获取屏幕高度,然后应用它,之后将所有的div设置为固定位置。


-6
首先,在您的 div 中放入一些内容,因为空的行为会变得非常奇怪。然后,如果将 fixed 放入一个 absolute 中,您期望什么呢?显然,没有人知道您的 fixed div 的参考点是什么。它应该是其父元素的位置吗?这个位置不随滚动而改变,还是页面位置发生变化?尽量使用那些完全有意义且具有明确定义的东西,因为如果您在 Chrome 中修复它,那么在另一个浏览器中会发生什么?您真的喜欢在所有浏览器上进行测试吗?
我想对您的 div 进行小的更改,使其将 fixed div 从 absolute div 中拿出来或将 absolute div 移动到其他地方。

6
在 OP 中,我只展示了 DOM,而没有展示内容。每个 div 中都有子标签和文本。fixed 不需要参考点。所有规范都指明它是相对于浏览器窗口参考的。下次请在请求额外信息时使用注释而不是答案。 - Mikhail

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