<nav class="nav">
<div class="nav__bar">
<button class="nav__toggle-btn">+</button>
</div>
<ul class="nav__toggle-menu">
<li><a class="nav__toggle-menu-item" href="#">Menu1</a></li>
<li><a class="nav__toggle-menu-item" href="#">Menu2</a></li>
<li><a class="nav__toggle-menu-item" href="#">Menu3</a></li>
<li><a class="nav__toggle-menu-item" href="#">Menu4</a></li>
</ul>
</nav>
.nav__bar {
background: #333;
color: #fff;
padding: 4px 12px;
}
.nav__toggle-btn {
display: block;
margin-left: auto;
color: #fff;
font-size: 24px;
cursor: pointer;
transition: transform 0.3s;
}
.nav__toggle-btn.is-open {
transform: rotate(45deg);
}
.nav__toggle-menu {
background: #555;
padding: 0 12px;
}
.nav__toggle-menu:not(.is-open) {
display: none;
}
.nav__toggle-menu.is-changing {
display: block;
overflow: hidden;
height: 0;
transition: height 0.3s;
}
.nav__toggle-menu-item {
display: block;
padding: 12px;
color: #fff;
border-bottom: 1px dotted #fff;
}
.nav__toggle-menu > li:last-child .nav__toggle-menu-item {
border-bottom: none;
}
// @import '../common/variables';
.nav {
&__bar {
background: $color_main;
color: $color_opposite;
padding: $space_xs $space_md;
}
&__toggle-btn {
display: block;
margin-left: auto;
color: $color_opposite;
font-size: 24px;
cursor: pointer;
transition: transform $speed_fast;
&.is-open {
transform: rotate(45deg);
}
}
&__toggle-menu {
background: $color_sub;
padding: 0 $space_md;
&:not(.is-open) {
display: none;
}
&.is-changing {
display: block;
overflow: hidden;
height: 0;
transition: height $speed_fast;
}
&-item {
display: block;
padding: $space_md;
color: $color_opposite;
border-bottom: 1px dotted $color_opposite;
}
& > li:last-child &-item {
border-bottom: none;
}
}
}
(function() {
const toggleBtnEl = document.querySelector('.nav__toggle-btn');
if(!toggleBtnEl) {return;}
const toggleMenuEl = document.querySelector('.nav__toggle-menu');
clickSet();
transitionEndSet();
// ボタンクリック時の挙動を設定
function clickSet() {
toggleBtnEl.addEventListener('click', (btn) => {
mutationObserverSet();
if(btn.target.classList.contains('is-open')) {
btn.target.classList.remove('is-open');
menuClose();
} else {
btn.target.classList.add('is-open');
menuOpen();
}
});
}
// メニューを開く
function menuOpen() {
toggleMenuEl.classList.add('is-open', 'is-changing');
}
// メニューを閉じる
function menuClose() {
toggleMenuEl.style.height = `${toggleMenuEl.scrollHeight}px`;
toggleMenuEl.classList.add('is-changing');
toggleMenuEl.classList.remove('is-open');
}
// メニュー開閉後に発火する挙動を設定
function transitionEndSet() {
toggleMenuEl.addEventListener('transitionend', () => {
toggleMenuEl.classList.remove('is-changing');
toggleMenuEl.style.height = '';
});
}
// メニューをアニメーションするためheightを付与
function mutationObserverSet() {
const observer = new MutationObserver((mutations, observer) => {
setTimeout(() => {
if(toggleMenuEl.classList.contains('is-open')) {
toggleMenuEl.style.height = `${toggleMenuEl.scrollHeight}px`;
} else {
toggleMenuEl.style.height = '';
}
observer.disconnect();
});
});
config = {attributes: true};
observer.observe(toggleMenuEl, config);
}
}());