【jQuery】プラグイン使わずサイドバーのバナーを特定の位置まで固定にしてそのあと解除する

jQueryを使ってプラグインは一切使わずにサイドバーのバナーがとある位置までスクロールしたら固定(追従してくる)にして、さらに下の別の位置に来たら固定を解除する方法をご紹介します。

→動作デモはこちら
→ソースコードはこちら

これはメイン、サイドメニューの両方を並べて表示する2カラムのWebサイト(PC版)で使用する事を想定しています。スマホやタブレットで主に用いられる1カラムの場合は固定の設定はしないという事を行います。

jQuery(JavaScript)を使ってプログラミングしていくのですが、先にHTMLとCSSの下準備をします。

<header class="mob"></header>
<div class="wrap">
  <main>
    <p>テキスト</p>
    <div style="height:700px; background:#f1f1f1;"></div>
    <p>テキスト</p>
    <p>テキスト</p>
    <div id="release_point_obj">
      固定解除のポイント
    </div>
    <p>テキスト</p>
    <div style="height:800px; background:#f1f1f1;"></div>
    <p>テキスト</p>
    <p>テキスト</p>
  </main>
  <div id="side">
    <p>テキスト</p>
    <div style="height:200px; background:#f1f1f1;"></div>
    <p>テキスト</p>
    <div id="fixed_obj">
       <img src="https://placehold.jp/250x150.png">
       <p>固定バナー</p>
       <p>固定バナー</p>
    </div>
  </div>
</div>
<footer class="mob"></footer>

重要なのは「固定解除のポイント」にidを付ける事と、「固定にしたい要素(固定バナー)」にもidをつける事です。これによってjQuery(JavaScript)で操作できるようにします。
クラスでも良いがidとクラスではidの方が処理が早いとされています。但しidはページ内で一つだけにしましょう。複数になりそうならクラスで作ります。

次にCSSです。

#fixed_obj {
  left: auto;
  right: auto;
  bottom: auto;
}
#side {
  position: relative;
  width: 20%;
}

/* レイアウト・他調整 */
mob {
  background:#f1f1f1;
  padding:50px;
}
p {
  margin:3rem 0;
}
.wrap {
  display:flex;
  justify-content: space-around;
}
img {
  max-width: 100%;
}

重要なのは#sideに「position:relative」をつける事。
そして、「固定にしたい要素(fixed_obj)」に「left、right、bottom」に「auto」をつけて下さい。このautoはスクロール位置が大きくなりすぎた時やabsolute要素の横幅を絶対値にしなくても、画像などがはみ出すのを防ぐ為に書いてます。最後に「#side」に横幅を与えます。

いよいよjQueryでプログラミングしていきます。

$(function () {
    const fixed_obj = $('#fixed_obj');
    const fixed_obj_top = fixed_obj.offset().top;
    const release_point_obj = $('#release_point_obj');
    const offset_top = $('#side').offset().top;
});

扱う要素を変数に代入します。変数のデータ型は他にもvarやletなどがあります。今回は再代入や再宣言もしないのでconstで作ります。

続いて固定したり解除したりする関数を作ります。

function FixedBnr() {
    fixed_obj.css({
        'position':'sticky',
        'top':'0'
    });
}

function ReleaseBnr() {
    fixed_obj.css({
        'position':'absolute', 
        'top':release_point_obj.offset().top - offset_top
    });
}

function StaticBnr() {
    fixed_obj.css({
        'position':'static', 
        'top':'0'
    });
}

FixedBnr()は固定する時に使います。
ReleaseBnr()は解除ですね。StaticBnr()はデフォルトの状態に戻すのに使います。デフォルトの状態とはpositionプロパティを使わないという事です。
スマホやタブレットデバイスでの表示に関係します。

ここで使っているのはCSSをご存知の方ならお分かりになると思いますが、基本的にpositionをstickyにしたりabsouluteにしたりしてるだけですね。

