こんにちは、T田です。
インターネットのサイトを見ていると、画面をある程度スクロールするとサイドバーや画面上部のメニューが固定されるページを見かけませんか?

今回は、それを特別なライブラリを使わないで実現する方法をお伝えします。

目次

  1. はじめに
  2. 実際のページとソースコード
  3. 処理概要とソースコード解説
  4. JQueryを使用しない場合
  5. おわりに

1.はじめに

このページをPCやタブレットなどの横長の画面で見ていただいている方は、サイドバーにSNSのボタンが
表示されているはずです。
これらのボタンも、画面をある程度スクロールすると画面上部に固定されるようになっています。
これは、記事を最後まで読んでいただいた方にボタンを押していただく機会を逃さないようにするためです。

SNSのボタン以外にも、ヘッダメニューやフッタメニューを固定する方法にも応用できますので
ぜひ参考にしていただければと思います。

2.実際のページとソースコード

まずはどんなことをしようとしているのか、以下のボタンから実際にページを見てみてください。

 
画面をある程度スクロールすると、「ここが固定されます」と表示されている要素が画面上部に固定されると思います。
これを実現しているのが、以下のソースコードです。

HTML


CSS


JavaScript


 
HTMLの操作対象は、id属性値が「area-1」「menu_bar」「area-2」の3つのdiv要素です。
これらのソースコードを、それぞれ順に解説していきます。

3.処理概要とソースコード解説

処理概要は以下のとおりです。

イ.画面全体の縦スクロール量(A)と、固定したい要素の位置(B)を取得する
ロ.AとBの値を比較し、その結果によってスタイルシートを切り替える
ハ.操作した要素の位置やサイズを調整する
ニ.これらの処理をスクロールイベントで実行する

イ.画面全体の縦スクロール量(A)と、固定したい要素の位置(B)を取得する

これを実装しているのが、JavaScriptの9行目と12行目です。

	// 画面のy座標を取得
	var screen_Y = $( window ).scrollTop();

	//メニューバー上部要素下辺のy座標を取得
	var area_1_Y = area_1.offset().top + area_1.height();

まず、画面全体の縦スクロール量(A)をwindowsオブジェクトのscrollTop()メソッドで取得しています。
次に固定したい要素「menu_bar」の位置(B)ですが、こちらは少し工夫が必要です。
「menu_bar」そのものの位置を取得してしまうと、その要素が画面上部に固定された際に値が0になり、それ以降ずっと値が変わらなくなってしまいます。
それを防ぐため、「menu_bar」の直前の要素である「area-1」の下辺y座標を、固定したい要素の位置(B)としています。

ロ.AとBの値を比較し、その結果によってスタイルシートを切り替える

これを実装しているのが、JavaScriptの16~21行目です。

	// 各y座標を比較してcssを切替
	var area_2_top = 0;
	if ( screen_Y >= area_1_Y ) {
		menu_bar.addClass( "fixed" );
		area_2_top = menu_bar.height();
	} else {
		menu_bar.removeClass( "fixed" );
	}

画面全体の縦スクロール量(A)が固定したい要素の位置(B)を超えた場合に、addClass()メソッドで「menu_bar」要素のclass属性に「fixed」を追加しています。
逆に画面全体の縦スクロール量(A)が固定したい要素の位置(B)を超えていない場合は、removeClass()メソッドで「menu_bar」要素のclass属性から「fixed」を削除しています。

このfixedクラスのソースコードは以下のようになっています。

.fixed {
	position : fixed;
	top : 0px;
	z-index : 999;
}

各行の意味は以下のとおりです。
position : fixed;:要素を絶対位置で指定かつスクロールしても固定されるようにする
top : 0px;:画面上部と要素の上部との距離を0pxに指定(画面上部に固定)
z-index : 999;:要素が常に表に表示されるように重なり順を指定

ハ.操作した要素の位置やサイズを調整する

これを実装しているのが、JavaScriptの24~25行目です。

	// 各y座標を比較してcssを切替
	var area_2_top = 0;
	if ( screen_Y >= area_1_Y ) {
		menu_bar.addClass( "fixed" );
		area_2_top = menu_bar.height();
	} else {
		menu_bar.removeClass( "fixed" );
	}

	// 各要素のサイズ・位置調整
	menu_bar.width( area_1.width() );
	area_2.css( "top", area_2_top );

addClass()メソッドでスタイルシートを切り替えたときに、固定する要素「menu_bar」の横幅が変わってしまいました。
そこで、width()メソッドで毎回「menu_bar」要素の横幅を指定しています。
 
また25行目の処理ですが、これは見た目を滑らかにするために入れています。
スタイルシートが切り替わると「menu_bar」要素が画面上部に移動して固定されるため、その直後の要素である「area-2」が「menu_bar」要素の高さ分、上にずれる形になります。
その際、見た目がカクカクして見にくくなってしまいます。
そこで「menu_bar」要素が固定されたときは、「area-2」要素の上部に「menu_bar」要素の高さ分の距離を空けるようにしています。

ニ.これらの処理をスクロールイベントで実行する

これを実装しているのが、JavaScriptの1行目です。

$( window ).scroll( function()
{
	// メニューバーとその上下の要素を取得
	var menu_bar = $( "#menu_bar" );
	var area_1 = $( "#area-1" );
	var area_2 = $( "#area-2" );

windowsオブジェクトのscrollイベント時に、これらの処理が実行されるようにしています。

4.JQueryを使用しない場合

JQueryが使えない、もしくは使いたくない場合もあると思います。
そんな場合も想定してJQueryを使わないで実現するソースコードも載せておきます。
行っている処理はJQueryを使用しているソースコードと同じです。



5.おわりに

今回は、特別なライブラリを使わないでHTML要素を固定する方法についてお伝えしましたが、いかがでしたでしょうか。
少しでも参考になれば幸いです。
ではまた次のブログでお会いしましょう!


<スポンサーリンク>