强制 DOM 在 Chrome/Mac 上重绘/刷新

2022-08-30 00:38:47

每隔一段时间,Chrome就会错误地呈现完全有效的HTML / CSS或根本不呈现。通过DOM检查器进行挖掘通常足以使其意识到其方式的错误并正确重绘,因此可以证明标记是好的。在我正在处理的项目中,这种情况经常发生(并且可以预测),以至于我已经将代码放在适当的位置,以便在某些情况下强制重绘。

这适用于大多数浏览器/操作系统组合:

    el.style.cssText += ';-webkit-transform:rotateZ(0deg)'
    el.offsetHeight
    el.style.cssText += ';-webkit-transform:none'

例如,调整一些未使用的CSS属性,然后询问一些强制重绘的信息,然后取消该属性。不幸的是,Chrome for mac背后的聪明团队似乎已经找到了一种方法来获得这种偏移量,而无需重绘。从而杀死一个本来有用的黑客。

到目前为止,我想出的在Chrome / Mac上获得相同效果的最好的方法是这个丑陋:

    $(el).css("border", "solid 1px transparent");
    setTimeout(function()
    {
        $(el).css("border", "solid 0px transparent");
    }, 1000);

就像在,实际上迫使元素跳跃一点,然后冷却一秒钟并将其跳回去。更糟糕的是,如果您将超时时间降至500ms以下(到不太明显的位置),它通常不会产生预期的效果,因为浏览器在返回其原始状态之前不会重新绘制。

有没有人关心提供在Chrome / Mac上运行的此重绘/刷新黑客的更好版本(最好基于上面的第一个示例)?


答案 1

不确定您到底想实现什么,但这是我过去成功使用的方法,迫使浏览器重新绘制,也许它会对您有用。

// in jquery
$('#parentOfElementToBeRedrawn').hide().show(0);

// in plain js
document.getElementById('parentOfElementToBeRedrawn').style.display = 'none';
document.getElementById('parentOfElementToBeRedrawn').style.display = 'block';

如果这个简单的重绘不起作用,你可以试试这个。它将一个空文本节点插入元素中,从而保证重绘。

var forceRedraw = function(element){

    if (!element) { return; }

    var n = document.createTextNode(' ');
    var disp = element.style.display;  // don't worry about previous display style

    element.appendChild(n);
    element.style.display = 'none';

    setTimeout(function(){
        element.style.display = disp;
        n.parentNode.removeChild(n);
    },20); // you can play with this timeout to make it as short as possible
}

编辑:作为对Šime Vidas的回应,我们在这里实现的将是强制回流。你可以从大师本人那里找到更多 http://paulirish.com/2011/dom-html5-css3-performance/


答案 2

以上答案都不适合我。我确实注意到调整窗口大小确实会导致重绘。所以这为我做到了:

$(window).trigger('resize');