IE6 position:fixed の諸問題を解決する jQuery.exFixed.js

最近の更新履歴

2011-12-07
Ver 1.3.2 リリース
jQuery 1.7.1に対応しました。
2010-12-27
Ver 1.3.1 リリース
fixed 要素がブラウザ表示エリアから隠れ1度非表示状態になると、ウィンドウをリサイズし表示エリア内におさめても非表示状態が続いてしまう不具合を修正しました。
2010-11-14
Ver 1.3.0 リリースしました。exAPI ベースの実装に変更しました。サイズに auto を指定できるように変更しました。
2009-12-08
Ver 1.2.2 リリースしました。IE6 にて fixed 対象要素を非表示にしても表示されてしまう不具合を修正しました。Ver 1.2.1 でサイズを明示せずプラグインを実行すると fixed されない不具合を修正しました。
more

jQuery exFixed を使用すると、IE6 で position : fixed をしようとした時に発生するさまざまな問題を解決することができます。以下 Demo を IE6 で確認してみてください。上下左右に配置した要素が固定表示されてることが確認できます。

Demo

固定表示した要素を動的にリサイズしたり、表示位置を変更することもできます。

Demo jQuery exFixed を動的な位置移動やリサイズ処理に対応させてみた - Cyokodog::Diary

position : fixed 自体の拡張として、水平、垂直のどちらか一方の方向にのみ固定表示を適用することもできます。(IE6 以外にも対応)

Demo jQuery.exFixed.js を機能拡張しました - Cyokodog::Diary

IE6 における position:fixed の諸問題とは

IE6 で position:fixed を実現し、より汎用性を持たせようとすると以下のような問題にぶつかります。

  • right , bottom ベースの位置指定の対応
  • スクロール時の fixed 要素のガタつき
  • パーセント(%) によるサイズ・位置指定の対応
right , bottom ベースの位置指定の対応

JavaScript で position:fixed を実現させる方法として、スクロール量を absolute 要素の現在位置に加算する方法があります。(cssで実現する場合は IE の独自機能 expression を使用します)

var box=$j('div.box').css({'position':'absolute','top':0,'left':0})
$j(window).scroll(function(){
    box.css({
       'top',$j(document).scrollTop()),
       'left',$j(document).scrollLeft())
    });
})

Demo

但しスクロール量は left,top ベースになるので、right,bottom ベースの位置指定に対応させるためには、ウィンドウのリサイズ時に配置位置の調整が必要になります。

Demo

関連記事

スクロール時の fixed 要素のガタつき

上記のサンプルページで画面をスクロールすると fixed 要素がガタついて表示されてしまいます。後方互換モードだとこの現象を軽減させる方法があるようです。

この問題を CSS の定義のみで解決する手段として下記のような方法があります。

html,body{   
    width :100%;
    height:100%;   
    overflow:auto;   
    margin:0;   
    padding:0;   
}   
div#samp{   
    position: fixed!important;   
    position: absolute;   
}

absolute 要素のコンテナを html 要素のままに body 要素のスクロールバーのみをフロントに表示させることで absolute 要素の位置固定を実現してます...が、いろいろと問題を含んでます。

  • absolute 要素に width:100% や right,bottom ベースの位置指定をすると、absolute 要素がスクロールバーに重なって表示される
  • body 要素が html 要素に完全に重なるかたちになるので html 要素 body 要素を個別にデザインできない
  • 全ての absolute , relative 要素が固定表示されてしまう(relative要素の固定表示は IE のバグ)

Demo

でこれらを解決してガタつきも抑える方法として試したのがこちら

Demo

div 要素を2つ使い擬似的に html 要素と body 要素を作り、fixed 要素の表示位置を調整してます...が、かなり大胆な手法なのでデザインによってはレイアウトがくずれんじゃないか...と少々心配な面もあります...

パーセント(%) によるサイズ・位置指定の対応

position:fixed の用途として、ヘッダやフッタの固定表示というのはありがちかと思われますが、この場合 width は 100% を指定することになるかと思います。
通常 body 要素のデフォルトには margin が付いてますが、ヘッダ・フッタの fixed(absolute)要素に対し width:100% とすると、この margin の効いた body 要素を基準にサイズ調整されるので、結果 margin 分短いヘッダやフッタになってしまいます。
また、反対にコンテンツの横幅が大きく body 要素を膨張させてる場合、今度はヘッダ・フッタの幅が長くなってしまいます。

