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

我有一些微不足道的JavaScript来改变风格:

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

这与FF,Opera和IE的最新版本正常工作,但最新版本的Chrome和Safari失败。

它影响到两个后代,这是兄弟姐妹。 第一个兄弟更新,但第二个没有。 第二个元素的子元素也具有焦点,并包含onclick属性中包含上述代码的<a>标记。

在Chrome“开发工具”窗口中,如果我推动(例如取消选中并检查) 任何元素的任何属性,则第二个兄弟更新为正确的样式。

有没有一种解决方法可以轻松地以编程方式“推”WebKit做正确的事情?

我发现了一些复杂的build议和很多简单的build议,但是Vasil Dinkov对其中一个人的评论提供了一个简单的解决scheme来强制重绘/重绘,这很好:

 sel.style.display='none'; sel.offsetHeight; // no need to store this anywhere, the reference is enough sel.style.display=''; 

我会让其他人评论,如果它适用于“块”以外的样式。

谢谢,Vasil!

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

 .willnotrender { transform: translateZ(0); } 

由于这些绘画问题主要在Webkit / Blink中出现,而且此修补程序主要针对Webkit / Blink,所以在某些情况下更可取。 特别是因为接受的答案几乎肯定会导致回stream和重漆 , 不仅仅是重漆。

Webkit和Blink一直在努力提高性能,而这些小故障是优化的不幸副作用,旨在减less不必要的stream量和颜料。 CSS将会改变或者其他成功的规范将成为未来的解决scheme。

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

丹顿解决scheme不适合我。 我有一些非常奇怪的问题,webkit根本不会画出一些元素。 input文字在onblur之前没有更新; 并改变className不会导致重绘。

我意外地发现,我的解决scheme是在脚本之后添加一个空的样式元素。

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

这固定它。 这有多奇怪? 希望这对某人有帮助。

由于显示器+偏移触发器不适合我,我在这里find了一个解决scheme:

http://mir.aculo.us/2009/09/25/force-redraw-dom-technique-for-webkit-based-browsers/

 element.style.webkitTransform = 'scale(1)'; 

我遇到了同样的问题。 当添加到我的animation的阶梯function时,danorton的“切换显示”修复function对我来说是有效的,但是我担心性能,我寻找其他选项。

在我的情况下,没有重绘的元素是在一个绝对的位置元素,当时没有一个Z-索引。 给这个元素添加一个z-index改变了Chrome的行为,并按预期发生了重绘 – >animation变得平滑。

我怀疑这是一个万能的,我想这取决于为什么 Chromeselect不重绘的元素,但我发布这个具体的解决scheme在这里帮助它希望有人。

干杯,罗伯

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

以下的作品。 它只需要在纯CSS中设置一次。 它比JSfunction更可靠。 性能似乎不受影响。

 @-webkit-keyframes androidBugfix {from { padding: 0; } to { padding: 0; }} body { -webkit-animation: androidBugfix infinite 1s; } 

出于某种原因,我不能得到丹顿的工作答案,我可以看到它应该做什么,所以我调整了一点这个:

 $('#foo').css('display', 'none').height(); $('#foo').css('display', 'block'); 

它为我工作。

我今天偶然发现了: 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()来处理有问题的元素。 有时重绘父元素不会解决孩子正在经历的问题。

关于浏览器呈现元素的方式的好文章: 渲染:重绘,回stream/重新布局,restyle

我来到这里,因为我需要改变其CSS后重新滚动滚动条。

如果有人有同样的问题,我通过调用这个函数来解决它:

 //Hack to force scroll redraw function scrollReDraw() { $('body').css('overflow', 'hidden').height(); $('body').css('overflow', 'auto'); } 

这种方法并不是最好的解决scheme,但它可以与所有的东西一起工作,隐藏和显示需要重绘的元素可以解决所有问题。

这里是我用它的小提琴: http : //jsfiddle.net/promatik/wZwJz/18/

