IE、Edgeでposition:fixedな要素がスクロール時にガタつく場合の対応策

ほんとマイクロソフトっていうのは出来の悪い子ばっかり生み出すわねーって思いますが、せっかく古いIEのサポートを切ってくれて「もうクロスブラウザ対応で頭を悩ますなんてことはないんだ!」と思わせておきながら最新のIE / Edgeにもしっかりとバグを組み込んでくれるとはさすがっすよね。

はい、というわけで今回はそんな話題であります。

症状

以下のようなHTML / CSSをIEで表示してみましょう。

<style>
#fixed {
width: 100px;
height: 100px;
border: 1px solid #000;
position: fixed;
top: 0;
right: 0;
z-index: -1;
}
#scroll {
width: 100%;
height: 1000px;
background-color: rgba(0,0,0,0.3);
}
</style>

<div id="fixed">
固定する要素
</div>
<div id="scroll">
スクロールする要素
</div>

想定としては、半透明の背景の下に何か固定要素を置いておきたい時でしょうか。どうやらこの「下に」という部分がポイントらしくて、z-indexがマイナスの時のみ発生するみたいです。

これをIEでスクロールさせると、固定したいはずのfixed要素がガタガタいってて見苦しいことこの上ないです。何とかしましょう。

対応策1. スムーズスクロールを使用しない

参考:IE11でFixedの要素がスクロール時にガタつく問題 – みかづきブログ その3

上記記事で紹介されているので詳しくはそちらを参照してほしいのですが、ユーザー側で

インターネットオプション > 詳細設定 > スムーズスクロールを使用するのチェックを外す

という設定を行うことで一応ガタつきは治ります。

ただ、そうは言ってもまさかIEで訪れたユーザーに対してその旨を要請するアラートを出すなどというのは、現実的にはありえないよなぁと思われます。というわけで何か他の解決策を探したいところです。

対応策2. htmlをoverflow:hiddenとする

参考:css – IE 10 & 11 make fixed backgrounds jump when scrolling with mouse wheel – Stack Overflow

以下のCSSを追加することで、このバグは治ります。

html{
 overflow: hidden;
 height: 100%;
}
body{
 overflow: auto;
 height: 100%;
}

ただし、これはこれで別の問題を引き起こしてしまいまして、htmlではなくbodyの方でスクロールさせるという仕様にしてしまったせいでJS側のスクロール関係が使えなくなってしまいます。

これはあくまで自分が試してみた結果なので他にももっとあるかもしれないですが、具体的には$(window).scroll(function(){...})というようなスクロールによるイベント取得だとか、あとはページ内リンクなどでよく使う$("body").scrollTop()(これは$(“html”)もダメでした)とかも動きませんでした。(あるいはここでの$(window)や$(“body”)を何か別の要素に変えてあげれば上手く動くのかもしれませんが、自分はそこまでは検証していません。どなたかやってみた方いたら教えてください)

というわけで、そういった機能を使わない場合はこの方法で良いですが、使いたい方は他の解決策が欲しいところです。

対応策3. スムーズスクロールを強制的に無効にする

参考:New bug in IE11 — scrolling position:fixed + background-image elements jitters badly.

以下のJavaScriptを入れてあげましょう。

<script>
 if(navigator.userAgent.match(/MSIE 10/i) || navigator.userAgent.match(/Trident\/7\./) || navigator.userAgent.match(/Edge\/12\./)) {
 $('body').on("mousewheel", function () {
 event.preventDefault();
 var wd = event.wheelDelta;
 var csp = window.pageYOffset;
 window.scrollTo(0, csp - wd);
 });
 }
</script>

これは何かというと、IEの時だけマウスのスクロール機能を無効にし、その分JS側で同じ量だけスクロールさせるというものです。

要するに、対応策1のスムーズスクロールを無効にするという設定を強制的にやってしまっているコードです。一応これでそもそものガタつくバグも解決し、他に副作用的なバグも起こさないので、自分としてはこれがベストプラクティスかなーと思っています。

まぁスムーズスクロールを切ったおかげでそもそもスクロール自体がコマ送り的なガクガク感が出てしまいますが、そこは「ぐれーすふるでぐらでーしょん」っていうやつだということにしておけばいいんじゃないでしょうか。

ということでお困りの方はお試しください〜

この投稿へのコメント

コメントはありません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


この投稿へのトラックバック

  1. […] IE、Edgeでposition:fixedな要素がスクロール時にガタつく場合の対応策 […]

トラックバック URL