スタイルを変更するための簡単な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の最新バージョンでは失敗します。
それはたまたま兄弟である2人の子孫に影響を及ぼします。最初の兄弟は更新されますが、2番目の兄弟は更新されません。 2番目の要素の子もフォーカスがあり、onclick属性に上記のコードを含む<a>タグが含まれています。
Chromeの「開発者ツール」ウィンドウで(たとえば、チェックマークを外してチェックする)any属性any要素の場合、2番目の兄弟が正しいスタイルに更新されます。
簡単にそしてプログラム的にWebKitを正しく動かして正しいことをさせるための回避策はありますか?
私はいくつかの複雑な提案とうまくいかなかった多くの単純な提案を見つけましたが、 Vasil Dinkov によってそれらの1つへのコメントはちょうどうまく働く再描画/再描画を強制する簡単な解決策を提供しました:
sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display='';
「ブロック」以外のスタイルでも機能する場合は、他の人にコメントさせていただきます。
ありがとう、Vasil!
私たちは最近これに遭遇し、CSSで composite layer with translateZ に影響を受ける要素をプロモートすることで余分なJavaScriptを必要とせずに問題が解決することを発見しました。
.willnotrender {
transform: translateZ(0);
}
これらの描画の問題は主にWebkit/Blinkで発生し、この修正は主にWebkit/Blinkを対象としているので、場合によってはそれが望ましいです。特に、受け入れられた答えはほぼ確実に リフローと再描画 を引き起こしますので、はそうではありません再塗装するだけです。
WebkitとBlinkはレンダリングパフォーマンスに懸命に取り組んできました、そしてこれらの種類のグリッチは不必要な流れと絵の具を減らすことを目的とする最適化の不幸な副作用です。 CSS will-change または他の連続した仕様が将来の解決策になるでしょう。
複合層を実現する方法は他にもありますが、これが最も一般的です。
danortonの解決策は私にはうまくいきませんでした。 WebKitが要素をまったく描画しないという非常に奇妙な問題がいくつかありました。入力内のテキストがonblurまで更新されなかった場所。 classNameを変更しても再描画されません。
私の解決策は、私が誤って発見したが、スクリプトの後に空のstyle要素を本文に追加することでした。
<body>
...
<script>doSomethingThatWebkitWillMessUp();</script>
<style></style>
...
それはそれを修正しました。それはどれほど変ですか?これが誰かに役立つことを願っています。
Display + offsetトリガーは私にはうまくいかなかったので、私はここで解決策を見つけました:
http://mir.aculo.us/2009/09/25/force-redraw-dom-technique-for-webkit-based-browsers/
すなわち.
element.style.webkitTransform = 'scale(1)';
私は同じ問題に苦しんでいました。 danortonの 'toggling display'修正は私のアニメーションのstep関数に追加されたとき私にはうまくいきましたが、私はパフォーマンスを心配していたので私は他のオプションを探しました。
私の状況では、再描画されなかった要素は、当時zインデックスを持たなかった絶対位置要素内にありました。この要素にz-indexを追加すると、Chromeの動作が変わり、期待どおりに再描画された - >アニメーションがスムーズになりました。
これが万能薬ではないかと思います、それは依存していると思いますなぜ Chromeは要素を再描画しないことを選択しましたが、私はそれが誰かを願ってこの手助けをします。
乾杯、ロブ
tl; dr >> zインデックスを要素またはその親に追加してみてください。
以下の作品。純粋なCSSで一度だけ設定する必要があります。そしてそれはJS関数よりも確実に機能します。パフォーマンスは影響を受けないようです。
@-webkit-keyframes androidBugfix {from { padding: 0; } to { padding: 0; }}
body { -webkit-animation: androidBugfix infinite 1s; }
どういうわけか私は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/
私は今日これにつまずいた: 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()を直接呼び出さなければならないことに気付きました。親要素を再描画しても、子が経験している問題を解決できないことがあります。
ブラウザが要素をレンダリングする方法についての良い記事: レンダリング:再描画、リフロー/再レイアウト、restyle
スクロール中にページの左下にある固定位置のキャプションボックスを更新すると、キャプションが画面いっぱいに「ゴースト」してしまいます。上記のすべてを試してみたが、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';
私はposition: absolute
で別のdivに挿入されたdivのいくつかでこの問題を抱えていました、挿入されたdivはposition属性を持っていませんでした。これをposition:relative
に変更したときはうまくいきました。 (問題を特定するのは本当に難しかったです)
私の場合は、要素はAngularでng-repeat
で挿入されています。
この質問に別の答えが必要なわけではありませんが、私は特定の状況で色を1ビット変更するだけで再描画を余儀なくされることに気付きました。
//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
は、2番目のスタイルの変更を現在のイベントループの外側に移動するのに重要です。
私のために働く唯一の解決策はsowasred2012の答えに似ています。
$('body').css('display', 'table').height();
$('body').css('display', 'block');
私はページ上にたくさんの問題ブロックがあるので、ルート要素のdisplay
プロパティを変更します。 none
はスクロールのオフセットをリセットするので、私はdisplay: table;
の代わりにdisplay: none;
を使用します。
誰もが彼ら自身の問題と解決策を持っているように思われるので、私は私のために働く何かを追加したいと考えました。現在のChromeを搭載したAndroid 4.1では、オーバーフロー付きで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);
}
画面のちらつきや実際の更新はありません。グローバルまたはクラススコープの変数はなく、単にローカル変数です。 Mobile Safari/iPadやデスクトップブラウザでは何も問題ないようです。
私はイオン性のhtml5アプリに取り組んでいます、私はIOSデバイス(iPhone 4、5、6、6 +)で上下にスクロールするとき、私はabsolute
name__の位置の要素を持っています私はバグを塗り直しました。
これが私の問題を解決することを除いてそれらのどれも働いていなかった多くの解決策を試しました。
これらの絶対位置要素にCSSクラス.fixRepaint
を使用しました。
.fixRepaint{
transform: translateZ(0);
}
これで私の問題は解決しました。助けになるかもしれません
要素にコンテンツスタイルを追加するだけで再描画が必要になることがわかりました。これは、再描画するたびに異なる値になるはずで、疑似要素に含める必要はありません。
.selector {
content: '1'
}
特定の状況で向きが変更されたときに、Chrome for Androidで表示されなくなっていた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>
突っ込んだりしっくりした1日半後に、ここで提供されているhacky解決策に満足していませんでしたが、この問題は新しい要素を描くときに要素をメモリに保持しているように見えることが原因です。解決策は、SVG上のlinearGradientのIDを一意にすることでした。ただし、これは1ページに1回しか使用されていませんでした。
これはさまざまな方法で実現できますが、角度のあるアプリではlodashのuniqueId関数を使用してスコープに変数を追加しました。
Angular Directive(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}})"/>
私はこの答えが他の誰かが彼らのキーボードを顔を壊すことの価値を節約することを願っています。
上記の提案は私にはうまくいきませんでした。しかし、下のものはそうします。
アンカー内のテキストを動的に変更したい。 「検索」という言葉。 id属性を持つ内部タグ "font"を作成しました。 javascriptを使ってコンテンツを管理しました(下記)
サーチ
スクリプトの内容
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);
}
私はtransform: translateZ(0);
メソッドを使いますが、場合によってはそれでは不十分です。
クラスを追加したり削除したりするのが大好きではないので、これを解決する方法を見つけようとしたところ、うまく機能する新しいハックができました。
@keyframes redraw{
0% {opacity: 1;}
100% {opacity: .99;}
}
// ios redraw fix
animation: redraw 1s linear infinite;
これはこれと関連しているようです: jQueryスタイルはSafariでは適用されていません
最初の回答で提案した解決策は、これらのシナリオでは私にはうまくいきました。
$('body').addClass('dummyclass').removeClass('dummyclass');
これはサファリに再描画を強制します。
私はこのメソッドがトランジションを扱うときに便利だと思った
$element[0].style.display = 'table';
$element[0].offsetWidth; // force reflow
$element.one($.support.transition.end, function () {
$element[0].style.display = 'block';
});
これは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);
}
私はもっと答えを試みましたが、それは私のために働きません。私は他のブラウザと比較してサファリと同じ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 = "";
の間になければならないので、本当に奇妙です。
最も確実に機能するもう1つの解決策は、
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
問題は、フォーカスとスクロールの状態が失われることです。
私の場合は "display/offsetHeight"ハックはうまくいきませんでした。少なくともそれがアニメ化されている要素に適用されたときです。
私はページのコンテンツ上で開閉されていたドロップダウンメニューを持っていました。メニューが閉じられた後にアーティファクトがページコンテンツに残っていました(WebKitブラウザでのみ)。 "display/offsetHeight"ハックが機能する唯一の方法は、私がそれをボディに適用した場合です。
しかし、私は別の解決策を見つけました:
これはまだかなり厄介です(ハードウェアレンダリングを強制するためにCSS3プロパティを使用します)、しかし少なくともそれは問題となっている要素にのみ影響を及ぼし、そして私にとってサファリとクロムの両方でPCとMacの上で働きました。
私は、リフローを強制するための、よりハックが少なく、より正式な方法をお勧めします。 forceDOMReflowJS を使用します。あなたの場合、あなたのコードは次のようになります。
sel = document.getElementById('my_id');
forceReflowJS( sel );
return false;