web-dev-qa-db-ja.com

CSSの変更中にブラウザーに強制的にリフローをトリガーさせる

CSS3トランジションに基づいて非jQueryレスポンシブイメージスライダーを構築しています。

構造はシンプルです。ビューポートと、左に浮いたLIを備えた相対的に配置されたULです。

私はそのような状況で問題に直面しています:

  1. ユーザーが「戻る」矢印をクリックします。
  2. JSは、現在表示されているLIノードの前に適切なLIを追加します。
  3. 今のところ、ULはCSSトランジションをnone 0s linearに設定して、アニメーションの変更を防ぎます。この瞬間、UL CSSの左の値をスライダーの幅(たとえば、0pxから-1200px)だけ減らして、ビューを同じようにします。
  4. 現在、ULの移行プロパティをall 0.2s ease-outに変更しています。
  5. 現在、ULのleftプロパティを変更してCSS3アニメーションをトリガーしています。 (言いましょう:-1200pxから0pxまで)。

何が問題ですか?ブラウザは変更を簡素化し、アニメーションを作成しません。

Stoyan Stefanovはブログでリフローの問題について書いています here ですが、この場合、要素にリフローを強制しようとしても機能しません。

これはこれを行うコードの一部です(簡単にするためにブラウザーのプレフィックスをスキップしました)。

ul.style.transition = 'none 0s linear 0s';ul.style.left = '-600px';ul.style.transition = 'all 0.2s ease-out';ul.style.left = '0px';

問題のアクションを見るためのフィドル: http://jsfiddle.net/9WX5b/1/

24
Simon

要素のoffsetHeightをリクエストすると、すべてがうまくいきます。この関数を使用して強制的にリフローを実行し、スタイルが変更された要素を渡すことができます。

_function reflow(elt){
    console.log(elt.offsetHeight);
}
_

そして、リフローが必要な場所でこれを呼び出します。この例を参照してください: http://jsfiddle.net/9WX5b/2/

編集:最近これを行う必要があり、console.logするよりも良い方法があるかどうか疑問に思いました。 _elt.offsetHeight_を独自のステートメントとして記述することはできません。オプティマイザ(少なくともChromeのもの)はリフローをトリガーしないのは、ゲッターセットなしでプロパティにアクセスするだけで、評価する必要もないためです。したがって、voidに副作用があるかどうかは確かではないため、これを行う最も安価な方法はvoid(elt.offsetHeight)です。 (オーバーライドされるか、idk)。

25
markasoftware
function reflow( element ) {
    if ( element === undefined ) {
        element = document.documentElement;
    }
    void( element.offsetHeight );
}

ChromeとFFで問題なく動作し、ATMを実行する最も簡単で移植性の高い方法のようです。

3
vaxquis