공부 모음집/실습 기록

[👩🏻‍💻 연습] 반응형 Navbar 만들기 (+ 미디어쿼리, 햄버거 메뉴 토글 버튼, 자바스크립트 적용)

leedaramji 2023. 10. 21. 05:46

반응형 Navbar 만들기 연습

  • HTML 구조 작업
  • CSS 스타일링
  • 미디어 쿼리
  • 햄버거 메뉴 (토글 버튼) 만들기
  • 토글 버튼 Javascript 적용

 

1. HTML 구조 작업

 

 

+ Google font로 Poppins 글꼴 설정

+  Fontawessome 아이콘 넣기

 

<body>
    <header id="header">
        <div class="header__logo">
            <i class="fa-solid fa-house-chimney-window"></i>
            <a href="#" title="slow life">Slow Life</a>
        </div>
        <ul class="header__menu">  
            <li><a href="">HOME</a></li>
            <li><a href="">ABOUT</a></li>
            <li><a href="">LIFE</a></li>
            <li><a href="">GALLERY</a></li>
            <li><a href="">IDEA</a></li>
        </ul>
        <ul class="header__icons">
            <li><i class="fa-sharp fa-solid fa-n"></i></li>
            <li><i class="fa-brands fa-instagram"></i></li>
        </ul>
        <a class="header__togglebtn" aria-label="navigation menu toggle">
            <i class="fa-solid fa-bars"></i>
        </a>
    </header>
</body>

 

  • <li> 안에 a태그의 href="" 안에 #(빈 프래그먼트)를 넣으면 페이지가 반응하지 않는다.
  • javascript 효과를 위해 비워둔다.

 

<!-- 1. 아이콘 들어가는 박스 class명 바꿈 -->
<!-- 2. ul 태그로 바꿈 -->
<ul class="header__icons">
            <li><i class="fa-sharp fa-solid fa-n"></i></li>
            <li><i class="fa-brands fa-instagram"></i></li>
</ul>

 


 

2. CSS 스타일링

 

 

마우스 hover 효과 (1)

 

  • Hover 아닌 상태 - border-bottom: 1px solid transparent;
  • Hover 상태 - border-bottom: 1px solid #fff;
  • 밀림 현상을 방지하기 위해서 hover 상태와 아닌 상태에  같은 값의 border-bottom을 적용한다.

 

마우스 hover 효과 (2)

 

  • 마우스 hover 상태가 되면 background-color 로 효과를 준다.

 

:root {
    --text-color: #f0f4f5;
    --background-color: #0e0e0e;
    --accent-color: deepskyblue;
}

* {
    margin: 0;
    box-sizing: border-box;
    font-family: 'Poppins', sans-serif;
}

a {
    text-decoration: none;
    color: var(--text-color);
}
/* Header Container */
#header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: var(--background-color);
    padding: 8px 12px;
}
/* Header logo Container */
.header__logo {
    font-size: 20px;
    color: var(--text-color);
}
.header__logo i {
    color: var(--accent-color);
}

/* Header menu Container */
.header__menu {
    display: flex;
    list-style: none;
    padding-left: 0;
}
.header__menu li {
    border-bottom: 1px solid transparent;
    padding: 8px 12px;
    margin-left: 10px;
}
/* Header menu list 마우스 hover 효과 */
.header__menu li:hover {
    border-bottom: 1px solid var(--text-color);
    transition: 0.2s;
}
/*.header__menu li:hover {
    background-color: rgba(0, 191, 280, 0.5);
    border-radius: 4px;
    transition: 0.2s;
}*/
/* Header icon Container */
.header__icons  {
    display: flex;
    list-style: none;
    color: var(--text-color);
    padding-left: 0;
}
.header__icons li {
    padding: 8px 12px;
    cursor: pointer;
}

 


 

3. 미디어쿼리 (반응형)

 

#navbar

  • flex-direction: column; (세로 정렬)
  • align-items: flex-start; (교차축 정렬)

 

.nav__menu

  • flex-direction: column; (세로 정렬)
  • align-items: center (교차축 정렬 가운데로)
  • width: 100%

 

메뉴의 리스트가 가운데가 아닌 왼쪽 정렬된 상태

 

.nav__menu 너비 100%로 설정

 

보더 너비만큼 차지

 

  • 마우스 hover 상태에 효과를 전체 영역을 차지하게 하고 싶다면 width: 100%; 로 설정해 준다.

 

 

  • .menu__li의 margin-left 때문에 마우스 hover 할 때 차지하는 영역의 크기가 다르다.
  • margin: 0; 으로 마진값 없애줘야 비율이 같아진다.

 

