HTML/CSS

【position:fixedが効かない】position:fixedとbackdrop-filterは同居できない

CSSを書いているときに、position:fixed;が効かない場面に出くわすことがあります。

結論から言うと、親要素にbackdrop-filterや、filterが使用されていると、子要素のposition:fixed;が効きません。

ただ、どうしても親要素にfilterをつけたいときもあるかと思います。そんなときの解決法も含めてご紹介していきます。

position:fixedとbackdrop-filter(filter)は同居できない

例えば、以下のようなデザインがあったとします。

See the Pen
fixedとbackdrop-filter: blurが同居できない話 01
by tom k (@tom-k-the-encoder)
on CodePen.

headerがあり、header内にある右上のボタンを押すと、右からメニューがスライドインしてきます。

このメニュー本体は、右側にright:-100%;で隠してあります。
ボタンを押すと、JavaScriptでメニューにis-activeクラスが付与され、right: 0;となって右からスライドインしてくる仕様です。

backgroundには、わかりやすいように斜線を敷いています。

menuの親要素headerにbackdrop-filter:blurを付け足すと…

では、position:fixed;を当てているmenuの親要素であるheaderに、backdrop-filter:blurを追加してみます。

すると、以下のようになります。

See the Pen
backdrop-filterとposition:fixedが同居できない話02
by tom k (@tom-k-the-encoder)
on CodePen.

position:fixed;が効かなくなり、右に隠しているメニュー分の横スクロールバーが出てきてしまいました。
表示もおかしいです。

どうしてもposition:fixed;とbackdrop-filterを同居させたいときの方法

ただ、私も経験したのですが、どうしてもposition:fixed;とfilterを同居させたい!どっちも使いたい!という場合があると思います。

その場合は、backdrop-filterをつけたい要素そのものにスタイルを当てるのではなく、ターゲットとなる要素の疑似要素にfilterをつけてあげると解決できます。

以下のような形です。

See the Pen
backdrop-filterとposition:fixedが同居できない話02
by tom k (@tom-k-the-encoder)
on CodePen.

/* headerの疑似要素にbackdrop-filterを当てる */
header::before {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  backdrop-filter: blur(5px);
  left: 0;
  top: 0;
  z-index: -1;  /*LOGOとメニューボタンが疑似要素の上にくるように調整*/
}

 

filterをつけたい要素(この例の場合はheader)の疑似要素を用意してあげて、width:100%;height:100%;にし、要素と同じ横幅・縦幅にしてあげます。

top:0;left:0;で、filterをつけたい要素と疑似要素をぴったり重ねます。

その疑似要素に対してbackdrop-filterをかけてあげると、子要素のposition:fixed;と競合することなく、フィルターを効かせることができました!

まとめ

親要素のbackdrop-filterやfilterと、子要素のposition:fixed;などは一緒に使用できません。

なので、親要素の疑似要素を用意してあげて、それにfilterを使うと解決できます。

うまくいかない場合は疑似要素に頼ってみてください〜。