向壁虚造

WEBサイト作成のためのプログラミング備忘録

CSSのposition:fixedが効かない時の原因と対策

CSSのposition:fixedが効かない時の原因と対策

ページのスクロール時に、ある要素を画面の特定の位置に固定したい場合があります。

例えば、ナビゲーションメニューやページトップに戻るボタンなどです。

このように要素を固定したい時に、よく使われるCSSと言えばposition:fixedを挙げられます。

しかし、一部の条件下でposition:fixedがうまく機能しない…なんてケースがあります。

今回はposition:fixedが効かない時の原因と対処法について解説します。

1.position:fixedの基本事項を確認しよう

まずposition:fixedの基本的な使い方について、簡単におさらいしておきましょう。

そもそもpositionとは、要素の位置を調整することができるプロパティです。

positionプロパティには以下の4つの値があります。

  • static
  • relative
  • absolute
  • fixed

staticはデフォルトの値で、位置調整ができません。

その他の値を指定した場合、toprightbottomleftによって、具体的な位置を決めることができます。

例えば、以下のような感じにです。

直感的にわかると思いますが、topは上から、rightは右から、bottomは下から、leftは左からの距離を示してます。

「どこを基準にして」という部分をstatic以外の値で決めます。

relativeなら「本来その要素がある位置」、absoluteは「親要素」、そしてfixedは「画面」を基準とします。

今回の主役はfixedなので、fixedの使用方法のみ詳しく説明します。

例えば、以下のCSSを適用させてみましょう。

right: 50pxbottom: 50pxなので、画面の右と下から50pxの距離に固定されるはずです。

結果は以下のとおりです。

position:fixedに指定すると、スクロールしても画面に固定される

.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は、親要素のtransformnone以外に指定していると上手く機能しません。

例えば、以下のように親(.parent)と子(.child)の関係にある要素があると仮定します。

さらにCSSで以下のように成形し、子要素にはposition: fixedを指定します。

position: fixedを指定された要素は、toprightbottomleftによって親要素ではなく画面を基準にして位置調整できます。

結果は以下の通りで、親要素との位置関係を無視して、画面の上端(top)と右端(right)から50px離れた位置(9~10行目)で固定されています。

子要素にposition:fixedを指定する

では、今度は親要素にtransformを指定してみましょう。

rotate()(4行目)は、要素を好みの角度に回転させることができるCSS関数です。

角度の単位である「deg」で調整します。

では、子要素の挙動を確認してみましょう。

親要素にtransformを指定した場合の子要素の挙動

上図の通り、親要素の回転は成功したものの、子要素が適切な位置に固定されていないことがわかります。

現状、子要素には親要素を基準にしてtoprightの値が適用されているよう見えます。

すなわち、absoluteと同様な挙動になっています。

MDN Web Docsにもposition: fixedの例外事項について以下のように述べられています。

祖先の一つに transform, perspective, filter の何れかのプロパティが none 以外に設定されている場合は例外で、その場合は祖先が包含ブロックとしてふるまいます。

position – CSS: カスケーディングスタイルシート | MDN

MDNによれば、親要素に対してtransformだけでなくperspectivefilterの値がnone以外に指定されていると、同様な挙動になるようです。

3.position:fixedを有効にするための対処法

では、transformを使いつつposition: fixedをちゃんと機能させるためにはどうしたら良いのでしょうか。

3-1.固定したい要素をtransformが指定されている親要素から外す

そもそもposition: fixedは画面を基準にして位置を決めるためのものです。

親要素を基準としないため、コーディングする上で親子関係にする必要性が無いケースがほどんどです。

親要素が原因で子要素のposition: fixedが効かないのであれば、親子関係を解消してあげれば良いです。

例えば、前述の例でいえばHTMLを以下のように変えてみます。

.parentの中の.childを取り出して、並列させただけです(クラス名がややこしいですが^^;)。

結果は以下の通りで、もともと子要素だった要素(オレンジの四角)にきちんとposition :fixedが適用されていることがわかります。

要素の親子関係を解消すればposition:fixedは機能する

元々、親要素だった要素(青の四角)のtransformも正常に機能しています。

このように親子関係である必要性が無ければ、要素を並列させることで問題を解決できます。

3-2.transform以外の方法で同じ動作が可能か探る

親子関係を維持したい場合には、親要素のほうのtransformで実現したいことが、別のCSSプロパティで可能か考えてみると良いでしょう。

例えば、以下のHTMLを想定してください。

そして、transformtranslate()関数で.parentを水平方向に移動させてみます。

さらに、先程と同様に.childにはposition: fixedが指定されています。

しかし、親要素にtransformが指定されているため、.childposition: fixedは正常に機能しません。

現状は下図のとおりです。

translate()関数でも、同様の問題が起こる

ただし、要素の位置を調整するだけであればtransform以外の方法もあります。

例えば、position: absoluteです。

先程のCSSを以下のように変更します(.childはそのまま)。

absoluteの注意点として、親要素のpositionstatic以外に指定(2行目)する必要があることに気を付けましょう。

では、結果を見てみましょう。

transform:translate()をposition:absoluteで代替させる

子要素がposition: fixedによって画面端に固定されており、また親要素の移動にも成功しました。

まとめ

今回はCSSのposition: fixedが効かない原因と対策について解説しました。

最後に今回、説明した内容をまとめておきます。

  • position: fixedはほとんどの主要ブラウザで対応されている。
  • スペルに間違いがなければ、親要素にtransformが指定されていないかチェックしよう。
  • 親要素にtransformnone以外に指定されていると、子要素のposition: fixedは正常に機能なくなる
  • 親子(入れ子)関係を解消させるか、transformと代替可能なプロパティに変えても問題ないか試してみよう。