jQuery＋CSS3でスクロールしたときに、ナビゲーションヘッダーを固定する方法

# はじめに

弊社の一部のサービス・ページで使用している、
<font color="#79b74a">**スクロールしたときに、ナビゲーションヘッダーを固定する方法**</font>をご紹介したいと思います:grinning:
<font color="gray">（本記事用に若干修正いたしました）</font>


固定する方法は、2パターン

- **タブ切り替えでコンテンツに移動するパターン**
- **アンカーリンクでコンテンツに移動するパターン**

ページの構成によって、使い分けています。

# 実装方法

head内にjQueryを読み込ませます。

```html:html5
<script src="https://code.jquery.com/jquery-1.10.1.min.js"></script>
```
## 【パターン1】 タブ切り替えでコンテンツに移動するパターン



![1.png](https://qiita-image-store.s3.amazonaws.com/0/54595/84b7c281-1e89-5c0f-e1ff-40ed1ebdc5a4.png)



###  <i class="fa fa-code"></i> **javascript**

```js:javascript：タブ切り替え
<script>
	$(function() {
		// タブの切替
		$(".tab__block a").click(function() {
			$(".tab__block a").removeClass("select"); // classを削除
			$(this).addClass("select"); // クリックしたナビゲーションにclassを追加
			$("html,body").animate({scrollTop:$("#top").offset().top}); // コンテンツ上部までスクロール
			var num = $(".tab__block a").index(this);
			$(".wrap").removeClass("select"); // classを削除
			$(".wrap").eq(num).addClass("select"); // コンテンツにclassを追加し、表示を切り替える
		});
		
		// ヘッダーを固定
		var bt = $("#nav").offset().top; // ページ上からの距離を取得
		var ds = 0;

		$(document).scroll(function(){ // スクロール発生時の処理の記述を開始
			ds = $(this).scrollTop(); // スクロールした距離を取得
			if (bt <= ds) {  // スクロール距離がnavの位置を超えると
				$("#nav").addClass("follow"); // classを追加
			} else if (bt > ds) { // スクロールがページ上まで戻ると、
				$("#nav").removeClass("follow"); // classを削除
			}
		});
	});
</script>
```
- タブ`<a>`をクリックすると、`class="select"`が追加され、コンテンツ上部まで移動します。また違うタブ`<a>`をクリックすると、別のコンテンツの上部に移動します。
- スクロールイベントが始まると、スクロールした距離を取得します。ヘッダーの距離まで移動すると、`id="nav"`に`class="follow"`が追加され、`position: fixed; top: 0;`が付与され固定されます。スクロールがヘッダーより上に戻ると、`id="nav"`の`class="follow"`が削除され、固定されなくなります。

###  <i class="fa  fa-css3"></i> **Sass**


```sass:Sass
// ナビの高さ
$navi_height: 68px;

.body {
	position: relative;
	// ナビ
	.tab__block {
		position: absolute;
		top: 0;
		box-sizing: border-box;
		width: 100%;
		height: $navi_height;
	}
	.tab {
		a.select {
			// 選択時の指定
		}
	}
	// コンテンツを囲む
	.wrap {
		display: none;
		padding-top: $navi_height;
		&.select {
			display: block;
		}
	}
}

// スクロールで付加される
.follow {
	position: fixed! important;
	top: 0! important;
	z-index: 10;
	width: 100%;
}
```
- `$navi_height`にナビゲーションの高さを指定します
- ※装飾部分は省略しています

###  <i class="fa  fa-html5"></i> **HTML**



```html:html5：タブ切り替え
<header><!-- メインビジュアルはこの位置 --></header>
<div class="body" id="top">
	<div id="nav" class="tab__block">
		<ul>
			<li class="tab"><a href="javascript: void(0);" class="select">AAA</a></li>
			<li class="tab"><a href="javascript: void(0);">BBB</a></li>
			<li class="tab"><a href="javascript: void(0);">CCC</a></li>
			<li class="tab"><a href="javascript: void(0);">DDD</a></li>
			<li class="tab"><a href="javascript: void(0);">EEE</a></li>
		</ul>
	</div>
	<div class="wrap select">
		<p>AAA</p>
	</div>
	<div class="wrap">
		<p>BBB</p>
	</div>
	<div class="wrap">
		<p>CCC</p>
	</div>
	<div class="wrap">
		<p>DDD</p>
	</div>
	<div class="wrap">
		<p>EEE</p>
	</div>
</div>
```
- 初期表示するコンテンツには、`class="select"`を指定しておきます。
- ※装飾部分は省略しています

## 【パターン2】 アンカーリンクでコンテンツに移動するパターン

![2.png](https://qiita-image-store.s3.amazonaws.com/0/54595/46fbca1f-b7df-8504-385d-5c20b6f1789a.png)



###  <i class="fa  fa-code"></i> **javascript**

```js:javascript：アンカーリンク
<script>
	$(function() {
		// #で始まるアンカーをクリックした処理
		$('a[href^=#]').click(function() {
			var headerHight = 68; // 固定ヘッダーの高さ
			var speed = 400; // スクロールの速度ミリ秒
			var href= $(this).attr("href"); // アンカーの値取得
			var target = $(href == "#" || href == "" ? 'html' : href); // 移動先を取得
			var position = target.offset().top-headerHight; // 移動先を数値で取得
			$('body,html').animate({scrollTop:position}, speed, 'swing'); // スムーススクロール
			return false;
		});

		// ヘッダーを固定
		var bt = $("#nav").offset().top; // ページ上からの距離を取得
		var ds = 0;

		$(document).scroll(function(){ // スクロール発生時の処理の記述を開始
			ds = $(this).scrollTop(); // スクロールした距離を取得
			if (bt <= ds) {  // スクロール距離がnavの位置を超えると
				$("#nav").addClass("follow"); // classを追加
			} else if (bt > ds) { // スクロールがページ上まで戻ると、
				$("#nav").removeClass("follow"); // classを削除
			}
		});
	});
</script>
```

- タブ`<a>`をクリックすると、アンカーリンク先の値を取得し、コンテンツ上部まで移動します。また違うタブ`<a>`をクリックすると、別のコンテンツの上部に移動します。
- スクロールイベントが始まると、スクロールした距離を取得します。ヘッダーの距離まで移動すると、`id="nav"`に`class="follow"`が追加され、`position: fixed; top: 0;`が付与され固定されます。スクロールがヘッダーより上に戻ると、`id="nav"`の`class="follow"`が削除され、固定されなくなります。



###  <i class="fa  fa-css3"></i> **Sass**


```sass:Sass
// ナビの高さ
$navi_height: 68px;

.body {
	position: relative;
	// ナビ
	.tab__block {
		position: absolute;
		top: 0;
		box-sizing: border-box;
		width: 100%;
		height: $navi_height;
	}
	// コンテンツを囲む
	.wrap {
		padding-top: $navi_height;
	}
}

// スクロールで付加される
.follow {
	position: fixed! important;
	top: 0! important;
	z-index: 10;
	width: 100%;
}
```
- `$navi_height`にナビゲーションの高さを指定します
- ※装飾部分は省略しています


###  <i class="fa  fa-html5"></i> **HTML**

```html:html5：アンカーリンク
<header><!-- メインビジュアルはこの位置 --></header>
<div class="body" id="top">
	<div id="nav" class="tab__block">
		<ul>
			<li class="tab"><a href="#AAA">AAA</a></li>
			<li class="tab"><a href="#BBB">BBB</a></li>
			<li class="tab"><a href="#CCC">CCC</a></li>
			<li class="tab"><a href="#DDD">DDD</a></li>
			<li class="tab"><a href="#EEE">EEE</a></li>
		</ul>
	</div>
	<div class="wrap">
		<div id="AAA" class="content">
			<p>AAA</p>
		</div>
		<div id="BBB" class="content">
			<p>BBB</p>
		</div>
		<div id="CCC" class="content">
			<p>CCC</p>
		</div>
		<div id="DDD" class="content">
			<p>DDD</p>
		</div>
		<div id="EEE" class="content">
			<p>EEE</p>
		</div>
	</div>
</div>
```
- ※装飾部分は省略しています