スクロールしても固定表示されるサイドバーで誤作動が1番少なかったのはこれ!

2017-12-16 @niketcha

サイドバーを固定する方法を色々なサイトで調べて試してみたのですが、そのほとんどが何かしら誤作動するものばかりでした。

途中でサイドバーが消えてしまったり、サイドバーの横位置がずれたり幅が変わってしまったり、固定する範囲がおかしくなったり。

仕方なく諦めかけていたところ、これだ!と思えるものを見つけたので紹介します。

Sponsored Link

固定表示のサイドバー実装方法

STINGER8の人は親テーマのscroll.jsを直接編集してもいいのですが、アップデートがあったときどうなるのかわからないので、子テーマに新しくjsファイルを作ります。

子テーマを利用していない方は親テーマを直接編集するか、以前投稿したWordPress子テーマの作り方という記事を参考にして子テーマを導入してください。

sidebar.phpの修正

子テーマディレクトリにsidepar.phpがない場合、親テーマのsidepar.phpを一旦ローカルに落とし、子テーマディレクトリにアップロードします。

固定したいエリアを<div id="scrollfix"></div>で囲みます。STINGER8の人はid="scrollad"となっているところをid="scrollfix"に変えます。

STINGER8のscroll.jsはscrolladというIDの要素を探し、なければ処理をしないという内容になっています。scrolladをscrollfixにすることで親テーマのjsが無効になります。

cssの設定

cssファイルに下記の内容を追加します。
#scrollfix {
	padding: 20px 0;
}

jsファイルの作成

WordPressの子テーマディレクトリ(function.phpとかが置いてある場所)にjsフォルダがなければ作成し、scrollfix.jsなど名前はなんでもいいのですがjsファイルを作ります。

作ったjsファイルに下記のコードを書きます。

/*--------------------------------
広告のフロート
-------------------------------*/
// jQueryの開始方法を変更
$(function() {
    /*
    Ads Sidewinder
    by Hamachiya2. http://d.hatena.ne.jp/Hamachiya2/20120820/adsense_sidewinder
    */
    var main = $('.st-main'); // メインカラムのID
    var side = $('#side .st-aside'); // サイドバーのID
    var wrapper = $('#scrollfix'); // 広告を包む要素のID
	
    var w = $(window);
    if (w.width() <= 959){
        return;
    }
	
    // 要素がなければ何もしない
    if (main.length === 0 || side.length === 0 || wrapper.length === 0 ) {
        return;
    }
	
    var wrapperHeight = wrapper.outerHeight();
    var wrapperTop = wrapper.offset().top;
    var sideHeight = side.outerHeight();
    var sideTop = side.offset().top;
    var sideLeft = side.offset().left;


    var sideMargin = {
        top:    side.css('margin-top')    || 0,
        right:  side.css('margin-right')  || 0,
        bottom: side.css('margin-bottom') || 0,
        left:   side.css('margin-left')   || 0
    };

    var winLeft;
    var pos;

    var scrollAdjust = function() {

        // サイドバーかスクロール広告の高さが変わっていたら更新する
        // 広告が浮いてる状態で高さが更新されるとwrapperTopにズレが発生する可能性あり
        if (sideHeight != side.outerHeight() || wrapperHeight != wrapper.outerHeight()) {
            sideHeight = side.outerHeight();
            wrapperHeight = wrapper.outerHeight();
            wrapperTop = wrapper.offset().top;
        }
        var mainHeight = main.outerHeight();
        var mainAbs = main.offset().top + mainHeight;
        var winTop = w.scrollTop();
        winLeft = w.scrollLeft();
        var winHeight = w.height();
        // スクロール広告の頭が画面上部からはみ出そうで、メインコンテンツがサイドバーが長い=広告を浮かす必要がある
        var nf = (winTop > wrapperTop) && (mainHeight > sideHeight) ? true : false;
        // スクロール広告の頭からサイドバーが終わるまでの高さ
        var wrapperTop2SideBottomHeight = sideHeight - (wrapperTop - sideTop);
        /**
         * 浮かす必要が無いならstaticでそのまま。
         * 画面上部の高さ+広告以下の高さを合わせて、コンテンツの高さを超えるならabsoluteで終端を揃える。
         * それ以外はfixedで広告の頭を固定で浮かして表示する。
         */
        pos = !nf ? 'static' : (winTop + wrapperTop2SideBottomHeight) > mainAbs ? 'absolute' : 'fixed';
        if (pos === 'fixed') {
            /**
             * スクロール広告の下にコンテンツ置いても大丈夫なように上基準に変更
             * 広告の頭が画面上部に合うように引っ張り上げる。
             * サイドバーが開始する高さまでは除去しないとずれる。
             */
            side.css({
                position: pos,
                top: sideTop - wrapperTop,
                bottom: '',
                left: sideLeft - winLeft,
                margin: 0
            });

        } else if (pos === 'absolute') {
            side.css({
                position: pos,
                top: mainAbs - sideHeight,
                bottom: '',
                left: sideLeft,
                margin: 0
            });

        } else {
            side.css({
                position: pos,
                marginTop: sideMargin.top,
                marginRight: sideMargin.right,
                marginBottom: sideMargin.bottom,
                marginLeft: sideMargin.left
            });
            // ずれた時の為に、通常の領域に戻った時に再調整する
            wrapperTop = wrapper.offset().top; 
        }
    };

    var resizeAdjust = function() {

        side.css({
            position:'static',
            marginTop: sideMargin.top,
            marginRight: sideMargin.right,
            marginBottom: sideMargin.bottom,
            marginLeft: sideMargin.left
        });

        sideLeft = side.offset().left;
        winLeft = w.scrollLeft();
        if (pos === 'fixed') {
            side.css({
                position: pos,
                left: sideLeft - winLeft,
                margin: 0
            });

        } else if (pos === 'absolute') {
            side.css({
                position: pos,
                left: sideLeft,
                margin: 0
            });
        }
		
    };

	w.on('load', scrollAdjust);
   	w.on('scroll', scrollAdjust);
	w.on('resize', resizeAdjust);
});

こちらのサイトからお借りしたコードを少しだけ修正しました。

修正前はスマホやタブレットのときに変な挙動(一番下までいくと跳ね返ってくるような感じ)になり、その直し方がわからなかったのでPC以外では処理を行わないようにしました。 if (w.width() <= 959)の部分のとこです。959という幅はうちのサイトの場合なので、調整してください。

またマーカーを付けた2か所はSTINGER8を想定しているので、テーマに合わせて要素のIDまたはクラス名を指定してください。

jsファイルの読み込み

function.phpに下記のコードを書きます。

/**
* スクリプトをキューへ追加
*/
function enqueue_scrollfix_scripts() {

	wp_enqueue_script(
		'scrollfix',
		get_stylesheet_directory_uri() . '/js/scrollfix.js',
		array( 'jquery' ),
		false,
		true
	);
}
add_action( 'wp_enqueue_scripts', 'enqueue_scrollfix_scripts' );

これでjsファイルが読み込まれるようになりました。

最後に

この方法も1つ問題点があります。PCで表示後、1カラムになるまでウィンドウ幅を縮めて下までスクロールすると跳ね返ってくるのと、逆に狭い幅で表示後に広げた場合は固定されないということです。リサイズされたときに条件を入れればいいのでしょうが、レアケースなので放置してます。

-ウェブサイト構築, word press

コメントを残す

お名前もメールも入力は任意です。お気軽に指摘や質問などしていただけると嬉しいです。

Gravatarに登録すると、お好きな画像をアバターに設定できます。

Copyright© ニケッチャニッキ , 2017-2018 All Rights Reserved.