Chrome 渲染问题。体内带有 UL 的固定位置锚

Posted

技术标签:

【中文标题】Chrome 渲染问题。体内带有 UL 的固定位置锚【英文标题】:Chrome rendering issue. Fixed position anchor with UL in body 【发布时间】:2013-02-15 15:26:45 【问题描述】:

Google Chrome 和 Opera 存在渲染问题(为什么?=)使用这样的代码:

<html>
<style>
    #content 
        width: 150px;
        background: gray;
    

    #sidebar 
        position: fixed;
        left: 200px;
        background: gray;
    
</style>
<body>
    <div id="sidebar">
        <a href="#s1">Link #1</a><br/>
        <a href="#s2">Link #2</a>
    </div>

    <div id="content">
        <div id="s1">
            <a href="#s1">Link #1 TARGET</a>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
            sed do eiusmod tempor incididunt ut labore et dolore magna
            aliqua. Ut enim ad minim veniam, quis nostrud exercitation
            ullamco laboris nisi ut aliquip ex ea commodo consequat.
            Duis aute irure dolor in reprehenderit in voluptate velit
            esse cillum dolore eu fugiat nulla pariatur.
            Excepteur sint occaecat cupidatat non proident, sunt in culpa
            qui officia deserunt mollit anim id est laborum.</p>
        </div>
        <div id="s2">
            <a href="#s2">Link #2 TARGET</a>
            <ul>
                <li>Item 1</li>
                <li>Item 2</li>
            </ul>
        </div>
    </div>

    <a href="#">TOP</a>
</body>
</html>

如您所见,我正在尝试使右侧的侧边栏保持静态。 一切正常,直到您在页面上添加一些 &lt;UL&gt; 标记:

http://www.youtube.com/watch?v=zkhH6di2M0c

当我点击锚链接时,固定的 div 有时会开始消失。

可以做些什么来避免这种行为?

【问题讨论】:

我把这个和平的代码放在一个 html5-boilerplate 中并且遇到了同样的问题。似乎是 chrome 中的一个错误。 我 put your code up on jsFiddle 但相信它没有复制……可能有一些线索吗? 我也尝试过 jsFiddle,但似乎它没有复制,因为 jsFiddle 引擎使用 iframe 来显示结果。 【参考方案1】:

Chrome 解决方案:

-webkit-transform: translateZ(0) 添加到#sidebar 为我解决了这个问题。

多年来,我使用translateZ(0) 修复了许多 Chrome 显示错误。基本原理是通过调用 3D 转换,重新绘制与 CSS 痛苦堆栈的其余部分分离(我无法提供更多细节,对我来说几乎都是希腊语)。无论如何,它似乎对我有用!

    #sidebar 
        -webkit-transform: translateZ(0);
    

Opera 解决方案:

这不是通用解决方案(需要根据相关元素的定位要求进行调整)。它通过在可能影响布局的属性上强制连续重绘(通过 CSS 动画)来工作(强制计算和渲染其他布局因素,即保持固定定位),但实际上不会。在这种情况下,我使用了margin-bottom,因为这不会影响您的页面布局(但 Opera 不知道!):

@keyframes noop 
  0%    margin-bottom: 0; 
  100%  margin-bottom: 1em; 


#sidebar 
    animation: noop 1s infinite;

注意:该解决方案并不完美,因为(至少在我的机器上)错误测试用例会导致一分钟闪烁,因为 Opera 失去定位并快速重绘。遗憾的是,我认为这与您将得到的一样好,因为as George says in his answer,这是 Opera 在重绘之间的自然行为——理论上我的代码使元素的重绘是连续的,但实际上会有无限小的间隙。

EDIT 2 (2013-11-05)此后我经常遇到此错误的变体。尽管原始发布者的简化测试用例提出了一个完全合法的错误,但大多数情况发生在已经有 3D 变换在身体上运行的情况(或类似地在 DOM 树的高处)。这通常被用作强制 GPU 渲染的黑客手段,但实际上会导致像这样令人讨厌的重绘问题。 2 个无操作 3D 变换不正确:如果您使用的是树上较高的一个,请先尝试删除它,然后再添加另一个。

EDIT 3 (2014-12-19): Chris reports translateZ(0)scale3d(1,1,1) 的某些情况下不起作用。

【讨论】:

使用-webkit-transform: scale3d(1,1,1); 似乎也适用于其他一些情况 @Barney 我知道,但在我的情况下,translateZ(0) 没有解决问题,而scale3d(1,1,1) 出于任何原因解决了这个问题。我不是假装理解它,只是将它作为另一种选择扔在那里,以防其他人遇到同样的事情。 @JosephCasey 是的,在树的上方使用空转换是导致此错误的常见原因。在 hack 上堆积 hack 有点代码味道,所以如果是这种情况,我建议完全放弃转换 hack(较低的 FPS 比显示错误的情况更好)。你能详细说明去抖动的方法吗? 当然,requestAnimation 帧、事件限制等。希望position: sticky 尽快流行起来。 工作了,感觉又回到了2002年!【参考方案2】:

如果您了解文档的正常流程是如何工作的,那就有意义了。假设这是一个边缘案例。

在任何元素中都没有声明高度,并且#sidebar 通过position:fixed 被带出文档的正常流程。

如果向#sidebar 添加高度属性(像素,而不是百分比),问题就解决了。

我建议包含 Normalize.css,我认为它会解决这个错误。

【讨论】:

我按照你说的添加height: 300px,问题没有解决:sunsay.ru/shared/rb-0012.html点击链接#2,#3 我点击了所有链接几次,完全没有问题。我在:版本 24.0.1312.56 Ubuntu 12.10 (24.0.1312.56-0ubuntu0.12.10.3) 。 (只有链接#1 在某些时候被剪掉了(一半),但非常轻微 我刚刚尝试了相同版本的 chrome 和 ubuntu。问题依然存在。 这很奇怪......所以你的问题是侧边栏 div 被隐藏/剪切了?【参考方案3】:

Chrome 的关键是:

 html, body height:100%;overflow:auto

加上这个,固定位置问题应该就解决了。

【讨论】:

这在 Opera 上也适用于我,但需要注意的是它会产生双滚动条,这太可怕了。但是,使用重置样式表(或简单地将 margin:0; 添加到该规则中),该问题就消失了——这行得通! 是的,我在一个旧的邮件列表中看到了这个解决方案......但我不喜欢我们不能再在固定 div 和这个固定 div 上使用鼠标滚动(如果我们愿意set right:0) 显示在右侧滚动条上方 :-( 在我们点击页面内部之前,我们不能使用 Page Down/Up 和光标向下/向上滚动。 当使用这个时,'scroll'事件在滚动窗口时停止触发。 在我的例子中,我使用了 `html, body overflow:auto` 然后scroll 仍然被触发并且position:fixed 有效!

以上是关于Chrome 渲染问题。体内带有 UL 的固定位置锚的主要内容,如果未能解决你的问题,请参考以下文章

将UL的位置设置为固定,下拉菜单不起作用

关于html的标=标签《ul》的位置固定问题

jQuery 移动数据过滤器固定位置/静态

更改位置时的 Safari 渲染问题:固定到位置:相对

Youtube iframes 位于 Chrome 中的固定位置元素之上

Chrome:拥有 HTML5 视频位置:固定或绝对导致所有背景附件:固定中断