hax.github.com icon indicating copy to clipboard operation
hax.github.com copied to clipboard

Chrome下float的bug一则

Open hax opened this issue 10 years ago • 5 comments

float一直是浏览器bug的重灾区。今天确认了Chrome浏览器中存在一个严重的float的bug。定位和调试过程就略了。直接看我精简到最小的testcase。

<div>
    text
    <div id="r" style="float: right">right</div>
</div>

只要空间足够,右浮动的内容应该和 text 在同一行,即如下效果:

text                right

然而当我们有如下脚本

function test() {
    var s = document.getElementById('r').style
    s.float = s.float ? null : 'right'
}

执行两次test()本应不变,但是实际效果变成了:

text
                    right

上述bug可在360se 7(Chrome 31)里重现。不过最新版的Chrome已经修复了。

然而新版Chrome其实仍然存在这个bug,只是触发条件更苛刻了一点点:

<div>
    <div id="l" style="display: inline">text</div>
    <div id="r" style="float: right">right</div>
</div>
function test() {
    var s = document.getElementById('l').style
    s.display = s.display ? null : 'inline'
    s = document.getElementById('r').style
    s.float = s.float ? null : 'right'
}

以上。

hax avatar Aug 21 '15 11:08 hax

这个bug还是比较容易在生产环境产生问题的。比如

<head>
<link rel="stylesheet" href="site.css">
</head>
<body>
...
<div>
  text
  <div class="r">right</div>
</div>
...
<script src="site.js"></script>
</body>

site.css:

...
.r { float: right }
...

看上去很正常的页面,也不存在动态修改float样式的情况。但是在实际环境中有一定的概率site.js会在site.css加载完成之前先加载成功并执行了。而site.js中可能有会触发reflow的功能,比如获得某个元素的实际位置和大小——调用getBoundingClientRect()之类的方法或访问clientHeight之类的属性。而此后当site.css加载完再render就会触发此bug。

尽管当前版本的Chrome进一步限制了触发条件,但是仍然不是不可能的。

hax avatar Aug 21 '15 12:08 hax

我记得 Chrome 中和 inline 文本并列时 float 的 bug 似乎是一个已知问题。之前遇到过一个更复杂的情况,多个 float: left 的元素放在一个 float: right 的元素里时即使宽度够也会折行,只是最简的 test case 还是很复杂,很难描述。

Justineo avatar Aug 21 '15 13:08 Justineo

@Justineo 确实是已知bug,在bug列表里有一些已经关闭和一些还open的issue,不过我这里把testcase简化了,可以更准确的判断问题。

hax avatar Aug 22 '15 10:08 hax

Canary 还没修复吗?

yisibl avatar Oct 26 '15 15:10 yisibl

@yisibl 最新版canary(48.0.2554.0)似乎修好了。

hax avatar Nov 04 '15 06:11 hax