Safari中的position:sticky在overflow:auto元素中无法工作

26
根据CanIUse,在使用overflow:auto的元素中,Safari存在一个已知问题,即position:sticky无法工作:

当父元素设置overflow为auto时,会防止Safari中的position: sticky生效。

然而,这正是我所需要的。我有一个可滚动的

,分为两列。右侧列应保持固定位置,即使整个
被滚动。我在右侧列上使用position:sticky的原因是我想让用户在光标位于右侧列时仍然能够滚动左侧列。而这是我找到的唯一解决方案。

Firefox/Chrome的实际例子在这里: http://cssdeck.com/labs/zfiuz4pc 橙色区域在滚动时保持固定,但在Safari中不起作用。

上面的示例对我的问题有些不必要的封装,但我希望尽可能地复制我需要它正常工作的环境。基本要点是我有这样一个结构:

<div class="modal-content">
  <div class="left-content">
  </div>
  <div class="sticky-element">
  </div>
</div>

而CSS为:

.modal-content {
  display: flex;
  overflow: auto;
  flex-flow: row nowrap;
}

.left-content {
  flex: 0 0 300px;
}

.sticky-element {
  position: sticky;
  top: 0;
  right: 0;
  width: 200px;
}

再次说明,在Firefox / Chrome中可以正常工作,但在Safari中无法正常工作。是否有解决方法可以使它在所有浏览器中都能正常工作?或者我可以使用不同的方法来保持即使鼠标指针位于固定元素上仍然可以滚动的功能吗?

8个回答

34

只需添加position: -webkit-sticky;


3
@debanjanB 你说得对,这是我的解释。目前,Safari 只支持使用前缀“-webkit-”来实现此功能。也许这个链接会帮助你理解 https://caniuse.com/#search=sticky - eledgaar
6
同样适用于Safari,粘性元素需要成为块级元素(或使用“display:block”)。我曾尝试使<button>元素粘性定位,但在Safari中无法正常工作,因为默认情况下按钮是inline-block - bryanbraun

9

.sticky-elementdisplay: block 属性添加进去就可以了,不用加上 position: -webkit-sticky。我在这个 Codepen 上找到了这个解决方案。


谢谢,伙计。我在Safari中遇到了Sticky/Position Bottom的问题...并且在粘性元素上使用display: block;解决了问题!不知道为什么,但似乎已经解决了问题! - user1406440
4
顺便说一下,我其实是一个女性 :) 很高兴它对你有用,这是一个不错的修复方法! - Binita Gupta

6

我从别人那里得到了这个解决方案:

http://cssdeck.com/labs/bu0nx69w

基本上,不要使用position:sticky,而是在右侧面板中使用position:fixed。关键是在父级div(在上面的示例中为.modal-content)中还要使用will-change:transform,这样position:fixed才会相对于该父级固定,而不是视口。这是一个巧妙的小技巧。


你可能已经解决了你的使用案例,但是你找到了sticky无法工作的原因吗? - Laura
2
@Laura 这只是Safari对sticky的实现。在overflow:auto;position:sticky的特定场景下,Safari无法处理它。因此,这里使用了position:fixed的解决方法。 - accelerate
谢谢,这对我很有用。我的布局更加复杂,第一列和最后一列是静态的,中间的列如果太多需要水平滚动,并且整个第一行需要固定在屏幕顶部。我最终使用了这个技巧来处理中间的列,并成功地让第一列和最后一列的顶部行保持固定。 - JStephen
不幸的是,由于 z-index:-1 的存在,这将消除粘性元素中的交互。 不过这是一个不错的技巧。 - Andy E

5

我有一个类似的案例:

<div scroll>
    <div sticky />
    <list />
</div>

只需将滚动内容用 div 包装一下就行了,非常有效:
<div scroll>
    <div>
       <div sticky />
       <list />
    </div>
</div>

4
我必须使用以下内容,以使其在Chrome和Safari中正常工作:
position: sticky;
position: -webkit-sticky;
display: block;

对我来说,在软件版本为14.7的iPhone上它不起作用。 在软件版本为15.2.1的iPhone上,它可以运行。 - IvoAtanasov

1
如果父元素具有“overflow: hidden”属性,则“position: sticky”将无法正常工作。设置为“sticky”后,它会自动将您的元素从相对位置转换为实际固定在文档顶部的位置。请注意保留HTML标签。

0

针对这种特定情况的另一种解决方案,只要您不需要模态框右侧的滚动条。

由于您的粘性元素与您的.modal-content具有相同的高度,因此您可以从.sticky-element中完全删除粘性。首先,从.modal-content中删除overflow:auto,然后将该样式添加到.left-content中,因为这是您想要滚动的部分。


发布后立即意识到,原帖作者想要在固定的右侧部分滚动时仍能滚动左侧。这种方式也无法实现。 - shaws

-1

我现在无法在Safari上测试这个,但是当我创建一个固定页脚时,这对我来说一直是一个替代方案:

<!DOCTYPE html>
<html>
<head>
    <title>sticky side div</title>
    <style type="text/css">
        .maindiv{
            position: relative;
            display: inline-block;
            background-color: forestgreen;
            width: calc(100vw - 150px);
            height: 100%;
            overflow: auto;
        }
        .sidediv{
            position: fixed;
            display: inline-block;
            background-color: lightyellow;
            float: right;
            width: 100px;
            height: 100%;
        }
    </style>
</head>
<body>
    <div class="maindiv">
        Lorem 45    
    </div>
    <div class="sidediv">
        Lorem 30
    </div>
    <div class="maindiv">
        Lorem 100
    </div>
    <div class="maindiv">
        Lorem 900
    </div>
</body>
</html>

一旦您知道右侧内容的宽度,请再添加一些像素,然后使用CSS calc函数来确保其他div不会流入其中

此外,在Safari 7中,vh和vw存在已知的错误。您可以通过在父元素具有vh高度或vw宽度的情况下,在#child元素上设置height: inherit来修复它们

但是,如果您不需要跨浏览器支持,我最好的建议是使用CSS Grids


我尝试了你的标记,它只能按原样工作。但是如果我添加一个带有 position:absolute 的父元素,右侧面板的位置就不正确了。我发布了一个解决方案,这是我从别人那里得到的,适合我的需求。 - accelerate

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