absouluteにする時は、ある地点(release_point_objの位置)で固定解除となる時なので、topプロパティに固定表示が解除になる数値を入れなければなりません。解除する時にtop:0;などが入ると固定した要素が瞬間移動してしまいます。

そうならないように「release_point_obj.offset().top」という固定要素の上(body)からの距離を入れる訳です。

次は上記の3つの関数がいつ実行されるのか?
固定・固定解除・デフォルトの3つの切り替えタイミングの設定です。

$(window).on('scroll', function () {
    var top = $(window).scrollTop();
    const release_point = release_point_obj.offset().top - offset_option;
    if (pc) {
        if (top >= fixed_obj_top && top <= release_point) {
            FixedBnr();
        }
        if (top > release_point) {
            ReleaseBnr();
        }    
    } else {
        StaticBnr();
    }
});
$(window).on('scroll', function (){}

これはスクロールする度にという意味です。

const release_point = release_point_obj.offset().top;

release_pointという変数を宣言しました。
その変数に固定を解除したい要素の上(body)からの距離を入れています。
例えばこの距離が1200pxであれば、1200pxスクロールしするを固定解除が行わるようにしたい訳です。

if (pc) {}

これはPC(2カラム)の時だけ行いますよという意味です。
スマホやタブレットなどの1カラム時には、固定にしたり固定解除をしたりをする必要はないというのを前提にしています。

else {}

この鉤括弧の中に入れることで、PC以外の時に実行するという意味になります。

if (top >= fixed_obj_top && top <= release_point) {)

“もしtop変数(どのくらいスクロールしたか?)がfixed_obj_top変数より大きく、さらにrelease_point変数より小さい時” という意味になります。
この状況は固定したい要素が見切れる状態になるので、FixedBnr()関数 = ‘position’:’absolute’を実行したい訳です。

if (top > release_point) {}

“もしtop変数が固定解除したい要素に到達したら”という意味になります。top変数は「どのくらいスクロールしたか?」というスクロール量です。

固定解除したい要素が一番家から1500pxの位置にあったのならば、1500pxスクロールした時に、固定解除したいという意図ですね。
そこでReleaseBnr()を実行します。

ここまで来ればStaticBnr()の説明は不要かもしれません。
デフォルトの状態、psitionプロパティにstatic(静的)を与え、topプロパティを0にすれば、固定・固定解除を無効にできます。

一つ言い忘れていました。PC版とそれ以外(スマホ・タブレット)のレスポンシブに対応する為に以下の記述が必要です。

const breakPoint = 800;
let pc;
$(window).on('load resize', function () {
    if ($(window).width() <= breakPoint) {
        pc = false;
    } else {
        pc = true;
    }
});

breakPoint変数に800pxを入れてます。これはレスポンシブ時のブレイクポイントに合わせて下さい。

$(window).on('load resize', function (){}

これはページが読み込まれた時か、ウィンドウがリサイズされた時に実行、という意味です。

if ($(window).width() <= breakPoint)

ウィンドウサイズがbreakPoint変数を下回っていれば、それはタブレット・スマホのデザイン(1カラム)を適用したいので、pc変数をfalseにします。それ以外(801px以上)の時はpc変数をtrueにして、FixedBnr()やReleaseBnr()関数を実行します。

サイドバーを固定にするプラグインは存在しますが、既存のWebサイトに導入する事ができないケースなどもあるかと思います。プラグインで済めばそれが一番早くスマートかもしれませんが、そうした事ができない場合やはり一から自分でプログラミングをして機能を追加していく必要があります。

いかがだったでしょうか。この記事では「プラグイン使わずサイドバーのバナーを特定の位置まで固定にしてそのあと解除する」をご紹介しました。お役に立てれば幸いです。

→動作デモはこちら
→ソースコードはこちら


投稿日

最終更新日

カテゴリー:

投稿者:

タグ: