こんにちは。今回はposition: fixed;が効かない理由とその対処法をまとめていきます。
なぜposition:fixed;が効かないのか | 親要素がtransformしていると効かない
例えばこんなヘッダーを作ろうとしています。こういうヘッダー、コーディングしてると結構出会います。
- ページ読み込み時にしたからふわっと出てくる
- グローバルナビがスクロールに追従する
見た目としてはこんな感じです。

さて、これをコーディングすると考えてみます。
まずは見た目はこんな感じでしょう。
1 2 3 4 5 6 7 8 9 10 |
<header class="Header" id="Header"> <nav class="Nav"> <ul class="List"> <li class="List-Item"><a href="#">メニュー1</a></li> <li class="List-Item"><a href="#">メニュー2</a></li> <li class="List-Item"><a href="#">メニュー3</a></li> </ul> </nav> </header> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
.Header { position: absolute; top: 0; left: 0; width: 100%; height: 60px; background-color: #6ba6e7; } .Nav { position: fixed; top: 18px; right: 20px; } .List { display: flex; gap: 20px; } .List-Item { color: #fff; font-size: 24px; line-height: 1; } |
アニメーションは以下のような形。
1 2 3 4 5 6 7 8 9 10 11 12 |
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous" ></script> <script> window.onload = function () { $("#Header").addClass("FadeIn") } </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
.Header { position: absolute; top: 0; left: 0; width: 100%; height: 60px; background-color: #6ba6e7; transition: all 1s; //追加 transform: translateY(30px); //追加 opacity: 0; //追加 } ...省略 .FadeIn { transform: translateY(0); opacity: 1; } |
さて、こうするとなんとposition: fixed;を指定しているはずのグローバルナビ部分がスクロールに追従しません(試してみてください)。
これは親要素(今回は.Header)に、アニメーションのためのtransform: translateY(30px)が付与されているからです。
MDNのpositionプロパティのページ(https://developer.mozilla.org/ja/docs/Web/CSS/position)にも、fixedについて以下のように書かれています。
祖先の一つに transform, perspective, filter の何れかのプロパティが none 以外 (CSS Transforms 仕様書を参照) に設定されている場合は例外で、その場合は祖先が包含ブロックとしてふるまいます。
要するに、親要素にtransformなどの指定があるとposition: absolute;と同様の挙動になってしまうのです。
どう対処するか
transform以外の方法が使えるならそちらを使う
今回であれば.Headerと.Navのtopの値を調整すれば実現可能です。それぞれtranslateYを使った時と同様に最初の値を30pxずらします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
.Header { position: absolute; top: 30px; //変更 left: 0; width: 100%; height: 60px; background-color: #6ba6e7; transition: all 1s; opacity: 0; } .Nav { position: fixed; top: 48px; //変更 right: 20px; transition: all 1s; //追加 opacity: 0; //追加 } ...省略 //追加 .FadeIn__Nav { top: 18px; opacity: 1; } |
1 2 3 4 5 |
window.onload = function () { $("#Header").addClass("FadeIn") $("#Nav").addClass("FadeIn__Nav") //追加 } |
これで想定通りの動きになります。
子要素をそれぞれtransformさせる
position: fixed;にしたい要素の親要素にtransformが指定されているのが問題なので、その状態さえ回避すれば良いです。背景とグローバルナビ部分を分け、それぞれをtransformさせます。
1 2 3 4 5 6 7 8 9 10 11 12 |
<header class="Header" id="Header"> <div class="Header__Background js-FadeIn"></div> <!-- 追加 --> <nav class="Nav js-FadeIn"> <!-- js-FadeInというクラスを追加 --> <ul class="List"> <li class="List-Item"><a href="#">メニュー1</a></li> <li class="List-Item"><a href="#">メニュー2</a></li> <li class="List-Item"><a href="#">メニュー3</a></li> </ul> </nav> </header> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
.Header { position: absolute; top: 0; left: 0; width: 100%; height: 60px; //background-colorを削除 } //追加 .Header__Background { width: 100%; height: 100%; background-color: #6ba6e7; transition: all 1s; transform: translateY(30px); opacity: 0; } .Nav { position: fixed; top: 18px; right: 20px; transition: all 1s; //追加 transform: translateY(30px); //追加 opacity: 0; //追加 } |
1 2 3 4 5 6 |
<script> window.onload = function () { $(".js-FadeIn").addClass("FadeIn") //.js-FadeInを対象に変更 } </script> |
これで想定通りの動きになります。
まとめ
というわけで、position: fixed;が効かない理由と、その対処をまとめました。知らないとかなり対処が難しいので、ぜひ参考にしてください。
コメントを残す