見出し画像

【JS】固定ヘッダー付きページのページ内スクロール

ページ内のアンカーへなめらかにスクロールする”あれ”です。
固定ヘッダーがあると通常のページ内リンクでは位置がずれて見えなくなってしまうので調整が必要になります。
位置の調整ついでにスムーススクロールで対応しました。

またアンカー付きで外部からリンクされているときにも正しく位置調整が動くように対応しました。

注意事項

  • jQueryで処理しているのでjQueryの読み込みをしてください。

  • サンプルファイルにはダミー文章を使用しています。
    ダミーテキストの作成は以下のサイトを利用しました。https://lipsum.sugutsukaeru.jp

  • デザイン・レイアウトのセンスはないので参考にはしないでください。

順を追って解説していきますがすぐに利用したい方は最後にサンプルファイルをまとめてありますのでダウンロードしてご利用ください。

まずは普通のページ内スクロール

// アンカー付きリンクをクリックしたときの処理
$('a[href*="#"]').click(function(){
	scroll_to($(this).prop("hash"));
	return false;
});

// ページ内スクロール
// hashに指定された要素へスクロールする
function scroll_to(hash){
	var target = $(hash == "#" || hash == "" ? 'html' : hash);
	if (target.length > 0)
	{
		var position = target.offset().top;
		$("html, body").animate({scrollTop:position}, 'slow');
		return false;
	}
}

ハッシュ'#'が含まれるリンクをクリックしたときに対象がページ内にあればそこへスクロールします。
無駄にスクロール処理部分を関数化しているように見えますが、後で使う際に便利なので関数化しています。

// ヘッダーの高さ取得(id=headerの要素のマージン/パディングを含む高さを取得)
var header_height = $('#header').outerHeight(true);


// ページ内スクロール
// hashに指定された要素へスクロールする
function scroll_to(hash){
	var target = $(hash == "#" || hash == "" ? 'html' : hash);
	if (target.length > 0)
	{
		var position = target.offset().top;
		$("html, body").animate({scrollTop:position - header_height}, 'slow');
		return false;
	}
}

固定ヘッダーがある場合の位置調整を入れたものです。固定ヘッダーの高さはid=headerの要素から自動取得します。直接、変数header_heightに高さを代入して使用も良いです。

外部からアンカー付きリンクでのアクセス

// ハッシュ付きURLでアクセスしてきたときの処理
$(window).on('load', function(){
	if (location.hash)
	{
		scroll_to(location.hash);
	}
});

ページが表示されたときにハッシュ付きURLであればページ内リンクの処理と同じようにスクロールします。

ブラウザが先に該当位置までスクロール位置を変更していることがありますがこの処理を制御することができません。そのため後から動くスクリプトは位置を戻すように逆にスクロールしていきます。かっこ悪いですが仕様です。

細かい調整

// アンカー付きリンクをクリックしたときの処理
// ページ内リンクのときだけクリック動作をキャンセルしてスクロール処理をする
$('a[href*="#"]').click(function(){
	if (location.href.replace(/#.*$/, '') == $(this).prop("href").replace(/#.*$/, ''))
	{
		scroll_to($(this).prop("hash"));
		return false;
	}
});

ハッシュ付きのリンクをクリックしたときにそれが別のページだった場合、意図しない動作となることがあるため、ページ内のときだけスクロール処理をするようにします。

// ページ内スクロール
// hashに指定された要素へスクロールする
function scroll_to(hash){
	var target = $(hash == "#" || hash == "" ? 'html' : hash);
	if (target.length > 0)
	{
		var position = target.offset().top;
		$("html, body").animate({scrollTop:position - header_height}, 'slow', function(){
			// スクロール後URLの表示を変更する
			location.hash = hash.substr(1);
		});
		return false;
	}
}

またスクロールした後にURLのハッシュを変更した方が都合が良いので対応します。

完成

以下、完成したスクリプトの全体ソースです。

jQuery(function($) {
	// ヘッダーの高さ取得(id=headerの要素のマージン/パディングを含む高さを取得)
	var header_height = $('#header').outerHeight(true);

	// アンカー付きリンクをクリックしたときの処理
	// ページ内リンクのときはクリック動作をキャンセルしてスクロール処理をする
	$('a[href*="#"]').click(function(){
		if (location.href.replace(/#.*$/, '') == $(this).prop("href").replace(/#.*$/, ''))
		{
			scroll_to($(this).prop("hash"));
			return false;
		}
	});

	// ハッシュ付きURLでアクセスしてきたときの処理
	// 画像等を読み込んだ後にスクロール処理をする
	// すでに移動している場合は逆スクロールする
	$(window).on('load', function(){
		if (location.hash)
		{
			scroll_to(location.hash);
		}
	});

	// ページ内スクロール
	// hashに指定された要素へスクロールする
	function scroll_to(hash){
		var target = $(hash == "#" || hash == "" ? 'html' : hash);
		if (target.length > 0)
		{
			var position = target.offset().top;
			$("html, body").animate({scrollTop:position - header_height}, 'slow', function(){
				// スクロール後URLの表示を変更する
				location.hash = hash.substr(1);
			});
			return false;
		}
	}
});

上記スクリプトソースとサンプルファイルをまとめました。ご自由にお使いください。



いいなと思ったら応援しよう!