【css、js】ハンバーガーメニュースニペット

# ハンバーガーメニュースニペット
よく使用するハンバーガーメニュースニペットです。

仕様

1. sp時CTAボタン+ハンバーガーメニュー
1. pc時横並びで展開
1. ハンバーガーメニュー開いている時、背景スクロール防止
1. 背景クリックでもハンバーガーメニュー閉じる


<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="jOzLdPY" data-user="__m-sato__" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/__m-sato__/pen/jOzLdPY">
  ハンバーガーメニュー</a> by __m-sato__ (<a href="https://codepen.io/__m-sato__">@__m-sato__</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## html

```html
<body>
	<header>
		<h1 class="logo_wrap">
			<a href="#">logo</a>
		</h1>

		<nav id="js-nav" class="header_nav_menu">
			<ul class="nav_menu_list">
				<li class="nav_menu_item"><a href="">メニュー</a></li>
				<li class="nav_menu_item"><a href="">メニュー</a></li>
				<li class="nav_menu_item"><a href="">メニュー</a></li>
				<li class="nav_menu_item"><a href="">メニュー</a></li>
				<li class="nav_menu_item"><a href="">お問合せ</a></li>
			</ul>
		</nav>

		<div class="header_contact_hamburger_wrap">
			<a class="header_contact_sp" href="#">お問合せ</a>
			<button class="header_hamburger" id="js-hamburger">
				<span></span>
				<span></span>
				<span></span>
			</button>
		</div>
	</header>
	<div class="background" id="js-background"></div>

	<main>
		メイン
	</main>
</body>
```
## sass

```style.scss
@charset "UTF-8";

* {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}
a {
	text-decoration: none;
	color: black;
}
li {
	list-style: none;
}


main {
	background-color: #edede5;
	padding: 500px 0;
	text-align: center;
	position: relative;
}

/* ヘッダー */
header {
	background-color: white;
	width: 100%;
	height: 50px;
	position: fixed;
	top: 0;
	left: 0;
	z-index: 100;
	padding: 0 20px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	box-shadow: 0 2px 3px rgba($color: #000000, $alpha: .06);
	@media screen and (min-width: 960px) {
		height: 70px;
	}
}

.logo_wrap {
	height: 100%;
	a {
		height: 50px;
		display: block;
		width: 80px;
		text-align: center;
		@media screen and (min-width: 960px) {
			width: 120px;
			height: 70px;
			line-height: 70px;
		}
	}
}

.header_nav_menu {
	position: absolute;
	left: 0;
	top: 0;
	z-index: 50;
	width: 100%;
	transform: translateY(-100%);
	background-color: #fff;
	transition: transform ease .4s;
	@media screen and (min-width: 960px) {
		position: static;
		transform: initial;
		height: inherit;
		display: flex;
		justify-content: end;
		width: 50%;
	}
	&.active {
		transform: translateY(0);
	}
 }

.nav_menu_list {
	padding: 100px 20px;
	@media screen and (min-width: 960px) {
		width: 100%;
		display: flex;
		align-items: center;
		height: initial;
		justify-content: space-between;
		padding: 0;
	}
}

.nav_menu_item {
	@media screen and (min-width: 960px) {
		width: calc(100% / 5 - 20px);
	}
	a {
		width: 100%;
		display: block;
		font-size: 15px;
		border-bottom: 1px solid #c3c3c3;
		padding: 20px 0;
		@media screen and (min-width: 960px) {
			text-align: center;
			padding: 0;
			border: none;
		}
	}
}


.header_contact_hamburger_wrap {
	display: flex;
	align-items: center;
	@media screen and (min-width: 960px) {
		display: none;
	}
}

.header_contact_sp {
	display: block;
	height: 40px;
	width: 100px;
	text-align: center;
	line-height: 40px;
	background: #c3c3c3;
	color: #fff;
	border-radius: 5px;
	margin-right: 20px;
}

/* ハンバーガーメニュー */
.header_hamburger {
	width: 35px;
	height: 100%;
	background-color: transparent;
	border-color: transparent;
	z-index: 100;
	span {
		width: 100%;
		height: 1px;
		background-color: #000;
		position: relative;
		transition: transform ease .4s;
		display: block;
		&:nth-child(2) {
			margin: 8px 0;
		} 
	}
	//ハンバーガーメニュークリック後のスタイル
	&.active {
		span {
			&:nth-child(1) {
				top: 9px;
				transform: rotate(45deg);
			}
			&:nth-child(2) {
				opacity: 0;
			}
			&:nth-child(3) {
				top: -9px;
				transform: rotate(-45deg);
			}
		}
	}
}

/* 背景 */
.background {
	display: none;
	position: fixed;
	top: 0;
	left: 0;
	content: "";
	width: 100vw;
	height: 100vh;
	z-index: 50;
	background: rgba($color: #000000, $alpha: .6);
	&.active {
		display: block;
	}
}
```
## js

```script.js
const hamburger = document.getElementById('js-hamburger');
const nav = document.getElementById('js-nav');
const bg = document.getElementById('js-background');

const toggleMenu = function () {
  if (hamburger.classList.contains("active") === true) {
    hamburger.classList.remove("active");
    nav.classList.remove("active");
    bg.classList.remove("active");
    document.querySelector("body").style.removeProperty("overflow");
    document.querySelector("body").style.removeProperty("height");
  } else {
    hamburger.classList.add("active");
    nav.classList.add("active");
    bg.classList.add("active");
    document.querySelector("body").style.overflow = "hidden";
    document.querySelector("body").style.height = "100%";
  }
};

    hamburger.addEventListener('click', () => toggleMenu());
    bg.addEventListener('click', () => toggleMenu());

```