如何强制WebKit重绘/重绘以传播样式更改?

I have some trivial JavaScript to effect a style change:

sel = document.getElementById('my_id');
sel.className = sel.className.replace(/item-[1-9]-selected/,'item-1-selected');
return false;

This works fine with the latest versions of FF, Opera and IE, but fails on the latest versions of Chrome and Safari.

It affects two descendants, which happen to be siblings. The first sibling updates, but the second doesn’t. A child of the second element also has focus and contains the <a> tag that contains the above code in an onclick attribute.

In the Chrome “Developer Tools” window if I nudge (e.g. uncheck & check) any attribute of any element, the second sibling updates to the correct style.

Is there a workaround to easily and programmatically “nudge” WebKit into doing the right thing?

Mandy村村2020/03/24 17:49:37

就我而言,“ display / offsetHeight” hack无效,至少在将其应用于动画元素时无效。

我有一个下拉菜单,正在页面内容上打开/关闭。菜单关闭后,工件才保留在页面内容上(仅在webkit浏览器中)。“ display / offsetHeight” hack唯一可行的方法是将其应用于身体,这似乎很讨厌。

但是,我确实找到了另一个解决方案:

  1. 在元素开始设置动画之前,添加一个定义“ -webkit-backface-visibility:hidden;”的类。在元素上(我猜你也可以使用内联样式)
  2. 完成动画制作后,删除类(或样式)

这仍然很棘手(它使用CSS3属性来强制进行硬件渲染),但至少它只影响所涉及的元素,并且在PC和Mac上的Safari和chrome上都为我工作。

梅西门蛋蛋2020/03/24 17:49:37

我在Ionic html5应用程序上工作,在几个屏幕上我已经absolute定位了元素,当在IOS设备(iPhone 4,5,6,6+)上向上或向下滚动时,我有重画错误。

尝试了许多解决方案,但除了解决我的问题外,他们都没有工作。

.fixRepaint在那些绝对位置元素上使用了CSS类

.fixRepaint{
    transform: translateZ(0);
}

这已经解决了我的问题,可能会对某些人有所帮助

米亚番长2020/03/24 17:49:37

我使用该transform: translateZ(0);方法,但在某些情况下还不够。

我不喜欢添加和删除类,所以我试图找到解决方法,最后得到了一个效果很好的新技巧:

@keyframes redraw{
    0% {opacity: 1;}
    100% {opacity: .99;}
}

// ios redraw fix
animation: redraw 1s linear infinite;
A飞云2020/03/24 17:49:37

我在使用另一个div插入了多个div时遇到了这个问题position: absolute,插入的div没有position属性。当我将position:relative更改为正常时。(很难找出问题所在)

就我而言,Angular用插入元素ng-repeat

飞云2020/03/24 17:49:37

我今天偶然发现了这个问题:prototype.js的Element.redraw()

使用:

Element.addMethods({
  redraw: function(element){
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    (function(){n.parentNode.removeChild(n)}).defer();
    return element;
  }
});

但是,我注意到有时您必须直接对有问题的元素调用redraw()。有时重新绘制父元素并不能解决孩子遇到的问题。

关于浏览器渲染元素的方式的好文章:渲染:重新绘制,重排/重新布局,重新样式

樱GO2020/03/24 17:49:37

我们最近遇到了这个问题,并发现在CSS中使用translateZ将受影响的元素提升为复合层可以解决此问题,而无需使用额外的JavaScript。

.willnotrender { 
   transform: translateZ(0); 
}

由于这些绘画问题主要出现在Webkit / Blink中,并且此修复程序主要针对Webkit / Blink,因此在某些情况下更可取。特别是由于接受的答案几乎肯定会导致回流和重绘只是一个重绘。

Webkit和Blink一直在致力于渲染性能,而这些小故障是旨在减少不必要的流程和绘制的优化的不幸副作用。 CSS可能会更改或将来的另一个规范成为将来的解决方案。

还有其他方法可以实现复合层,但这是最常见的方法。

Itachi2020/03/24 17:49:37

我也遇到了同样的问题。将danorton的“切换显示”修复功能添加到动画的步进功能后,确实可以为我工作,但我担心性能,因此我在寻找其他选项。

在我的情况下,未重涂的元素在绝对位置元素内,该元素当时没有z索引。向此元素添加z-index会更改Chrome的行为,并且按预期进行重新绘制->动画变得流畅。

我怀疑这是灵丹妙药,我想这取决于Chrome 为什么选择不重绘该元素,但我在此发布此特定解决方案是希望它对某人有所帮助。

干杯,罗布

tl; dr >>尝试将z-index添加到元素或其父元素。

西门2020/03/24 17:49:37

以下作品。在纯CSS中只需设置一次。而且它比JS函数更可靠地工作。性能似乎不受影响。

@-webkit-keyframes androidBugfix {from { padding: 0; } to { padding: 0; }}
body { -webkit-animation: androidBugfix infinite 1s; }
2020/03/24 17:49:37

danorton解决方案不适用于我。我遇到了一些非常奇怪的问题,其中webkit根本不会绘制一些元素。直到onblur才更新输入中的文本;并且更改className不会导致重绘。

我偶然发现的解决方案是在脚本之后在正文中添加一个空的样式元素。

<body>
...
<script>doSomethingThatWebkitWillMessUp();</script>
<style></style>
...

这样就解决了。那有多奇怪?希望这对某人有帮助。