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を使うと解決できます。
うまくいかない場合は疑似要素に頼ってみてください〜。