ですので正確に position:fixed を再現するなら fixed(absolute) 要素のサイズや位置にパーセント(%)が含まれてた場合は、ブラウザの表示領域(clientWidth / clientHeight)に対しての比率でサイズ・位置調整を行う必要があります。

以下のライブラリではスクロール時のガタ付きを除けば、上記の問題を全て解決してるようです。

jQuery などのコアライブラリ非依存で実装されてるところがすばらしいです。

jQuery exFixed

まえふりが長くなりましたが、jQuery exFixed では、スクロール時のガタつきも含めて前述の全ての問題について解決しています。
互換 / 標準両モードにも対応しています。

下記ブラウザで動作確認してあります。

デモによる比較

パーセント指定をふんだんに使ったデモで各手法の実行結果を比較してみます。
上下にヘッダ・フッタ、左右にサイドバー、真ん中に正方形のボックス要素という構成で配置しています。

exFixed
Demo(標準) Demo(互換)

Fixed positioning
Demo(標準) Demo(互換)

html,body の height:100%
Demo(標準)

div による 擬似 html,body
Demo(標準)

exFixed.js と Fixed positioning のみ正しく表示されてることが確認できます。
また、exFixed.js の場合、標準 / 互換 両モードでスクロール時にガタつきが発生してない事も確認できます。
IE7 で Fixed positioning のサンプルページを見ると bottom 指定の fixed が効いてないことが確認できます。Fixed positioning の読み込みを行わないと正常に表示されるので Fixed positioning を使用する場合は IE6 の場合のみ読み込むようにした方が良いです。

使い方

jquery.js、jquery.exfixed.js を読み込みます。

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.exfixed.js"></script>

下記のように fixed の CSS 定義をし、対象要素に対し exFixed() メソッドを実行します。

<style>
    #sample{
        position:fixed;
        width:40%;
        height:40%;
        right:10%;
        bottom:10%;
    }
</style>
<script>
    $(function(){
        $('#sample').exFixed(); // for IE6
    });
</script>

ダウンロード

こちらからどうぞ

動作原理

基本的に expression を使ったスクロール量に合わせた位置移動で position: fixed を実現しています。

element.style.setExpression(
    'top',
    '(baseTop+(document.body.scrollTop||document.documentElement.scrollTop))+"px"'
);

これだけだとスクロール時、対象要素がガタつくので以下のような記述で解消します。

$('html').css({
    'background-image':'url(image)',
    'background-attachment':'fixed'
});

background-attachment を fixed にして、background-image を指定もしくは url(null) とするとガタつかなくなります!
CSS Lecture さんのこちらの記事をきっかけに知ることができました。(ありがとうございました)

ちなみ後方互換モードの場合は body 要素に対し同様の処理をすることでガタつきを解消できます。(背景画像の移動はできませんが...)

最後に

IE8 がリリースされたばかりで IE6 ネタというのもあれですが、私のように社内イントラシステムをメインに仕事をされてる方はなかなか IE6 とは手を切れないのではないでしょうか。

今までは IE6 が足枷になって fixed 自体が存在しないも同然でしたが、ガタつきの解消とパーセント(%) 指定の対応で本来の fixed とほぼ同等の再現性を実現できたかなと思うので、使える場面があれば使っていこうかと思います。

更新履歴

2009-11-29
Ver 1.2.1 リリースしました。IE6 にて fixed 対象要素のサイズを指定してない状態で、ウィンドウをリサイズし、対象要素の一部が表示領域外にはみ出すと、その部分が欠けた状態のままになってしまう問題を修正しました。
2009-11-11
ご要望があったので圧縮版の JS ファイルもダウンロードできるようにしました。(Ver 1.2.0 / 11KB → 7KB)
2009-10-02
機能拡張と不具合修正をしました(Ver 1.2.0)。詳細は以下をご覧ください。
2009-09-03
スクロール時のガタつき防止処理を変更しました(Ver 1.1.2)。詳細は以下をご覧ください。
2009-08-23
標準・互換モードの判定タイミングに問題ありIE8でただしく動作しないケースがあり、ソースを修正しました(Ver 1.1.1
2009-08-22
background-attachment:fixedの強制設定による背景画像の固定化を防止するために html 要素の背景画像を body 要素に割り当てなおすおせっかい機能がありましたが廃止しました
2009-05-15
fixed 要素を動的にリサイズ、位置移動できるようにしました。詳しくはこちら。