minimal navigation menu

woolee의 기록보관소·2022년 11월 7일

FE 기능구현 연습

목록 보기
16/33

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

profile
https://medium.com/@wooleejaan

0개의 댓글