Safari中的绝对定位浮动标题抖动

时间:2014-06-02 08:16:52

标签: javascript css animation safari

我在这里有一个简单的单个浮动标题的JSFiddle:

http://jsfiddle.net/zT9KQ/

基本上,这使用translate3d启动GPU,硬件加速浮动标题,以便更顺畅地绘制。标题在最新的Safari中抖动,但在最新的Chrome,FF和Opera中被完美地绘制。受此影响的实际代码(引发此问题的代码)是我编写的代码,无法公开共享,但以类似的方式工作,fixed定位很遗憾,无效溶液

我试过了:

  1. backface-visibility CSS属性设置为none
  2. perspective CSS属性设置为1000
  3. 在动画逻辑期间使用requestAnimationFrame
  4. 限制滚动事件回调。
  5. translateZ转换设置为高于0px的内容。
  6. 但这一切都没有奏效(或者至少 - 假设GPU已经开始但抖动仍然存在似乎是合理的)。我注意到有两个问题已经打开,这个问题与我提出的问题相同,但是没有人回答过这些问题:

    这是一个已知的错误吗?是否存在性能漏洞,我没有密封?

    修改

    我一直在接受很多关于为什么position: fixed不是有效选项的问题。直接回复安东尼对问题本身的评论:

    我没有模仿/重塑position: fixed。如果你看一下最高投票的答案(截至本评论),你会发现这似乎是一个Safari问题。在这种情况下,position: fixed不可取的原因是因为所讨论的代码必须能够支持多个浮动标题,这些标题位于彼此之下并且具有"容器"可能存在无限嵌套容器的范围。使用固定定位不仅会使代码更复杂,如果这些浮动标头位于水平滚动的容器中,而且整体上组件也更脆弱(当窗口小部件需要位于页面上其他位置的另一个容器内时计算偏移量) 。因此,从语义上讲,absolute定位比fixed更符合我的需求。

    第二次编辑

    在考虑安东尼告诉我的事情(我可能正在重新发明轮子)时,以及在听到用户3716477的-wekbit-sticky后,我想更新问题以显示我尝试的内容去做。您可以在此处查看我的代码在Safari以外的每个浏览器中的行为:

    http://cl.ly/3y1i3C473G2G

    我了解到:

    1. 您不能依赖scroll或任何类似滚动的事件(例如mousewheel),因为它们本质上是异步的。我向Apple提交了一个错误,详细说明了正在发生的事情,他们因此解决了这个错误。
    2. 现在没有真正的方法可以做我想要的事情 - 拥有多个堆叠和互相替换的浮动标头。我想我必须等-webkit-sticky之类的东西出来。
    3. 我应该从现在开始在SO问题中包含所有相关信息。 :-P
    4. 感谢玩家!以下是我从Apple收到的确切回复:

        

      Apple Developer Relations09-Jun-2014 01:16 PM

           

      工程已确定没有计划解决这个问题   基于以下内容:

           

      代码正在使用滚动事件,这是异步的。

           

      我们现在正在关闭此错误报告。

           

      如果您对此问题的解决方案有疑问,请   使用该信息更新您的错误报告。

           

      请务必定期检查新的Apple版本是否有任何更新   这可能会影响这个问题。

6 个答案:

答案 0 :(得分:10)

由于在使用触控板滚动和scroll事件触发之间存在apparent delay,因此您可以将处理程序附加到其他mousewheel event以使事情顺利进行。

$scrollContainer.on('scroll mousewheel', function () {
    // reinvent the wheel here
});

您可以在this demo here中看到,使用触控板滚动时抖动的可能性要小得多。在演示中,我在加载时调用了处理程序,以便在首次在Safari上滚动时消除闪存。可能仍然会有一些偶然的抖动,但是如果你想最小化它,你可以采用using setInterval and requestAnimationFrame的资源密集型方式。

这可能暂时解决了这个问题,但正如我之前所说的那样,这种仿真方法并不理想,而且你很可能在未来遇到更多麻烦。

答案 1 :(得分:3)

似乎是Safari滚动的错误。如果您手动拖动滚动条(不要使用触控板手势滚动),则不会出现抖动。

Chrome(和其他浏览器)处理滚动方式不同,这就是为什么这个错误只出现在Safari上。您可能想向Apple提交错误报告。

答案 2 :(得分:1)

稍微重组怎么样,像这样: http://jsfiddle.net/me2loveit2/zT9KQ/6/

HTML:

<div>
<h1>Header</h1>
    <div class="container">
        <div class="content"></div>
    </div>
</div>

CSS:

.container {
    height: 300px;
    position: relative;
    overflow-y:scroll;
}
.content {
    height:1000px;
}
h1 {
    position: relative;
    top:0px;
    left:0px;
    margin: 0;
    width: 100%;
    background: black;
    color: white;
}

答案 3 :(得分:0)

如果你使用类似于小丑代码的东西,你必须检查浏览器是否是safari,然后以不同的方式使用:

$(function () {
    var $header = $('h1'),
        $container = $('.container'),
        $scrollContainer = $('.scroll-container'),
        scrollContainerOffset = $scrollContainer.offset().top;
    $scrollContainer.on('scroll', function () {
        var top = Math.max(0, $container.offset().top * -1 + scrollContainerOffset);
        $header.css('top', top + 'px');

    });
});

即使不是您想要解决问题的方式,也可能是一种可能有帮助的解决方法......

答案 4 :(得分:0)

滚动事件在各种浏览器中异步发送;你不应该依赖他们做这样的事情。

最好的解决方案是使用position:-webkit-sticky;顶部:0;

答案 5 :(得分:0)

您可以尝试禁用所有和任何javascript-ish滚动处理,只需删除

即可 来自position: relative;

.container

之后只需添加h1{ top:0; },就会很高兴地坚持.scroll-container

摘自CSS绝对定位:

  

将其放置在相对于其最近位置祖先的指定位置......

要解释 - 您的绝对H1将查找树的第一个祖先元素,该元素定义“位置”属性并将其作为0,0参考点继承。

起初它可能是一个WTF,但是一旦你驯服它,这种行为就是一个强大的力量。

编辑:与原来的jsFiddle相关,我做了一些属性删除:

http://jsfiddle.net/253Ss/

也可以删除

^ .container包装器,因为从技术意义上说它不再是必需的。