[CSS] mediaquery 대응 navbar 만들기

테크야끼·2021년 5월 8일
0

CSS

목록 보기
5/9
post-thumbnail

💡 학습목표

웹페이지를 만들때 첫번째 고비는 GNB 즉 navbar를 만드는 것이고 두번째 고비는 mediaquery를 이용해 모바일 기기에 대응하는 레이아웃으로 만드는 것이다. 그리고 이 두가지의 고난이 동시에 오는 순간이 navbar를 mediaquery로 재선언하는 순간인데 처음 레이아웃을 크게 바꾸는 작업인만큼 미디어쿼리를 접했을 때 스타일링의 재정의가 까다로워서 고생을 했다.

하지만 요즘 대부분의 웹사이트가 모바일기기 대응을 제공하는 이상 모바일기기 대응작업은 웹페이지를 만들 때 빼놓을 수 없는 과정이기도 하다.

이렇게 나를 괴롭혔던 navbar의 mediaquery를 가장 쉽고 직관적이게 만들수 있는 방법에 대해 포스팅을 해보았다.

💡 완성작

데스크톱

모바일 (below 768px screen width)

완성도는 위와 같다. 로고와 메뉴로 이루어진 navbar를 모바일기기 사이즈로 변경되었을 때, 토글버튼이 생기면서 버튼을 눌렀을 때 메뉴가 세로정렬 되는 navbar을 만들어 볼 것이다.

💡 START

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hiko's Portfolio</title>
    <script
      src="https://kit.fontawesome.com/9eb162ac0d.js"
      crossorigin="anonymous"
    ></script>
    <link
      href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="style.css" />
    <script src="main.js" defer></script>
  </head>
  <body>
    <!-- Navbar -->
    <nav id="navbar">
      <div class="navbar__logo">
        <i class="fab fa-angellist"></i>
        <a href="#">Hiko</a>
      </div>
      <ul class="navbar__menu">
        <li class="navbar__menu__item">Home</li>
        <li class="navbar__menu__item">About</li>
        <li class="navbar__menu__item">Studio</li>
        <li class="navbar__menu__item">Works</li>
        <li class="navbar__menu__item">Process</li>
        <li class="navbar__menu__item">Contact</li>
      </ul>
      <button class="navbar__toggle-btn">
        <i class="fas fa-bars"></i>
      </button>
    </nav>
  </body>
</html>
  • navbar block안에 logo, menu, toggle-btn 라는 세가지 element로 나누어진 구조로 만들었다.

CSS

/* Global */
:root {
  /* Color */
  --color-dark-white: #bdbdbd;
  --color-black: #4d4d4d;
  --color-grey: #616161;
  --color-light-grey: #7c7979;
  --color-black: #000000;

  /* Font size */
  --font-large: 48px;
  --font-medium: 28px;
  --font-regular: 18px;
  --font-small: 16px;
  --font-micro: 14px;

  /* Font weight */
  --weight-bold: 700;
  --weight-semi-bold: 600;
  --weight-regular: 400;

* {
  box-sizing: border-box;
}

body {
  font-family: 'Open Sans', sans-serif;
  margin: 0;
  height: 3000px;
}

a {
  text-decoration: none;
  color: var(--color-black);
}

ul {
  padding-left: 0;
  margin: 0;
}

li {
  list-style: none;
}

button {
  background-color: transparent;
  cursor: pointer;
  border: none;
  outline: none;
  padding: 0;
}

/* 1. Navbar 정렬 */
#navbar {
  position: fixed;
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid var(--color-light-grey);
}

.navbar__logo {
  font-size: var(--font-medium);
  font-weight: var(--weight-semi-bold);
}

.navbar__menu {
  display: flex;
}

.navbar__menu__item {
  padding: 8px 12px;
  margin: 0 4px;
  cursor: pointer;
  border: 1px solid var(--color-light-grey);
}

/* 2.toggle btn */
.navbar__toggle-btn {
  position: absolute;
  right: 32px;
  top: 24px;
  font-size: 24px;
  display: none;
}

