IE6でposition:fixedがうまくいかないのをfixするhtc

to-Rの西畑さんの講演を聞いてIE6でpositonfixedが動かないのを思い出した。それでそれをどう回避するかというと以下みたいにwindow.onscrollのイベントが発生したときに毎回毎回位置を計算して描画する。このコードって実は問題で描画がスクロールの速度においつかずちらつきが発生したりする。
このちらつきは僕は苦手というエントリーを以前書いた(http://d.hatena.ne.jp/shogo4405/20060919/1158664960)そこにはstyle.setExpressionを使えばちらつかなくていいとも書いた。

といわけで

今回はHTML Component(.htc)を使って書き直してみる。以下の部分をfixed.htcみたいな名前にして保存する。あとはスタイルシートのbehaviorで読み込みするだけ。

<public:component>
<attach event="ondocumentready" handler="fixed" />
<script type="text/javascript">
function fixed()
{
    var i, expression = '';
    var value, style = element.style;
    var currentStyle = element.currentStyle;

    if(currentStyle.position.toLowerCase() != 'fixed'){ return; };

    var bounds =
    {
        Top : currentStyle.top,
        Right : currentStyle.right,
        Bottom : currentStyle.bottom,
        Left : currentStyle.left
    };

    style.position = 'absolute';
    for(i in bounds)
    {
        value = bounds[i];
        expression = '';
        if(bounds[i] == 'auto'){ continue; };

        switch(i)
        {
            case 'Bottom':
                i = 'Top';
                value = '-' + bounds.Bottom;
                expression = 'parseInt(document.documentElement.clientHeight) - ';
                expression += parseInt(currentStyle.height) + ' + ';
                break;
            case 'Right':
                i = 'Left';
                value = '-' + bounds.Right;
                expression = 'parseInt(document.documentElement.clientWidth) - ';
                expression += parseInt(currentStyle.width) + ' + ';
                break;
        };

        style.setExpression
        (
            i.toLowerCase(),
            '(parseInt(document.documentElement.scroll'+ i + ') + ' +
            expression + parseInt(value) + ')' + ' + "px"'
        );

    };

    style.behavior = null;
    style = currentStyle = null;
};
</script>
</public:component>

使い方は以下のようにスタイルシートを記述。

<style type="text/css">
#fixed
{
     position: fixed;
     top: 100px; left: 100px;
     behavior: url('fixed.htc'); /* ←今回はここがポイント */
}
</sytyle>

注意として

上のコードでは互換モードでは動作しない。あと試作品。ソースが汚いので訂正する。あとIE7でもこのコードが動作してしまう。

今後の予定

バグとりしてライブラリとして公開します。