HTML
.logo 클래스 => 로고
.welcome 클래스 => 홈페이지 소개 문구
.menu-toggle 클래스 => 메뉴 버튼
.menu 클래스 => 버튼을 눌렀을 때 덮을 화면들 (그 안에 등장하는 링크 버튼 + 닫기버튼 + 로고까지)
nav 태그는 현재 페이지와 연결되는 네비게이션 링크 집합 정의할 때 사용함
메뉴, 목차, 인덱스 등
<header>
<h2 class="logo">logo.</h2>
</header>
<div class="welcome">
<h1>Welcome to our website</h1>
<h1 class="sub">- Please click on the menu toggle</h1>
</div>
<div class="menu-toggle">
<span></span>
<span></span>
</div>
<nav class="menu">
<header>
<h2 class="logo-nav">logo.</h2>
</header>
<div class="menu-close">
<span></span>
<span></span>
</div>
<ul>
<li><a class="nav-link active-link" href="#">Home</a></li>
<li><a class="nav-link" href="#">About</a></li>
<li><a class="nav-link" href="#">Projects</a></li>
<li><a class="nav-link" href="#">Shop</a></li>
<li><a class="nav-link" href="#">Contact</a></li>
<li><a class="nav-link" href="#">Blog</a></li>
</ul>
</nav>
<script src="app.js"></script>
CSS
.menu-toggle
=> 토글 버튼이므로 position:fixed;
span으로 직선을 그릴 예정이므로 flex-direction:column;
justify-content:space-around; 요소들 주위에 동일한 간격으로
justify-content는 수평 방향 정렬 방식임.
반대로 align-items는 수직 방향 정렬 방식임.
nav
=> top:100vh;로 덮을 화면을 위로 올려서 숨겨놓기
js로 active 클래스 붙이면 top:0;으로 보여주기
.nav-link
=> active 붙이면 opacity:1;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
header {
position: relative;
width: 100%;
height: 6rem;
}
.logo {
position: absolute;
bottom: 0;
left: 12%;
}
.menu-toggle {
position: fixed;
top: 45vh;
left: 3%;
width: 2rem;
height: 1rem;
cursor: pointer;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.menu-toggle span:nth-child(1) {
width: 70%;
height: 2px;
background-color: black;
transition: 0.5s;
}
.menu-toggle:hover span {
width: 100%;
opacity: 0.5;
transition: 0.5s;
}
.menu-toggle span:nth-child(2) {
width: 100%;
height: 2px;
background-color: black;
}
.welcome {
position: relative;
top: 25vh;
left: 12%;
font-size: 1.4rem;
}
.sub {
color: #CBCFD3;
}
nav {
position: fixed;
width: 100%;
height: 100vh;
left: 0;
top: -100vh;
background-color: #171717;
transition: 0.2s;
}
nav.active {
top: 0;
transition: 0.2s;
}
.logo-nav {
position: absolute;
color: white;
bottom: 0;
left: 12%;
}
nav ul {
position: absolute;
left: 12%;
list-style: none;
top: 20%;
height: 55%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.nav-link {
position: relative;
color: #CBCFD3;
left: 0;
text-decoration: none;
font-size: 2.5rem;
transition: 0.5s;
opacity: 0;
}
.nav-link.active {
opacity: 1;
transition: 0.5s;
}
.nav-link.active:hover {
color: white;
left: 10%;
transition: 0.5s;
}
.active-link {
color: white;
}
.menu-close {
position: absolute;
top: 45vh;
left: 2%;
width: 2rem;
height: 1rem;
cursor: pointer;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.menu-close:hover {
opacity: 0.6;
}
.menu-close span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 70%;
height: 2px;
background-color: white;
}
.menu-close span:nth-child(1) {
transform: rotate(45deg);
}
.menu-close span:nth-child(2) {
transform: rotate(-45deg);
}
JS
menuToggle 클릭하면 메뉴가 열리고
menuClose 클릭하면 메뉴가 닫히고
메뉴 열리고 닫힐 때 a 링크 애들을 setTimemout()으로 순차적으로 주르륵 보여주도록 인터랙션 구현
let menuToggle = document.querySelector('.menu-toggle');
let menuClose = document.querySelector('.menu-close');
let menu = document.querySelector('.menu');
let navLinks = Array.from(document.querySelectorAll('.nav-link'));
menuToggle.addEventListener('click', openMenu);
menuClose.addEventListener('click', closeMenu);
function openMenu() {
menu.classList.add('active');
navLinks.forEach((link, idx) => {
setTimeout(() => {
link.classList.add('active');
}, idx * 100);
})
}
function closeMenu() {
menu.classList.remove('active');
setTimeout(() => {
navLinks.forEach(link => link.classList.remove('active'));
}, 100);
}
참고
Vanilla JavaScript: Creating A Clean / Minimal Navigation Menu