ページのスクロール時に、ある要素を画面の特定の位置に固定したい場合があります。
例えば、ナビゲーションメニューやページトップに戻るボタンなどです。
このように要素を固定したい時に、よく使われるCSSと言えばposition:fixedを挙げられます。
しかし、一部の条件下でposition:fixedがうまく機能しない…なんてケースがあります。
今回はposition:fixedが効かない時の原因と対処法について解説します。
もくじ
1.position:fixedの基本事項を確認しよう
まずposition:fixedの基本的な使い方について、簡単におさらいしておきましょう。
そもそもpositionとは、要素の位置を調整することができるプロパティです。
positionプロパティには以下の4つの値があります。
- static
- relative
- absolute
- fixed
staticはデフォルトの値で、位置調整ができません。
その他の値を指定した場合、top、right、bottom、leftによって、具体的な位置を決めることができます。
例えば、以下のような感じにです。
|
1 2 3 4 5 |
.sample { position: relative; top: 100px; left: 50px; } |
直感的にわかると思いますが、topは上から、rightは右から、bottomは下から、leftは左からの距離を示してます。
「どこを基準にして」という部分をstatic以外の値で決めます。
relativeなら「本来その要素がある位置」、absoluteは「親要素」、そしてfixedは「画面」を基準とします。
今回の主役はfixedなので、fixedの使用方法のみ詳しく説明します。
例えば、以下のCSSを適用させてみましょう。
|
1 2 3 4 5 |
.sample { position: fixed; right: 50px; bottom: 50px; } |
right: 50px、bottom: 50pxなので、画面の右と下から50pxの距離に固定されるはずです。
結果は以下のとおりです。

.sample(青色の四角)は画面の右端付近に固定され、上下にスクロールしても位置を留めていることがわかります。
ちなみにposition: absoluteの場合、その親要素に対してstatic以外の値を指定しないと思い通りに機能しませんが、fixedにはそのような操作は必要ありません。
以上がposition: fixedの基本的な使用方法です。
補足情報としてもう一点だけ。
現時点(22年12月)において、主要ブラウザでposition: fixedが使用できない…なんてことはほぼほぼありません。
参考:CSS position:fixed | Can I use… Support tables for HTML5, CSS3, etc
ただし「Opera Mini」と呼ばれるOperaのスマートフォン用のブラウザでは未対応のようです。
2.position:fixedが効かない原因は親要素のtransform
position: fixedのコードの記述に問題が無ければ、効かない原因として疑われるのは親要素のtransformです。
transformとは要素を変形したり、移動させたりするCSSプロパティです。
主にメニューの開閉やボタンの変化など、アニメーションを施したい場合に使用されます。
実はposition: fixedは、親要素のtransformをnone以外に指定していると上手く機能しません。
例えば、以下のように親(.parent)と子(.child)の関係にある要素があると仮定します。
|
1 2 3 |
<div class="parent"> <div class="child"></div> </div> |
さらにCSSで以下のように成形し、子要素にはposition: fixedを指定します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.parent { width: 100px; height: 100px; background: steelblue; } .child { position: fixed; top: 50px; right: 50px; width: 50px; height: 50px; background: tomato; } |
position: fixedを指定された要素は、top・right・bottom・leftによって親要素ではなく画面を基準にして位置調整できます。
結果は以下の通りで、親要素との位置関係を無視して、画面の上端(top)と右端(right)から50px離れた位置(9~10行目)で固定されています。

では、今度は親要素にtransformを指定してみましょう。
|
1 2 3 4 5 6 |
.parent { width: 100px; height: 100px; transform: rotate(45deg); background: steelblue; } |
rotate()(4行目)は、要素を好みの角度に回転させることができるCSS関数です。
角度の単位である「deg」で調整します。
では、子要素の挙動を確認してみましょう。

上図の通り、親要素の回転は成功したものの、子要素が適切な位置に固定されていないことがわかります。
現状、子要素には親要素を基準にしてtop、rightの値が適用されているよう見えます。
すなわち、absoluteと同様な挙動になっています。
MDN Web Docsにもposition: fixedの例外事項について以下のように述べられています。
祖先の一つに transform, perspective, filter の何れかのプロパティが none 以外に設定されている場合は例外で、その場合は祖先が包含ブロックとしてふるまいます。
position – CSS: カスケーディングスタイルシート | MDN
MDNによれば、親要素に対してtransformだけでなくperspectiveやfilterの値がnone以外に指定されていると、同様な挙動になるようです。
3.position:fixedを有効にするための対処法
では、transformを使いつつposition: fixedをちゃんと機能させるためにはどうしたら良いのでしょうか。
3-1.固定したい要素をtransformが指定されている親要素から外す
そもそもposition: fixedは画面を基準にして位置を決めるためのものです。
親要素を基準としないため、コーディングする上で親子関係にする必要性が無いケースがほどんどです。
親要素が原因で子要素のposition: fixedが効かないのであれば、親子関係を解消してあげれば良いです。
例えば、前述の例でいえばHTMLを以下のように変えてみます。
|
1 2 |
<div class="parent"></div> <div class="child"></div> |
.parentの中の.childを取り出して、並列させただけです(クラス名がややこしいですが^^;)。
結果は以下の通りで、もともと子要素だった要素(オレンジの四角)にきちんとposition :fixedが適用されていることがわかります。

元々、親要素だった要素(青の四角)のtransformも正常に機能しています。
このように親子関係である必要性が無ければ、要素を並列させることで問題を解決できます。
3-2.transform以外の方法で同じ動作が可能か探る
親子関係を維持したい場合には、親要素のほうのtransformで実現したいことが、別のCSSプロパティで可能か考えてみると良いでしょう。
例えば、以下のHTMLを想定してください。
|
1 2 3 4 5 |
<div class="grandparent"> <div class="parent"> <div class="child"></div> </div> <div> |
そして、transformのtranslate()関数で.parentを水平方向に移動させてみます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
.grandparent { width: 300px; height: 400px; background: tan; } .parent { width: 100px; height: 100px; transform: translate(50px); background: steelblue; } .child { position: fixed; top: 50px; right: 50px; width: 50px; height: 50px; background: tomato; } |
さらに、先程と同様に.childにはposition: fixedが指定されています。
しかし、親要素にtransformが指定されているため、.childのposition: fixedは正常に機能しません。
現状は下図のとおりです。

ただし、要素の位置を調整するだけであればtransform以外の方法もあります。
例えば、position: absoluteです。
先程のCSSを以下のように変更します(.childはそのまま)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.grandparent { position: relative; width: 300px; height: 400px; background: tan; } .parent { position: absolute; left: 50px; width: 100px; height: 100px; background: steelblue; } |
absoluteの注意点として、親要素のpositionをstatic以外に指定(2行目)する必要があることに気を付けましょう。
では、結果を見てみましょう。

子要素がposition: fixedによって画面端に固定されており、また親要素の移動にも成功しました。
まとめ
今回はCSSのposition: fixedが効かない原因と対策について解説しました。
最後に今回、説明した内容をまとめておきます。
position: fixedはほとんどの主要ブラウザで対応されている。- スペルに間違いがなければ、親要素に
transformが指定されていないかチェックしよう。 - 親要素に
transformがnone以外に指定されていると、子要素のposition: fixedは正常に機能なくなる - 親子(入れ子)関係を解消させるか、
transformと代替可能なプロパティに変えても問題ないか試してみよう。



