Donec et eros nibh。没有门,精英如箭,pulvinar 湖,augue loborti mauris,但没有医疗保健精英。酱汁在餐厅里。只要是环保的,航空公司就得付费。但骨灰盒的元素是未来的利益。 Curabitur 悲伤的 orci 和 ligula 有时,eu 酱恐惧 eleifend。对于免费宣传,最大的颤抖,是兽人的华丽投资。他还需要孩子,那是成员。脸上露出灿烂的笑容,但粉丝和妆容紧随其后的是仇恨。但互联网不限制时间或欢笑。
我有一些简单的 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 属性中包含上述代码。
在 Chrome 的“开发者工具”窗口中,如果我轻推(例如取消选中和选中)任何元素的任何属性,第二个兄弟姐妹将更新为正确的样式。
是否有一种解决方法可以轻松地以编程方式“推动”WebKit 做正确的事情?
我发现了一些复杂的建议和许多不起作用的简单建议,但 Vasil Dinkov 对其中一个的评论提供了一个简单的解决方案来强制重绘/重绘,效果很好:
sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display='';
如果它适用于“块”以外的样式,我会让其他人评论。
谢谢,瓦西尔!
我们最近遇到了这个问题,发现在 CSS 中使用 translateZ 将受影响的元素提升为 composite layer 可以解决问题,而无需额外的 JavaScript。
.willnotrender {
transform: translateZ(0);
}
由于这些绘画问题主要出现在 Webkit/Blink 中,并且此修复主要针对 Webkit/Blink,因此在某些情况下更可取。特别是因为接受的答案几乎肯定会导致 reflow and repaint,不只是重绘。
Webkit 和 Blink 一直在努力提高渲染性能,而这些故障是旨在减少不必要的流量和绘制的优化的不幸副作用。 CSS will-change 或其他后续规范很可能是未来的解决方案。
还有其他方法可以实现复合层,但这是最常见的。
danorton 解决方案对我不起作用。我遇到了一些非常奇怪的问题,webkit 根本不会绘制一些元素;输入中的文本直到 onblur 才更新;并且更改 className 不会导致重绘。
我偶然发现,我的解决方案是在脚本之后在正文中添加一个空样式元素。
<body>
...
<script>doSomethingThatWebkitWillMessUp();</script>
<style></style>
...
那解决了它。这有多奇怪?希望这对某人有帮助。
var div = $('<div>').appendTo(element); setTimeout(function(){ div.remove(); }, 0);
$('<style></style>').appendTo($(document.body)).remove();
由于显示+偏移触发器对我不起作用,我在这里找到了解决方案:
http://mir.aculo.us/2009/09/25/force-redraw-dom-technique-for-webkit-based-browsers/
IE
element.style.webkitTransform = 'scale(1)';
scale(1)
分配给自己,而是将其分配给自己作为 element.style.webkitTransform = element.style.webkitTransform
。这样做的原因是,将其设置为前者会使页面略微扭曲absolute
定位元素!
display
解决方案那样闪烁或重置滚动位置的问题。
我遇到了同样的问题。 danorton 的“切换显示”修复在添加到我的动画的步进函数时确实对我有用,但我担心性能,我寻找其他选项。
在我的情况下,未重新绘制的元素位于绝对位置元素中,当时该元素没有 z-index。向该元素添加 z-index 改变了 Chrome 的行为,并且重绘按预期发生 -> 动画变得流畅。
我怀疑这是灵丹妙药,我想这取决于 Chrome 选择不重绘元素的原因,但我在这里发布这个特定的解决方案是为了希望有人帮助。
干杯,罗伯
tl;dr >> 尝试向元素或其父元素添加 z-index。
以下作品。它只需要在纯 CSS 中设置一次。而且它比 JS 函数更可靠。性能似乎不受影响。
@-webkit-keyframes androidBugfix {from { padding: 0; } to { padding: 0; }}
body { -webkit-animation: androidBugfix infinite 1s; }
zoom
而不是填充:@-webkit-keyframes safariBugFix {from { zoom: 100%; } to { zoom: 99.99999%; }}
出于某种原因,我无法得到 danorton 的工作答案,我可以看到它应该做什么,所以我对其进行了一些调整:
$('#foo').css('display', 'none').height();
$('#foo').css('display', 'block');
它对我有用。
我来到这里是因为我需要在更改其 css 后在 Chrome 中重绘滚动条。
如果有人遇到同样的问题,我通过调用这个函数来解决它:
//Hack to force scroll redraw
function scrollReDraw() {
$('body').css('overflow', 'hidden').height();
$('body').css('overflow', 'auto');
}
这种方法不是最好的解决方案,但它可能适用于所有问题,隐藏和显示需要重绘的元素可能会解决所有问题。
这是我使用它的小提琴:http://jsfiddle.net/promatik/wZwJz/18/
我今天偶然发现了这个:Element.redraw() for prototype.js
使用:
Element.addMethods({
redraw: function(element){
element = $(element);
var n = document.createTextNode(' ');
element.appendChild(n);
(function(){n.parentNode.removeChild(n)}).defer();
return element;
}
});
但是,我有时注意到您必须直接在有问题的元素上调用 redraw()。有时重绘父元素并不能解决孩子遇到的问题。
关于浏览器呈现元素方式的好文章:Rendering: repaint, reflow/relayout, restyle
appendChild
是 DOM 方法,而不是 jQuery 方法。
我在使用 position: absolute
插入另一个 div 的多个 div 中遇到了这个问题,插入的 div 没有位置属性。当我将其更改为 position:relative
时,它工作正常。 (真的很难查明问题)
在我的例子中,Angular 使用 ng-repeat
插入的元素。
我不敢相信这在 2014 年仍然是一个问题。我刚刚在滚动时刷新页面左下角的固定位置标题框时遇到了这个问题,标题会在屏幕上“重影”。在尝试上述所有操作均未成功后,我注意到很多事情要么缓慢/导致问题,因为创建非常短的 DOM 重新布局等导致滚动感觉有些不自然等......
我最终用 pointer-events: none
制作了一个固定位置的全尺寸 div 并将 danorton 的答案应用于该元素,这似乎强制在整个屏幕上重绘而不干扰 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';
z-index
和 pointer-events
规则在这里是多余的。
并不是说这个问题需要另一个答案,但我发现在我的特定情况下只需改变一点颜色就会强制重新绘制。
//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
被证明对于将第二个样式更改移到当前事件循环之外至关重要。
我使用 transform: translateZ(0);
方法,但在某些情况下它还不够。
我不喜欢添加和删除一个类,所以我试图找到解决这个问题的方法,最终得到了一个效果很好的新技巧:
@keyframes redraw{
0% {opacity: 1;}
100% {opacity: .99;}
}
// ios redraw fix
animation: redraw 1s linear infinite;
唯一对我有用的解决方案类似于 sowasred2012 的回答:
$('body').css('display', 'table').height();
$('body').css('display', 'block');
我在页面上有很多问题块,所以我更改了根元素的 display
属性。我使用 display: table;
而不是 display: none;
,因为 none
将重置滚动偏移量。
由于每个人似乎都有自己的问题和解决方案,我想我会添加一些对我有用的东西。在具有当前 Chrome 的 Android 4.1 上,尝试在具有溢出:隐藏的 div 内拖动画布,除非我向父 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);
}
没有屏幕闪烁或真正的更新,并自行清理。没有全局或类范围的变量,只有局部变量。似乎对移动 Safari/iPad 或桌面浏览器没有任何影响。
我正在开发 ionic html5 应用程序,在几个屏幕上我有 absolute
定位元素,当在 IOS 设备(iPhone 4、5、6、6+)中向上或向下滚动时,我有重绘错误。
尝试了很多解决方案,除了这个解决了我的问题,没有一个有效。
我在这些绝对位置元素上使用了 css 类 .fixRepaint
.fixRepaint{
transform: translateZ(0);
}
这已经解决了我的问题,它可能会帮助一些人
这个答案适用于那些使用 Angular 10 为@danorton 的解决方案而苦苦挣扎的人。这个解决方案
sel.style.display='none';
sel.offsetHeight;
sel.style.display='';
仅适用于 angular.json
文件中的 "buildOptimizer": false
。看起来优化器以某种方式打破了这一点。
这对 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 事件时,以下方法将起作用。
您需要获取对象/div 的 OUTER(MOST) 容器,然后将其所有内容删除到变量中,然后重新添加它。它将使外部容器内完成的所有更改可见。
$(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” hack 在我的情况下不起作用,至少当它应用于动画元素时。
我有一个在页面内容上打开/关闭的下拉菜单。菜单关闭后,工件留在页面内容上(仅在 webkit 浏览器中)。 “display/offsetHeight”破解的唯一方法是如果我将它应用到身体上,这看起来很讨厌。
但是,我确实找到了另一种解决方案:
在元素开始动画之前,添加一个定义“-webkit-backface-visibility: hidden;”的类在元素上(你也可以使用内联样式,我猜)当它完成动画时,删除类(或样式)
这仍然很老套(它使用 CSS3 属性来强制硬件渲染),但至少它只影响有问题的元素,并且在 PC 和 Mac 上的 safari 和 chrome 上都为我工作。
这似乎与此有关:jQuery style not being applied in Safari
第一个响应中建议的解决方案在这些情况下对我来说效果很好,即:在进行样式更改后将虚拟类应用和删除到正文:
$('body').addClass('dummyclass').removeClass('dummyclass');
这迫使 safari 重新绘制。
以上建议对我不起作用。但下面的一个。
想要动态更改锚点内的文本。 “搜索”一词。创建了一个带有 id 属性的内部标签“font”。使用 javascript 管理内容(下)
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);
}
当在某些情况下更改方向时,我遇到了一个 SVG 在 Chrome for Android 上消失的问题。下面的代码不会重现它,而是我们的设置。
正文 {字体系列:tahoma,无衬线;字体大小:12px;边距:10px; } 文章 { 显示:弹性; } 一边 { flex: 0 1 10px;右边距:10px;最小宽度:10px;位置:相对; } SVG { 底部:0;左:0;立场:绝对;右:0;顶部:0; } .backgroundStop1 { 停止颜色:#5bb79e; } .backgroundStop2 { 停止颜色:#ddcb3f; } .backgroundStop3 { 停止颜色:#cf6b19; } Donec et eros nibh。没有门,精英如箭,pulvinar 湖,augue loborti mauris,但没有医疗保健精英。酱汁在餐厅里。只要是环保的,航空公司就得付费。但骨灰盒的元素是未来的利益。 Curabitur 悲伤的 orci 和 ligula 有时,eu 酱恐惧 eleifend。对于免费宣传,最大的颤抖,是兽人的华丽投资。他还需要孩子,那是成员。脸上露出灿烂的笑容,但粉丝和妆容紧随其后的是仇恨。但互联网不限制时间或欢笑。
一天半后,在戳戳和刺激并且对这里提供的 hacky 解决方案不满意后,我发现问题是由于它似乎在绘制新元素时将元素保留在内存中。解决方案是使 SVG 上的 linearGradient 的 ID 唯一,即使每页只使用一次。
这可以通过许多不同的方式实现,但是对于我们的 Angular 应用程序,我们使用 lodash uniqueId 函数将变量添加到范围:
角度指令(JS):
scope.indicatorColourPatternId = _.uniqueId('IndicatorColourPattern');
HTML 更新:
第 5 行:<linearGradient ng-attr-id="{{indicatorColourPatternId}}" x1="0" x2="0" y1="0" y2="1">
第 11 行:<rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" ng-attr-fill="url(#{{indicatorColourPatternId}})"/>
我希望这个答案可以为其他人节省一天的时间来砸他们的键盘。
我会推荐一种不那么生硬和更正式的方式来强制回流:使用 forceDOMReflowJS。在您的情况下,您的代码如下所示。
sel = document.getElementById('my_id');
forceReflowJS( sel );
return false;
我发现只是向元素添加内容样式会强制它重新绘制,每次你希望它重新绘制时这应该是一个不同的值,并且不需要在伪元素上。
.selector {
content: '1'
}
我尝试了更多的答案,但它对我不起作用。与其他浏览器相比,我在 Safari 中使用相同的 clientWidth 时遇到了麻烦,这段代码解决了这个问题:
var get_safe_value = function(elm,callback){
var sty = elm.style
sty.transform = "translateZ(1px)";
var ret = callback(elm)//you can get here the value you want
sty.transform = "";
return ret
}
// for safari to have the good clientWidth
var $fBody = document.body //the element you need to fix
var clientW = get_safe_value($fBody,function(elm){return $fBody.clientWidth})
这真的很奇怪,因为如果我在 get_safe_value 之后再次尝试获取 clientWidth,我会在 safari 中获得一个错误的值,getter 必须在 sty.transform = "translateZ(1px)";
和 sty.transform = "";
之间
另一个明确有效的解决方案是
var $fBody = document.body //the element you need to fix
$fBody.style.display = 'none';
var temp = $.body.offsetHeight;
$fBody.style.display = ""
temp = $.body.offsetHeight;
var clientW = $fBody.clientWidth
问题是您失去焦点和滚动状态。
这将强制重绘,同时避免闪烁、现有元素修补和任何布局问题......
function forceRepaint() {
requestAnimationFrame(()=>{
const e=document.createElement('DIV');
e.style='position:fixed;top:0;left:0;bottom:0;right:0;background:#80808001;\
pointer-events:none;z-index:9999999';
document.body.appendChild(e);
requestAnimationFrame(()=>e.remove());
});
}
此代码将重新渲染 css
document.body.style.display = 'flex';
setTimeout(() => (document.body.style.display = ''), 0);
将转换 CSS 设置为 scale(0.9999)
显然适用于最新的 chrome。
function redraw(node){
// Adjust the 200 as fastest as you can
// or, change the setTimeout to requestAnimationFrame as soon as the element
// is drawn
setTimeout(() => (node.style.transform = "scale(0.9999)"), 200);
}
我发现 @morewry 的 excellent answer 解决了我的问题,而且 will-change
属性从那以后就到了。
CSS will-change 或其他后续规范很可能是未来的解决方案。
就我而言,仅 will-change: transform;
的值在 Safari 14 中有效。
.wont-update {
will-change: transform;
/* for Safari < 9.1 */
transform: translateZ(0);
}
https://developer.mozilla.org/en-US/docs/Web/CSS/will-change
https://caniuse.com/will-change
'inline-block'
、'table'
或'run-in'
而不是'none'
,但这可能会产生副作用。此外,超时 0 会触发重排,就像查询offsetHeight
所做的那样:sel.style.display = 'run-in'; setTimeout(function () { sel.style.display = 'block'; }, 0);