webkit里会出现突然闪一下的问题

来源:互联网 发布:美工能力提升 编辑:程序博客网 时间:2024/04/29 17:42

写这么多的字比较累,看得也累,如果想直接知道解决方法,就一句:
-webkit-backface-visibility: hidden;
(但不能用于sprite雪碧图)

或者
.no-flick{-webkit-transform:translate3d(0,0,0);}

一,场景
在chrome下出现屏幕会闪,但不是每次都能复现。
出现这类问题,是种头疼的事。

二,初步debug
昨天晚上和maomao,晓刚我提起,会否是我们的mask导致。
因为mask的style是加了opacity。没有加display:none。页面还没load就把mask给加到body第一个元素了。

而后我在mask把background:white改成Red。看看是否会闪成红色。
很遗憾是没有出现红色。
结论基本确定不是mask导致的问题。

但幸运的是发现这个问题相起来都是在header处,并且是在<a ><i><i></a>标签里。

三,再次debug
第二天中午吃饭的时候说起今天一定要想法解决这个问题。
晓亮提到会否是Transform引起的。
于是下午试了一下,去除transform果然管用。
但是我们仍然没有知道解决办法,以及为何这样。

晚上回到家之后再打开dom inspect。先精简代码(如果没法定位问题,精简代码也可以采取二分法,这样速度理论上会更快些):
<!doctype html>
<!--STATUS OK-->
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
 <link href="http://st.youa.com/resource/css/apps/sns_bc.css?f98dcf15fd.css" rel="stylesheet" type="text/css" media="screen">
 <link rel="stylesheet" type="text/css" href="http://st.youa.com/resource/sp/sns/home/css/index.css?1325074239.css"/>
</head>
<body>
<div id="header">
 <div class="global-header">
 <div class="global-header-inner">
 <ul class="person">
 <li class="top-user" id="top-user"><a href="###" class="user"><img src='
 http://img.youa.com/img_new/a94813a8f57f526b715f5c2a--20-20-1' alt=""/>rank<i></i></a></li>
 <li class="top-mess" id="top-mess"><a href="javascript:;" class="mess">消息<i></i></a></li>
 </ul>
 
 </div>
 </div>
</div>
</body>
</html>

四,解决问题
在百度上搜索类似css 3 transform bug,无果。
别灰心,在stackoverflow上看看。
query: "transform flick bug webkit"
果然有料。
http://stackoverflow.com/questions/3461441/prevent-flicker-on-webkit-transition-of-webkit-transform

五,是否还有其他优化方案
意味着在i元素里也加入
-webkit-backface-visibility: hidden;
(但不能用于sprite雪碧图)

也可以通过
.no-flick{-webkit-transform:translate3d(0,0,0);}
来解决。

直观上看,我看到translate3d这么解决,心里想这不是扯东窗补西窗么。
顺着往下看,果然如此。translate3d有问题。
引用
However, the body {-webkit-transform} approach causes all elements on the page to effectively be rendered in 3D. This isn't the worst thing, but it slightly changes the rendering of text and other CSS-styled elements.
It may be an effect you want. It may be useful if you're doing a lot of transform on your page. Otherwise, -webkit-backface-visibility:hidden on the element your transforming is the least invasive option.
所以, 从目前来看-webkit-backface-visibility: hidden; 是最优解。

六,弄清源头
关于这个css3属性拿来作什么用的。可以查阅w3c
http://www.w3.org/TR/css3-3d-transforms/#backface-visibility-property
引用
The ‘backface-visibility’ property determines whether or not the "back" side of a transformed element is visible when facing the viewer. With an identity transform, the front side of an element faces the viewer. Applying a rotation about Y of 180 degrees (for instance) would cause the back side of the element to face the viewer.
This property is useful when you place two elements back-to-back, as you would to create a playing card. Without this property, the front and back elements could switch places at times during an animation to flip the card. Another example is creating a box out of 6 elements, but where you want to see the inside faces of the box. This is useful when creating the backdrop for a 3 dimensional stage.
也就是说这个属性做翻卡片的小游戏,比较合适哈。
测试运行以下代码,就能理解为什么会在transform时会闪:
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#div1 {
width:120px;
height:100px;
background-color:yellow;
border:1px solid black;
-moz-transform:rotateY(25deg); /* Firefox */
-webkit-transform:rotateY(25deg); /* Safari and Chrome */
transform:rotateY(25deg);
}
</style>
<script type="text/javascript">
function rotate(value) {
  document.getElementById('div1').style.webkitTransform = "rotateY(" + value + "deg)";
  document.getElementById('div1').style.MozTransform = "rotateY(" + value + "deg)";
  document.getElementById('div1').style.transform = "rotateY(" + value + "deg)";
  document.getElementById('span1').innerHTML = value + "deg"
}
function checkBackface() {
  if (document.getElementById("bf").checked == true) {
    document.getElementById('div1').style.webkitBackfaceVisibility = "hidden"
  } else {
    document.getElementById('div1').style.webkitBackfaceVisibility = "visible"
  }
}
</script>
</head>
<body>
<div id="div1">HELLO</div>
<p>Rotate the yellow div element, with and without checking the backface-visibility checkbox:</p>
<p>Hide the backside:<input type="checkbox" onchange="checkBackface()" id="bf" /></p>
Rotate:<br />
<input type="range" min="-360" max="360" value="25" onchange="rotate(this.value)" /><br />
-webkit-transform: rotateY(<span id="span1">7deg</span>);
</body>
</html>
我的理解是transform其实都是3维的变换,而backface-visibility:hidden,则是在几个面隐藏。理论上解释得通,合情合理。
如上,如果把translate3d变换关闭也可,但性能不好。
如。象border:0与border:none是有本质区别的。
0需要浏览器渲染。而none不需要渲染。

结论
在用position:absulote+zindex!=0时用transform会偶尔出现页面会闪的现象,确实是chrome的一个bug。
chromium里没有发现有人提bug,所以我检索了一下webkit.org的bugtrace,看到
https://bugs.webkit.org/show_bug.cgi?id=47175
https://bug-47175-attachments.webkit.org/attachment.cgi?id=69779
这哥们儿还举出case了。就不用自己写bad case了。
-webkit-backface-visibility: hidden; 是最优解。

OK。结案。

原创粉丝点击