CSS
CSSDay 20

position:fixedが効かない事件簿

More than 1 year has passed since last update.

初めに

よし、ヘッダーを画面上に固定してやろ(^ω^)

って時に

え、ヘッダーの上に文字が来るんですけど( ‘д‘⊂彡☆))Д´) パーン

とか

スクロールして、動的におしゃれに上部メニューを表示させたいのにスクロール中に表示されない( ‘д‘⊂彡☆))Д´) パーン

とかそんな事件の対処法をテンションに任せて書いていこうと思います。

事件1「z-index」

概要

ヘッダーにposition:fixedを指定してtop:0,left:0で画面上部に固定しているのに

なんで他の要素が上に来ているの!?という事件。

DEMO

DEMO

キャプチャ

fixed_sample1 (1).gif

code

html

<body>
    <div class="div_elm">
        hoge
    </div>
    <div class="fixed_elm">
        hoge
    </div>
    <div class="div_elm">
        hoge
    </div>
</body>

css

.fixed_elm {
    height: 100px;
    width: 100px;
    background: red;
    position: fixed;
    top: 0px;
    left: 0px;
}

.div_elm {
    position: relative;
    background-color: yellow;
    text-align: center;
}

解決策

position:fixedにしている要素の前後に同じdiv要素を配置しているのに、なんでposition:fixedにしている要素の次の要素は上に来ているのか・・・

原因はdiv要素にposition:relativeを指定している時は、position:fixedにしている要素にz-indexを指定していないからでした。

下記のように修正するときちんと動きました。

.fixed_elm {
    height: 100px;
    width: 100px;
    background: red;
    position: fixed;
    top: 0px;
    left: 0px;
    z-index: 1;
}

事件2「Transform」

概要

ヘッダーにposition:fixedを指定してtop:0,left:0で画面上部に固定しているのに

位置がなぜか画面上部にならない!?

DEMO

DEMO

キャプチャ

sample2.gif

code

html

<body>
    <div class="fixed_elm">
        hoge
    </div>
</body>

css

body {
    transform: translate3d(0, 0, 0);
    height: 300px;
    background-color: black;
}

.fixed_elm {
    height: 100px;
    width: 100px;
    background: red;
    position: fixed;
    top: 0px;
    left: 0px;
}

解決策

原因はbodyに指定しているtransform: translate3d(0, 0, 0);です。

どうやら親要素にtransformが指定してあると子要素のposition:fixed;は親要素からの相対位置になるっぽいです。

w3cでもバグ?として言われているっぽいです。

https://www.w3.org/TR/css-transforms-1/#transform-rendering

解決策は親要素からtransformを外すか、position:fixed;の要素の親子関係を解消させるか現状なさそうでうす。

事件3「スクロール」

概要

iPhoneでスクロールして、動的に上部メニューにposition:fixed;を指定して画面上部に固定させたいのにスクロール中に画面上部に固定されない・・・

stack overflowにも同じような悩みの人が・・・

iOS 9 Safari: changing an element to fixed position while scrolling won't paint until scroll stops

解決策

どうやらスクロール中にクラスを付与してposition:fixed;を指定してあげても

描画はCPUが行うのでスクロールが終わるまで反映されないそうです。

そのため、解決策としてはposition:fixed;を指定するクラスに

transform: translate3d(0, 0, 0);を指定するとスクロール中にも反映されます。

これは、transform: translate3d(0, 0, 0);を指定すると描画をGPUが行うため解決できるそうです。

最後に

position:fixed;は便利ですが、たまにはまったりするので気をつけましょう(´・ω・`)