サイバーセキュリティを勉強していく漢

【jquery・css】”position: fixed;”を任意の場所で止める

cssfixedjavascriptjquerypositionscroll

“position: fixed;”を使用してヘッダー等をウィンドウに固定させたはいいものの、これ以上はついてこないで!って場面があった。

headerを縦に使用して横に配置したら、縦長だからfooterを侵食されたので、jsで制御する。

$(window).scrollTop()のみでは不安定

$(window).scrollTop()とか使って、headerを止めたいところ以降からスクロールした分topを引いていけばいいかななんて安易に考えてたら、思い通りにいかずにだいぶ時間がかかってしまった。

何も考えずにコードを書くと、早いスクロールに追いつけなくてheaderのtopが大きくなりすぎたり、小さくなりすぎたり(超マイナス)なったりする。

静的な特定の場所を起点にしてfixedを制御する。

今回は、headerのbottomをコンテンツ2のbottom以降にはいかないように制御した。

これは、headerの可動範囲を上から計った形。

下から計ると、footerより50px上ってことになった。

どっちでもいいと思う。

上限と下限を指定

topが大きすぎたり小さすぎたりする対策として、上限と下限をあらかじめ指定することでこれを阻止する。

下限を求める
//document(body)の高さ
var bodyHeight = $(document).height();
//一番上からcontents2のbottomの高さ
var contents2Bottom = $(".contents2").offset().top + $(".contents2").height();
//ヘッダーの高さ 状況によってouterHeight(true)とかinnerHeight()とか
var headerHeight = $(".header").height();
//画面の高さ
var displayHeight = $(window).height();

//下限
var minTopValue = bodyHeight - (contents2Bottom - headerHeight) - displayHeight + headerHeight;

これでいいはず。僕のは動いてるので・・・

上限を求める

あきらめた。

数値べたで書いた。

これらを踏まえて以下コード

$(function(){
    var nowScroll = $(window).scrollTop();
    var displayHeight = $(window).height();
    var bodyHeight = $(document).height();
    var headerHeight = $(".header").height();
    var headerBottom = $(".header").offset().top + headerHeight;
    var contents2Bottom = $(".contents2").offset().top + 350;
    //ヘッダーtopの最小値
    var minTopValue = bodyHeight - (contents2Bottom - headerHeight) - displayHeight + headerHeight;
    //ヘッダーtopの最大値
    var top = 50;
    //更新したときのヘッダーの位置を調整 
    if($(window).scrollTop() + headerHeight + 50 > contents2Bottom)
    {
        top = top + (-1 * ($(window).scrollTop() + headerHeight + 50 - contents2Bottom));
        $(".header").css("top", top+"px");
        $(".header").css("display", "block"); 
    }
    $(".header").css("display", "block"); 

    $(window).scroll(function()
    {
        //下にスクロールしたら
        if(nowScroll < $(window).scrollTop())
        {
            headerBottom = $(".header").offset().top + headerHeight;
            if(headerBottom > contents2Bottom)
            {
                diffirence = Math.abs(headerBottom - contents2Bottom);
                if(top - diffirence < -1*minTopValue)
                {
                    top = -1*minTopValue;
                }
                else
                {
                    top = top - diffirence;
                }
                $(".header").css("top", top+"px");
            }
            nowScroll = $(window).scrollTop();
        }
        //上にスクロールしたら
        else if(nowScroll > $(window).scrollTop())
        {
            headerBottom = $(window).scrollTop() + headerHeight + 50;
            if(headerBottom > contents2Bottom)
            {
                diffirence = Math.abs(nowScroll - $(window).scrollTop());
                if(top + diffirence > 50)
                {
                    top = 50;
                }
                else
                {
                    top = top + diffirence;
                }
                $(".header").css("top", top+"px");
            }
            else if(top < 50)
            {
                top = 50;
                $(".header").css("top", top+"px");
            }
            nowScroll = $(window).scrollTop();
        } 
    });
});

12行目から19行目がないと、更新したときにヘッダーがfixedにしたがってついてきてほしくないところに来てしまうのを防ぐ記述。

ここでdisplay: none;をblock;にするので、デフォルトではnone;でcssを記述する必要がある。

ごちゃごちゃしててクールじゃなくなったけどまあいいや。