我有这样的问题与插入到另一个div中的position: absolute插入的div没有位置属性的一些div。 当我改变这个position:relative它工作正常。 (真的很难指出问题)

在我的情况下,由ng-repeat插入Angular的元素。

这并不是说这个问题需要另外一个答案,但是我发现仅仅通过一点点改变颜色就可以在我的特定情况下重绘。

 //Assuming black is the starting color, we tweak it by a single bit elem.style.color = '#000001'; //Change back to black setTimeout(function() { elem.style.color = '#000000'; }, 0); 

setTimeout对于将当前事件循环之外的第二个样式变化移动至关重要。

我不能相信这在2014年仍然是一个问题。我只是在滚动页面左下方刷新一个固定的位置标题框的时候遇到了这个问题,标题会在屏幕上“虚晃”。 在尝试了一切之后没有成功,我注意到很多事情要么慢/造成问题,因为创build非常短的DOM推广等等造成有点不自然的感觉滚动等…

我最终做了一个固定的位置,全尺寸的div与pointer-events: none并应用丹顿的答案,这似乎强制重新整个屏幕上,而不会干扰的DOM。

HTML:

 <div id="redraw-fix"></div> 

CSS:

 div#redraw-fix { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 25; pointer-events: none; display: block; } 

JS:

 sel = document.getElementById('redraw-fix'); sel.style.display='none'; sel.offsetHeight; // no need to store this anywhere, the reference is enough sel.style.display='block'; 

唯一的解决scheme对我来说是类似于sowasred2012的答案:

 $('body').css('display', 'table').height(); $('body').css('display', 'block'); 

页面上有很多问题块,所以我改变了根元素的display属性。 我使用display: table; 而不是display: none; ,因为none会重置滚动偏移量。

由于每个人似乎都有自己的问题和解决scheme,我想我会添加一些适合我的东西。 在Android 4.1上使用当前的Chrome浏览器,试图拖放一个canvas,在溢出:隐藏,我不能重绘,除非我添加一个元素到父div(不会有任何伤害)。

 var parelt = document.getElementById("parentid"); var remElt = document.getElementById("removeMe"); var addElt = document.createElement("div"); addElt.innerHTML = " "; // Won't work if empty addElt.id="removeMe"; if (remElt) { parelt.replaceChild(addElt, remElt); } else { parelt.appendChild(addElt); } 

没有屏幕闪烁或真正的更新,并自己清理。 没有全局或类范围的variables,只有当地人。 移动Safari / iPad或桌面浏览器似乎没有受到任何伤害。

这对JS很好

 sel.style.display='none'; sel.offsetHeight; // no need to store this anywhere, the reference is enough sel.style.display='block'; 

但在JQuery中,特别是当你只能使用$(document).ready并且由于某种原因无法绑定到一个对象的.load事件时,下面的工作将会起作用。

