position:fixed;とtransformのスマホ挙動

position:fixed;で負のz-indexを使用して要素を疑似的な背景にしようとした際の話。

それと同一階層の要素や別の階層の子要素などにtransform:rotate3d;を使用すると、position:fixed;がz-indexが負の値にもかかわらず、transform:rotate3d;の要素が隠れてしまう。

スマホで以上のような現象を確認した。スマホだけ。PCには問題がない。

 

例として、animate.cssでflipInやflipOutをかけようとして、この条件が満たされてしまうと発現する。

 

試しに以下のようなコード体系でコーディングをしてみる。

 

テスト用のコード

<style>
.content{ /* レイアウトのスタイルなんたら */  }
.image{ /* レイアウトのスタイルほにゃらら */ }
.text{ /* レイアウトのスタイルほげほげ */ }
.fix-background{
    width:100%; height:100%;
    background:#CCC;
    position:fixed;
    top:0; left:0; right:0; bottom:0;
    z-index:-1;
}
</style>
 
<div id="container">
    <article class="content">
        <!--↓このimageをanimateさせようとする-->
        <div class="image flipInY animated"><img src="image.jpg" alt="image" /></div>
        <div class="text">
            <p>上記imageに対して、animate.cssのプロパティをかけてあげるとあら不思議。</p>
            <p>スマホで見たときに下のfix-backgroundにimageが隠れてしまう!</p>
        </div>
    </article>
    <div class="fix-background">position:fixed;での疑似背景</div>
</div>

 

上記の例だとtransform:rotate3d;のかかった「image」要素は、position:fixed;とz-index:-1;をかけた「fix-background」要素の後ろ側に隠れてしまう。

 

animate.cssでrotate3dがかかっているためではないかと早い段階で気づいたものの・・・。

単なる要素の重なりの問題かと思って、上記の「image」にposition relativeとz-indexをかけてもうまくはいかない。

transform:rotate3d;自体が上記のコードでは、animate.cssがかかっている「image」にしか入っていないわけで・・・。

こいつだけかと思いきや、translate3dとかの3D系のtransformの要素に関してはアニメーションなどの「処理」が行われると同じことが起きる。

これがスマホだけで起こるというのもなんとも奇妙な話である。

 

 

???

こいつの特定と修正で小一時間悩んだ。

 

調べた結果

いわゆるスマホのブラウザレンダリングのGPUアクセラレーションに引っかかっているらしい。

 

3D系のtransformが「処理」される前に、祖先要素のどこかで静的にGPUアクセラレーションを有効化させておく必要がある。

要は処理する前に準備しといてくださいねーってこと。

これしないと、position:fixed;の疑似背景に、いくら負のz-indexをかけようが意味がない。

 

そして、これに対策を施すのであれば、以下のようにコードとなる。

<style>
.content{
    /* レイアウトのスタイルなんたら */
    transform:translate3d(0,0,0);
}
.image{ /* レイアウトのスタイルほにゃらら */ }
.text{ /* レイアウトのスタイルほげほげ */ }
.fix-background{
    width:100%; height:100%;
    background:#CCC;
    position:fixed;
    top:0; left:0; right:0; bottom:0;
    z-index:-1;
}
</style>
 
<div id="container">
    <article class="content"><!--←これ-->
        <div class="image flipInY animated"><img src="image.jpg" alt="image" /></div>
        <div class="text">
            <p>これでスマホでもうまいことアニメーションするぞ!</p>
        </div>
    </article>
    <div class="fix-background">position:fixed;での疑似背景</div>
</div>

上記では静的なtransform:translate3d(0,0,0);をanimate.cssを使う要素の親要素にかけている。

transform:translate3d(0,0,0);といいつつ、GPUアクセラレーションを有効化させられるCSSプロパティならperspectiveでも何でもいいっぽい。

 

GPUアクセラレーションの有効化をワイルドカードでかける習慣が自分にはないので遭遇した問題・・・といえばそれまでですが、備忘録として記載しておきます。

カテゴリ

この記事のコメント

コメントはないです。

コメントを残す

メールアドレスが公開されることはありません。