/* 3.mediaquery */
@media screen and (max-width: 768px) {
  .navbar__toggle-btn {
    display: block;
  }

  #navbar {
    /* logo와 gnb 수직배열 */
    flex-direction: column;
    /* logo 제자리로 돌리기 */
    align-items: flex-start;
  }

  .navbar__menu {
    /* gnb menu 수직배열 */
    flex-direction: column;
    /* 텍스트 화면전체 너비의 중앙배열  */
    width: 100%;
    text-align: center;
    display: none;
  }

  .navbar__menu.open {
    display: block;
  }
}

1. Navbar 정렬

#navbar {
  position: fixed;
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  transition: all var(--animation-duration) ease-in-out;
  border-bottom: 1px solid var(--color-light-grey);
}

스크롤을 내려도 메뉴를 고정시키기 위해 fixed를 주고 화면너비 전체를 사용하기 위해 width:100%를 주었다. 그리고 블럭요소를 수평 정렬시키기 위해 flexbox를 사용했다.

😳 nav를 스타일링할 때 습관적으로 nav안의 요소에 너비나 높이를 설정하게 되면 화면이 바뀌었을 때 대응하기가 어려워진다. 버튼 하나하나에 너비를 주고싶은 경우에 padding을 주는 것이 좋다.

2. toggle btn 스타일링

/* 2.toggle btn */
.navbar__toggle-btn {
  position: absolute;
  right: 32px;
  top: 24px;
  font-size: 24px;
  display: none;
}

모바일 화면에서 메뉴를 노출시킬 토글버튼을 스타일링한다. position: absolute로 나머지 두 요소와 상관없이 위치를 잡아두고 모바일 화면에서만 노출시켜야 하기 때문에 display: none; 으로 숨겨둔다.

2. mediaquery

/* 3.mediaquery */
@media screen and (max-width: 768px) {
  .navbar__toggle-btn {
    display: block;
  }

  #navbar {
    /* logo와 gnb 수직배열 */
    flex-direction: column;
    /* logo 제자리로 돌리기 */
    align-items: flex-start;
  }

  .navbar__menu {
    /* gnb menu 수직배열 */
    flex-direction: column;
    /* 텍스트 화면전체 너비의 중앙배열  */
    width: 100%;
    text-align: center;
    display: none;
  }

  .navbar__menu.open {
    display: block;
  }
}
  • 화면이 768px 밑으로 떨어졌을 때 바뀔 레이아웃을 스타일링한다. 먼저 숨겨둔 토글버튼을 다시 노출시킨다.

  • navbar에서 수평배열 되있던 로고와 메뉴를 flex-direction: column;으로 변경하여 수직배열로 한다.

이 경우 윗처럼 로고와 메뉴와 같이 정렬되어 로고가 중간에 온다. 이것을 해결하기 위해 align-items: flex-start;를 사용해 로고가 원래 있던 자리를 유지시킨다.

로고가 중간에 오는 이유는 미리 선언한 align-items: center;가 적용된 상태이기 때문이다. flex-direction이 column일 경우 교차축은 수평이 되어 중앙으로 정렬된다.

  • 마지막으로 토글 버튼은 class의 유무로 제어하기 위하여 버튼이 클릭되었을 때 노출된 상태를 open이라는 class를 붙은 선택자에 스타일링해준다.

Javascript


const navbarMenu = document.querySelector('.navbar__menu');
const navbarToggleBtn = document.querySelector('.navbar__toggle-btn');
navbarToggleBtn.addEventListener('click', () => {
  navbarMenu.classList.toggle('open');
});
  • .navbar__menu.navbar__toggle-btn을 변수에 넣는다.
  • addEventListener()를 사용하여 navbarToggleBtn을 클릭했을 때 작동될 함수를 만든다
  • toggle()을 이용해 navbarMenuopen이라는 class가 추가되었다 사라졌다 한다
  • 이 떄 navbarMenuopen에 인해 display:none, display:block이 반복되며 메뉴를 노출시킨다.

💡 완성!

1개의 댓글

comment-user-thumbnail
2022년 8월 17일

안녕하세요. 드림코딩 아카데미 강의 내용이 블로그에 올라와 있다는 다른 수강생 분의 보고를 받고 방문하게 되었습니다. 아카데미 강의 내용은 블로그에 공개적으로 작성할 수 없습니다. 이는 엄연히 저작권 위반이며, 비공개 또는 삭제 처리 부탁드립니다. 블로그에 올리신 유사 포스트도 조치 부탁드립니다.

답글 달기