좌우 영역 같아짐

 

  • .nav__icons는 row 상태이기 때문에 주축 방향으로 가운데로 옮겨준다.
  • 마찬가지로 너비가 100%가 아니기 때문에 너비를 100%로 설정해 준다.
  • 하지만 중간이 아니라 저 우측으로 치우치게 된다.
  • 왜냐하면 <ul>에 기본으로 설정된 패딩이 있기 때문이다.
  • 미디어쿼리가 아닌 CSS 설정에서 padding-left: 0;으로 설정해 준다.
  • 원래는 처음에 * { padding: 0 } 으로 CSS를 초기화시켜 준다.
  • justify-content: center;

 


4. 햄버거 메뉴 

 

➕ 햄버거 메뉴 추가

<a href="#" class="header__togglebtn" title="navigation menu toggle">
	<i class="fa-solid fa-bars"></i>
</a>

 

  • position: absolute; 를 사용해서 문서의 흐름에서 빠져나오게 한다.
  • right: 30px;을 줘서 뷰포트의 오른쪽 화면에서 30px만큼 이동시켜 준다.
  • 🚨 하지만 창을 다시 크게 늘리면 반응형을 설정하지 않은 화면으로 바뀌게 되는데 이때 아이콘이 겹치는 문제가 발생한다.
  • [ Solution ] 반응형을 했을 경우에만 나타날 수 있게 기본적인 CSS코드에는 display: none으로 설정한다.
  • [ Solution ] 반응형 상태일 때 나타날 수 있도록 미디어쿼리에는 display: block으로 설정한다.
  • button이 무엇을 의미하는지 aria-label을 작성한다. button을 읽어주는 경우가 있기 때문에 button이라는 문자는 작성하지 않아도 된다.

 

position: absolute; 설정해서 햄버거 아이콘이 문서의 흐름에서 빠져나온 상태

 

right: 30px;을 줘서 위치를 뷰포트의 오른쪽에서 30px 떨어트림.
화면을 다시 늘렸을 때 생기는 문제 상황

Replay[ Solution ] 반응형 상태일 때 나타날 수 있도록 미디어쿼리에는 display: block으로 설정한다.

 

/* Hamburger Menu */
.header__togglebtn {
    display: none;
    position: absolute;
    right: 30px;
    font-size: 24px;
    color: var(--accent-color);
}
/* 미디어쿼리 max-width: 768px */
.header__togglebtn {
        display: block;
}

 


5. 햄버거 메뉴 - 토글 버튼 Javascript로 이벤트 처리

 

하지만 반응형 상태가 되었을 때 햄버거 버튼 클릭시에 메뉴를 나타나게 하고 싶다. 

 

  • 미디어 쿼리에서 메뉴와 아이콘을 display: none으로 설정해서 숨겨준다.
  • 그리고 Javascript로 이벤트 처리를 해준다.

 

메뉴와 하단의 아이콘 display: none으로 숨겨진 상태

 

[Javascript 이벤트 처리]

 

1) JS 변수에 html 클래스 연결시키기

  • toggleBtn 변수에 .nav__togglebtn 클래스 연결
  • menu 변수에 .nav__menu 클래스 연결
  • icons 변수에 .nav__icons 클래스 연결

 

2) toggleBtn에 마우스 클릭시 발생될 이벤트 정의

  • .toggle은 active가 없다면 active를 추가하고, active가 있다면 active를 빼주는 일을 한다.
// html body에서 같은 이름의 클래스를 가진 것을 찾아서 JS 변수와 연결
const toggleBtn = document.querySelector('.header__togglebtn');
const menu = document.querySelector('.header__menu');
const icons = document.querySelector('.header__icons');

//toggleBtn 마우스 클릭시 발생될 이벤트 정의
//.toggle은 menu와 icons의 클래스에 active가 없다면 active 추가
//active기 있다면 active를 빼주는 일을 한다.
toggleBtn.addEventListener('click', () => {
    menu.classList.toggle('active');
    icons.classList.toggle('active');
});

//반응형 상태일 때 메뉴 클릭시 메뉴를 자동으로 닫아준다.
menu.addEventListener('click', () => {
    menu.classList.remove('open');
});

 

3) 미디어쿼리에는 Javascript .toggle 이벤트를 활성할 코드를 작성해준다.

/* CSS 미디어 쿼리에 .toggle active 활성 코드 작성 */
.header__menu.active,
    .header__icons.active {
        display: flex;
    }

 

클릭 전

 

클릭하면 active class list가 생긴다.

 


 

- 태블릿이나 모바일은 손가락으로 누르기 때문에 클릭 영역이 넓어야 한다.

👉🏻 메뉴 <li>의 <a> 태그를 display: block;으로 바꾼다. 그러면 a영역이 <li>를 가득 채운다.

- padding도 content의 일부분