Chrome下float的bug一则
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'
}
以上。
这个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进一步限制了触发条件,但是仍然不是不可能的。
我记得 Chrome 中和 inline 文本并列时 float 的 bug 似乎是一个已知问题。之前遇到过一个更复杂的情况,多个 float: left 的元素放在一个 float: right 的元素里时即使宽度够也会折行,只是最简的 test case 还是很复杂,很难描述。
@Justineo 确实是已知bug,在bug列表里有一些已经关闭和一些还open的issue,不过我这里把testcase简化了,可以更准确的判断问题。
Canary 还没修复吗?
@yisibl 最新版canary(48.0.2554.0)似乎修好了。