Ich habe etwas triviales JavaScript, um eine Stiländerung zu bewirken:
sel = document.getElementById('my_id');
sel.className = sel.className.replace(/item-[1-9]-selected/,'item-1-selected');
return false;
Dies funktioniert gut mit den neuesten Versionen von FF, Opera und IE, schlägt jedoch bei den neuesten Versionen von Chrome und Safari fehl.
Betroffen sind zwei Nachkommen, die Geschwister sind. Das erste Geschwister wird aktualisiert, das zweite jedoch nicht. Ein untergeordnetes Element des zweiten Elements hat ebenfalls den Fokus und enthält den Tag <a> , der den oben genannten Code in einem onclick -Attribut enthält.
Wenn Sie im Chrome-Fenster „Developer Tools“ das Element any des Elements any anstoßen (z. B. deaktivieren und das Kontrollkästchen deaktivieren), wird das zweite Geschwister auf den korrekten Stil aktualisiert.
Gibt es eine Problemumgehung, um das WebKit einfach und programmatisch dazu zu bewegen, das Richtige zu tun?
Ich habe einige komplizierte Vorschläge gefunden und viele einfache, die nicht funktionierten, aber ein Kommentar von Vasil Dinkov bot eine einfache Lösung zum Erzwingen eines erneuten Zeichnens, das gut funktioniert:
sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display='';
Ich lasse eine andere Person kommentieren, wenn dies für andere Stile als „Block“ funktioniert.
Danke, Vasil!
Wir sind vor kurzem auf dieses Problem gestoßen und haben festgestellt, dass das Problem durch das Befördern des betroffenen Elements auf eine Verbundschicht mit translateZ in CSS behoben wurde, ohne dass zusätzliches JavaScript benötigt wurde.
.willnotrender {
transform: translateZ(0);
}
Da diese Malprobleme hauptsächlich in Webkit/Blink angezeigt werden und dieses Update hauptsächlich auf Webkit/Blink abzielt, ist dies in manchen Fällen zu bevorzugen. Zumal die akzeptierte Antwort fast sicher zu einem reflow führt und repaint , not nur ein Repaint ist.
Webkit und Blink haben hart an der Rendering-Performance gearbeitet, und diese Art von Störungen sind der ungünstige Nebeneffekt von Optimierungen, die darauf abzielen, unnötige Flüsse und Farben zu reduzieren. CSS wird sich ändern oder eine andere nachfolgende Spezifikation wird höchstwahrscheinlich die zukünftige Lösung sein.
Es gibt andere Möglichkeiten, eine Verbundschicht zu erhalten, dies ist jedoch die häufigste.
die Lösung von Danorton hat bei mir nicht funktioniert. Ich hatte einige wirklich seltsame Probleme, bei denen das Webkit überhaupt keine Elemente zeichnete. Der Text in den Eingaben wurde erst bei Onblur aktualisiert. und das Ändern von className würde nicht zu einem Neuzeichnen führen.
Ich habe zufällig entdeckt, dass ich nach dem Skript ein leeres Stilelement in den Hauptteil einfügen wollte.
<body>
...
<script>doSomethingThatWebkitWillMessUp();</script>
<style></style>
...
Das hat es behoben. Wie komisch ist das? Hoffe, das ist für jemanden hilfreich.
Da der Display + Offset-Trigger für mich nicht funktionierte, habe ich hier eine Lösung gefunden:
http://mir.aculo.us/2009/09/25/force-redraw-dom-technique-for-webkit-based-browsers/
d.h.
element.style.webkitTransform = 'scale(1)';
Ich hatte das gleiche Problem. danortons "toggling display" -update funktionierte für mich, als ich die schrittfunktion meiner animation hinzufügte, aber ich war besorgt über die performance und suchte nach anderen möglichkeiten.
In meinem Fall befand sich das Element, das nicht neu gestrichen wurde, innerhalb eines absoluten Positionselements, das zu der Zeit keinen Z-Index hatte. Durch Hinzufügen eines Z-Index zu diesem Element wurde das Verhalten von Chrome geändert, und Repaints erfolgten wie erwartet -> Animationen wurden glatter.
Ich bezweifle, dass dies ein Allheilmittel ist. Ich kann mir vorstellen, dass es davon abhängt , warum Chrome das Element nicht neu gezeichnet hat, aber ich poste diese spezifische Lösung hier in der Hilfe, die es jemandem erhofft.
Prost, Rob
tl; dr >> Versuchen Sie, dem Element oder einem übergeordneten Element einen Z-Index hinzuzufügen.
Die folgenden Arbeiten In reinem CSS muss es nur einmal gesetzt werden. Und es arbeitet zuverlässiger als eine JS-Funktion. Leistung scheint nicht betroffen zu sein.
@-webkit-keyframes androidBugfix {from { padding: 0; } to { padding: 0; }}
body { -webkit-animation: androidBugfix infinite 1s; }
Aus irgendeinem Grund konnte ich nicht die Antwort von danorton zur Arbeit bekommen, ich konnte sehen, was es tun sollte, also habe ich es ein bisschen angepasst:
$('#foo').css('display', 'none').height();
$('#foo').css('display', 'block');
und es hat für mich funktioniert.
Ich bin hier hergekommen, weil ich nach dem Ändern der CSS-Funktion Bildlaufleisten in Chrome neu zeichnen musste.
Wenn jemand dasselbe Problem hat, habe ich es gelöst, indem ich diese Funktion aufgerufen habe:
//Hack to force scroll redraw
function scrollReDraw() {
$('body').css('overflow', 'hidden').height();
$('body').css('overflow', 'auto');
}
Diese Methode ist nicht die beste Lösung, kann aber mit allem funktionieren. Das Ausblenden und Anzeigen des Elements, das neu gezeichnet werden muss, kann jedes Problem lösen.
Hier ist die Geige, wo ich sie benutzt habe: http://jsfiddle.net/promatik/wZwJz/18/
Ich bin heute darauf gestoßen: Element.redraw () für prototype.js
Mit:
Element.addMethods({
redraw: function(element){
element = $(element);
var n = document.createTextNode(' ');
element.appendChild(n);
(function(){n.parentNode.removeChild(n)}).defer();
return element;
}
});
Ich habe jedoch manchmal bemerkt, dass Sie redraw () für das problematische Element direkt aufrufen müssen. Manchmal löst das Neuzeichnen des übergeordneten Elements das Problem, das das Kind hat, nicht.
Guter Artikel über die Art und Weise, wie Browser Elemente rendern: Rendern: Neuzeichnen, Reflow/Relayout, Restyle
Ich kann nicht glauben, dass dies 2014 immer noch ein Problem ist. Ich hatte gerade dieses Problem, als ich beim Scrollen ein Untertitelfeld mit fester Position in der linken unteren Seite der Seite aktualisiert habe. Nachdem ich alles zuvor ohne Erfolg ausprobiert hatte, bemerkte ich, dass viele Dinge entweder langsam waren oder Probleme verursachten, weil sehr kurze DOM-Relayouts usw. erstellt wurden, was zu einem unnatürlichen Gefühl beim Scrollen usw. führte.
Am Ende machte ich mit pointer-events: none
eine feste Position, ein Full-Size-Div, und wendete danortons Antwort auf dieses Element an, das ein Neuzeichnen auf dem gesamten Bildschirm zu erzwingen scheint, ohne das DOM zu beeinträchtigen.
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';
Ich hatte dieses Problem mit einer Anzahl von divs, die mit position: absolute
in ein anderes div eingefügt wurden. Die eingefügten divs hatten kein Positionsattribut. Als ich dies in position:relative
änderte, hat es gut funktioniert. (war wirklich schwer das Problem zu lokalisieren)
In meinem Fall wurden die Elemente von Angular mit ng-repeat
eingefügt.
Nicht, dass diese Frage eine andere Antwort erfordert, aber ich fand es einfach, die Farbe durch ein einziges Bit zu ändern, was zu einem Neulackieren in meiner speziellen Situation führte.
//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);
Die Variable setTimeout
erwies sich als entscheidend, um die zweite Stiländerung außerhalb der aktuellen Ereignisschleife zu verschieben.
Die einzige Lösung, die für mich funktioniert, ist der Antwort von sowasred2012 ähnlich:
$('body').css('display', 'table').height();
$('body').css('display', 'block');
Ich habe viele Problemblöcke auf der Seite, daher ändere ich die display
-Eigenschaft des Wurzelelements ..__ und benutze display: table;
anstelle von display: none;
, da none
den Scroll-Offset zurücksetzt.
Da jeder scheint, seine eigenen Probleme und Lösungen zu haben, dachte ich, ich würde etwas hinzufügen, das für mich funktioniert. Unter Android 4.1 mit aktuellem Chrome wurde versucht, eine Leinwand innerhalb eines Div mit Overflow zu ziehen: Versteckt, ich konnte keine Neuzeichnung erstellen, es sei denn, ich habe dem übergeordneten Div ein Element hinzugefügt (bei dem es keinen Schaden anrichtete).
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);
}
Kein Bildschirmflackern oder echtes Update und das Aufräumen nach mir. Keine globalen oder Klassenvariablen, nur lokale. Scheint auf Mobile Safari/iPad oder Desktop-Browsern nichts zu schaden.
Ich arbeite an einer ionischen html5-App, auf einigen Bildschirmen habe ich absolute
positioniertes Element. Wenn Sie in IOS - Geräten (iPhone 4,5,6, 6+) nach oben oder unten scrollen, hatte ich einen Repaint-Fehler.
Habe viele Lösungen ausprobiert, aber keiner von ihnen funktionierte, außer dieser löste mein Problem.
Ich habe die css-Klasse .fixRepaint
für diese absoluten Positionselemente verwendet
.fixRepaint{
transform: translateZ(0);
}
Dies hat mein Problem behoben, es kann jemandem helfen
Ich habe festgestellt, dass durch das Hinzufügen eines Inhaltsstils zu dem Element eine Neulackierung erzwungen wurde. Dies sollte jedes Mal ein anderer Wert sein, wenn Sie möchten, dass es neu gezeichnet wird, und es muss sich nicht auf einem Pseudoelement befinden.
.selector {
content: '1'
}
Ich hatte ein Problem mit einer SVG, die unter Chrome für Android verschwand, als die Ausrichtung unter bestimmten Umständen geändert wurde. Der folgende Code reproduziert es nicht, aber es ist das Setup, das wir hatten.
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>
Nach anderthalb Jahren, nachdem ich gestoßen und angestoßen hatte und mit den hier angebotenen hacky -Lösungen nicht zufrieden war, entdeckte ich, dass das Problem auf die Tatsache zurückzuführen war, dass es das Element im Gedächtnis zu halten schien, während ein neues gezeichnet wurde. Die Lösung bestand darin, die ID des linearGradient in der SVG eindeutig zu machen, obwohl sie nur einmal pro Seite verwendet wurde.
Dies kann auf viele verschiedene Arten erreicht werden, aber für unsere Winkel-App verwendeten wir die lodash uniqueId-Funktion, um eine Variable zum Gültigkeitsbereich hinzuzufügen:
Winkelrichtlinie (JS):
scope.indicatorColourPatternId = _.uniqueId('IndicatorColourPattern');
HTML-Updates:
Zeile 5: <linearGradient ng-attr-id="{{indicatorColourPatternId}}" x1="0" x2="0" y1="0" y2="1">
Zeile 11: <rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" ng-attr-fill="url(#{{indicatorColourPatternId}})"/>
Ich hoffe, diese Antwort erspart jemandem ein paar Tage, wenn es darum geht, die Tastatur zu zerschlagen.
die obigen Vorschläge haben für mich nicht funktioniert. aber das tut man unten.
Sie möchten den Text im Anker dynamisch ändern. Das Wort "Suche". Erstellt ein inneres Tag "font" mit einem id-Attribut. Verwaltete den Inhalt mit Javascript (unten)
Suche
skriptinhalt:
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);
}
Ich verwende die Methode transform: translateZ(0);
, aber in einigen Fällen reicht es nicht aus.
Ich bin kein Fan des Hinzufügens und Entfernens einer Klasse, also habe ich versucht, einen Weg zu finden, um dieses Problem zu lösen, und bin zu einem neuen Hack gekommen, der gut funktioniert:
@keyframes redraw{
0% {opacity: 1;}
100% {opacity: .99;}
}
// ios redraw fix
animation: redraw 1s linear infinite;
Dies scheint damit zu zusammenhängen: Der jQuery-Stil wird in Safari nicht angewendet
Die in der ersten Antwort vorgeschlagene Lösung hat für mich in diesen Szenarien gut funktioniert, und zwar: Anwenden und Entfernen einer Dummy-Klasse auf den Körper, nachdem die Stiländerungen vorgenommen wurden:
$('body').addClass('dummyclass').removeClass('dummyclass');
Dies zwingt die Safari zum Neuzeichnen.
Ich habe festgestellt, dass diese Methode nützlich ist, wenn Sie mit Übergängen arbeiten
$element[0].style.display = 'table';
$element[0].offsetWidth; // force reflow
$element.one($.support.transition.end, function () {
$element[0].style.display = 'block';
});
Das ist gut für JS
sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display='block';
Aber in Jquery und insbesondere, wenn Sie $ (document) .ready nur verwenden können und aus einem bestimmten Grund nicht an das .load-Ereignis eines Objekts gebunden werden können, wird Folgendes funktionieren.
Sie müssen den OUTER (MOST) -Container der Objekte/divs abrufen und dann den gesamten Inhalt in einer Variablen entfernen und dann erneut hinzufügen .. _ Dadurch werden ALLE Änderungen im äußeren Container sichtbar.
$(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);
}
Ich habe versucht, eine neue Antwort zu finden, aber es funktioniert nicht für mich ... Ich hatte Probleme, dieselbe clientWidth mit Safari zu haben, die mit anderen Browsern verglichen wurde, und dieser Code hat das Problem gelöst:
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})
Es ist wirklich seltsam, denn wenn ich erneut versuche, die clientWidth nach get_safe_value zu bekommen, erhalte ich mit safari einen schlechten Wert. Der Getter muss zwischen sty.transform = "translateZ(1px)";
.__ liegen. und sty.transform = "";
Die andere Lösung, die definitiv funktioniert, ist
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
Das Problem ist, dass Sie den Fokus- und Bildlaufstatus verlieren.
der "display/offsetHeight" -Hack funktionierte in meinem Fall nicht, zumindest wenn er auf das animierte Element angewendet wurde.
ich hatte ein Dropdown-Menü, das über den Seiteninhalt geöffnet/geschlossen wurde. Die Artefakte wurden nach dem Schließen des Menüs auf dem Seiteninhalt verbleiben (nur in Webkit-Browsern). Der "display/offsetHeight" -Hack funktionierte nur, wenn ich ihn auf den Körper anwendete, was unangenehm erscheint.
ich habe jedoch eine andere Lösung gefunden:
dies ist immer noch ziemlich hackig (es verwendet eine CSS3-Eigenschaft, um das Hardware-Rendering zu erzwingen), aber es wirkt sich immer nur auf das betreffende Element aus und arbeitete für mich sowohl auf Safari als auch auf Chrome auf PC und Mac.
Ich würde eine weniger hackhafte und formalere Methode empfehlen, um einen Reflow zu erzwingen: use forceDOMReflowJS . In Ihrem Fall würde Ihr Code folgendermaßen aussehen.
sel = document.getElementById('my_id');
forceReflowJS( sel );
return false;