黒ブタBLOG

【jQuery】コピペでOK!スクロールで固定、解除されるBOXを配置する方法

こんばんは、黒ブタです。
最近のサイトで使われている技術ですが、今回はスクロールすると開始するイベントを紹介したいと思います。
サイドバーやヘッダーのナビでよく見かけますね。
どういったものかと言いますと、Facebookのサイドなどでスクロールすると固定されるBOXと言えばわかると思います。
特定の位置までスクロールするとサイドにあるボックスが固定され、さらにスクロールして一定の位置に到達すると解除されるアレです。
さてさて、早速コードを書いていきます。

・・・の前にDEMOを作ったので見てみましょう。
※DEMOはPCで見た場合のみでスマホ用には整えていません。
レスポンシブ対応にはしていますが、Android4.2以下はcssのflexに対応していないので、現在はAndroidの為にもflexを使っている要素はスマホで読み込みCSSを変更してリストで並べるように対策しましょう。
対策方法はCSS3のMedia Queries(メディアクエリ)等を利用し、使い分けましょう。
なぜ対策するか・・・・Androidのバージョンが4.2以上に移行したのはまだまだ最近(2年以内)で、4.2以下のバージョンのAndroid携帯を使っている方が沢山いる。最低でも基本の2年買い替えを考えて、余裕を持って3年は対策しましょう。

DEMO

今回はナビをトップから150pxスクロールで固定に、1000pxスクロールで固定を解除するというプログラムです。
もちろんnavでは無く、div要素でもなんでも可能です。

準備として必要なのはheadにJQueryとreset.cssを読み込んでおいてください。
Queryはこれがいいかな?

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

さて、コードを書いていきます。
まずはhtmlに記述

<body>
<header class="clearfix">
<h1 class="logo">header</h1>
</header>
<nav>
<ul>
<li>NAVI1</li>
<li>NAVI2</li>
<li>NAVI3</li>
<li>NAVI4</li>
</ul>
</nav>
<div id="content">
<p class="position">現在位置</p>
</div>
<footer class="clearfix">
<p>footer</p>
</footer>
</body>

続いてCSS
CSSは少ないのでheadに書き込みます。

<style>
header {width: 100%;height: 150px; line-height:150px;color: #333;background:rgba(253,239,213,1.00); text-align:center; font-size:250%;}
footer{ height:90px;background:rgba(57,39,9,1.00); color:rgba(245,245,245,1.00); font-size:250%; text-align:center; padding:40px 0 20px;}
nav {width: 100%;color:rgba(245,245,245,1.00);background:rgba(57,39,9,1.00);}
nav.fixed {position: fixed;left: 0;top: 0;}
ul { display:flex;justify-content: center;}
ul li { height:24px; line-height:24px;padding: 10px 20px;border-left: 1px solid #666;}
#content {height: 2000px;background:rgba(253,239,213,1.00);}
#content .position{ padding-top:20px; text-align:center;}
</style>

最後にjQueryを書き込み。
これも量が少ないのでhtmlのheadに書き込みます。

<script>
$(function() {
var content = $("#content");//基準となる場所を定義(今回はメインコンテンツ)
var head_nav_height = 44;//ヘッダーナビの高さ
var release =1000;//固定を解除するイベント開始位置
var p = $("#content p.position");//コメントで位置の確認(本番では不要)
var offset = content.offset();//定義した要素のドキュメント上での表示位置
var offset2= offset.top - head_nav_height;//スクロールで固定BOXに変更する為のイベント開始位置
p.html("メインコンテンツ(#content)のTOPからの位置確認" + "<br> left: " + offset.left + ", top: " + offset.top + "px" + ", ナビの高さ:" +head_nav_height + "px" );//コメントで位置の確認(本番では不要)
$(function() {
//ロード or スクロールされると実行
$(window).on('load scroll', function(){
if ($(window).scrollTop() > offset2 && $(window).scrollTop() < release ) {//ページのトップから任意の高さ分スクロール(メインコンテンツの位置到達)するとナビにfixedクラスを追加
$('nav').addClass('fixed');
} else {
//TOPからの位置が(スクロール量が)ヘッダーの高さ(今回は150px)以下または1000px以上だとfixedクラスを削除
$('nav').removeClass('fixed');
}
});
});
});
</script>

以上でスクロールで固定、解除されるBOXの設置ができました。

DEMOページも用意してるので確認してください。

DEMO

まだまだ改良が沢山出来そうなのでちょこちょこ変更していきます。