您需要获取objects / div的OUTER(MOST)容器,然后将其所有内容移除到variables中,然后重新添加它。 这将使外部容器内的所有更改都可见。

 $(document).ready(function(){ applyStyling(object); var node = $("div#body div.centerContainer form div.centerHorizontal").parent().parent(); var content = node.html(); node.html(""); node.html(content); } 

我发现这个方法在处理转换时很有用

 $element[0].style.display = 'table'; $element[0].offsetWidth; // force reflow $element.one($.support.transition.end, function () { $element[0].style.display = 'block'; }); 

在我的情况下,“display / offsetHeight”破解不起作用,至less当它被应用到animation的元素时。

我有一个正在打开/closures页面内容的下拉菜单。 在菜单closures之后,只有在webkit浏览器中,工件才留在页面内容上。 “display / offsetHeight”破解工作的唯一方法是如果我将它应用到身体,这似乎是讨厌的。

但是,我find了另一个解决scheme:

  1. 在元素启动animation之前,添加一个定义“-webkit-backface-visibility:hidden;”的类 在元素上(你也可以使用内联样式,我猜)
  2. 当它完成animation时,删除类(或样式)

这仍然是非常hacky(它使用CSS3属性来强制硬件渲染),但至less它只影响有问题的元素,并在PC和Mac上的safari和chrome工作。

这似乎与此相关: jQuery风格不适用于Safari

在第一个响应中提出的解决scheme对于我来说在这些情况下运行良好,即:在进行样式更改后,将一个虚拟类应用到主体并将其删除:

 $('body').addClass('dummyclass').removeClass('dummyclass'); 

这迫使Safari浏览器重绘。

以上build议没有为我工作。 但下面的一个呢。

想dynamic地改变锚内的文字。 单词“search”。 创build一个id属性的内部标签“字体”。 使用JavaScriptpipe理内容(下)

search

脚本内容:

  var searchText = "Search"; var editSearchText = "Edit Search"; var currentSearchText = searchText; function doSearch() { if (currentSearchText == searchText) { $('#pSearch').panel('close'); currentSearchText = editSearchText; } else if (currentSearchText == editSearchText) { $('#pSearch').panel('open'); currentSearchText = searchText; } $('#searchtxt').text(currentSearchText); } 

我正在研究离子html5应用程序,在几个屏幕上,我有absolute定位的元素,当在iOS设备(iPhone 4,5,6,6+)向上或向下滚动时,我有重绘错误。

尝试了很多解决scheme,除了这个解决我的问题,他们没有一个正在工作。

我对这些绝对位置元素使用了css类.fixRepaint

 .fixRepaint{ transform: translateZ(0); } 

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

在某些情况下改变方向时,我遇到了在Android版Chrome上消失的SVG问题。 下面的代码不会重现它,但是是我们的设置。

 body { font-family: tahoma, sans-serif; font-size: 12px; margin: 10px; } article { display: flex; } aside { flex: 0 1 10px; margin-right: 10px; min-width: 10px; position: relative; } svg { bottom: 0; left: 0; position: absolute; right: 0; top: 0; } .backgroundStop1 { stop-color: #5bb79e; } .backgroundStop2 { stop-color: #ddcb3f; } .backgroundStop3 { stop-color: #cf6b19; } 
 <article> <aside> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="100%" width="100%"> <defs> <linearGradient id="IndicatorColourPattern" x1="0" x2="0" y1="0" y2="1"> <stop class="backgroundStop1" offset="0%"></stop> <stop class="backgroundStop2" offset="50%"></stop> <stop class="backgroundStop3" offset="100%"></stop> </linearGradient> </defs> <rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" fill="url(#IndicatorColourPattern)"></rect> </svg> </aside> <section> <p>Donec et eros nibh. Nullam porta, elit ut sagittis pulvinar, lacus augue lobortis mauris, sed sollicitudin elit orci non massa. Proin condimentum in nibh sed vestibulum. Donec accumsan fringilla est, porttitor vestibulum dolor ornare id. Sed elementum urna sollicitudin commodo ultricies. Curabitur tristique orci et ligula interdum, eu condimentum metus eleifend. Nam libero augue, pharetra at maximus in, pellentesque imperdiet orci.</p> <p>Fusce commodo ullamcorper ullamcorper. Etiam eget pellentesque quam, id sodales erat. Vestibulum risus magna, efficitur sed nisl et, rutrum consectetur odio. Sed at lorem non ligula consequat tempus vel nec risus.</p> </section> </article> 

一个简单的解决scheme与jQuery的:

 $el.html($el.html()); 

要么

 element.innerHTML = element.innerHTML; 

有一个SVG,当它被添加到HTML时没有显示。

这可以在屏幕上显示svg元素后添加。

更好的解决scheme是使用:

 document.createElementNS('http://www.w3.org/2000/svg', 'svg'); 

和jQuery:

 $(svgDiv).append($(document.createElementNS('http://www.w3.org/2000/svg', 'g')); 

这将在Chrome上正确呈现。