본문 바로가기

TIL

<CSS> 반응형 웹 디자인 - 메뉴바 (3)

 

지난 (1), (2) 글에서 반응형 웹 디자인의 메뉴바를 완성하였으나, 드림코딩 강의를 참조하여 코드를 다시 수정해보았다. 일명 리팩토링! 하였다.

 

디자인은 위처럼 에어비앤비를 테마로하여 다시 만들어보았다.

 

 

- HTML

전체 헤더는 클래스명 nav로 하여 section 태그로 만들었다. 지난번과 달리 nav를 감싸는 더 큰 div 박스는 불필요하여 제거하였다. 브랜드명에는 로고 이미지도 새롭게 추가하였다. 메뉴는 지난번처럼 중단점 이하에서 나타나는 메뉴를 따로 만들지 않고, 하나의 메뉴만 만들고 이를 CSS에서 조작하여 미디어 쿼리를 통해 중단점 이하일 경우 다르게 나타나도록 만들었다. 코드가 훨씬 간결하고 보기 편해졌다. 맨 하단의 클래스 fas는 중단점 이하에서 나타나는 햄버거 모양의 메뉴바 아이콘이다. 처음에 이를 div 태그로 감쌌었는데, 이는 불필요한 부분이어서 다시 제거하였다.

      <section class="nav">
        <div class="logo">
          <i class="fab fa-airbnb"></i>
          airbnb
        </div>

        <ul class="menu">
          <li><a href="">HOME</a></li>
          <li><a href="">ABOUT</a></li>
          <li><a href="">EXPLORE</a></li>
          <li><a href="">EXPERIENCE</a></li>
          <li><a href="">ONLINE</a></li>
        </ul>

        <div class="icon">
          <i class="fab fa-instagram"></i>
          <i class="fab fa-facebook"></i>
        </div>

        <i class="fas fa-bars"></i>
      </section>

 

 

- CSS

가상선택자 root를 이용하여 컬러 부분은 개별적으로 수정할 필요가 없도록 코드의 효율성을 높였다. nav와 menu는 flex를 이용하여 위치를 설정하였고, 햄버거 모양의 메뉴바 아이콘은 display : none을 통해 숨겨두었다. 이전과 크게 달라진 점은 없다.

:root {
  --text-color: #f8f8ff;
  --background-color: #ffb6c1;
  --accent-color: #fff0f5;
}

* {
  margin: 0;
  padding: 0;
}

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

.nav {
  background-color: var(--background-color);
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 40px 30px;
}

.logo {
  font-size: 2.5em;
  color: var(--text-color);
}

.menu {
  list-style: none;
  display: flex;
  flex-direction: row;
}

.menu li {
  padding: 0 15px;
  font-size: 25px;
}

.icon {
  font-size: 25px;
  color: var(--text-color);
}

.fab {
  padding: 0 5px;
}

.fas {
  display: none;
}

 

미디어 쿼리는 중단점을 960px으로 둔 1개만 설정하였다. 이전처럼 큰 화면일 때와 작은 화면일 때 2개로 설정하는 것은 불필요한 것으로 판단되어 제거하였다. 대신 앞서 HTML에서 설명했듯 메뉴들을 작은 화면일 때 다르게 배치해야 하므로 이를 flex를 통해 구현하였다. 그리고 기본 설정은 display : none인데, 햄버거 모양의 메뉴바 클릭 시 나타나도록 해야 하기 때문이다. 햄버거 모양의 메뉴바는 위치 설정에 position을 이용하였다. nav 안에 포함되어 있어 flex 속성 값이 적용되어있기 때문에 개별적으로 위치 설정을 하기 위해 position으로 개별적인 값을 설정한 것이다. 마지막으로 active는 햄버거 모양의 메뉴바 클릭 시 menu와 icon의 클래스명에 추가될 선택자이다. active가 추가되면 display : none 대신 active의 display : flex가 적용되어 메뉴와 아이콘이 나타나게 된다. 이로써 전처럼 메뉴를 두 개 만드는 대신, 1개만으로 flex를 통해 나타나는 모습을 달리하였기 때문에 코드가 훨씬 간결해졌다.

@media screen and (max-width: 960px) {
  .nav {
    flex-direction: column;
    align-items: flex-start;
  }

  .menu {
    display: none;
    flex-direction: column;
    width: 100%;
    justify-content: center;
    align-items: center;
  }

  .menu li {
    padding: 20px 0;
  }

  .icon {
    display: none;
    width: 100%;
    justify-content: center;
    padding: 10px 0;
  }

  .fas {
    display: block;
    font-size: 25px;
    color: var(--text-color);
    position: absolute;
    right: 30px;
    top: 50px;
  }

  .active {
    display: flex;
  }
}

 

 

- JS

이번 코드는 menu와 icon을 추가하여 이벤트 발생 시 이들이 나타나거나 사라지도록 구현하였다. 또한 이벤트 발생 시 실행할 함수는 화살표 함수를 사용하여 보다 간결한 코드로 기능을 구현하였다. 햄버거 모양의 메뉴 바를 클릭하면, toggle에 의해 menu와 icon에 active 클래스가 추가되고 active에 설정된 display : flex로 인해 menu와 icon에 기존에 설정되어 있던 display : none은 이 active의 값으로 덮어씌워지게 된다. 이전과 달리 menu를 1개만 만들어 이로써 컨트롤하고 있기 때문에 코드가 달라졌지만, 근본적인 큰 차이는 없다.

const bars = document.querySelector(".fas");
const menu = document.querySelector(".menu");
const icon = document.querySelector(".icon");

bars.addEventListener("click", () => {
  menu.classList.toggle("active");
  icon.classList.toggle("active");
});

 

 

- 짧은 소감

이전과 달리 menu를 2개 만들지 않고 1개만으로 구현할 수 있었다는 점이 내게는 획기적(?)이었다. 중단점에 따라 모양이 달라지니 당연히 메뉴를 2개 만들고 이를 각각 적용해야 하는 것으로 이해했었다. 이를 flex를 통해 충분히 구현할 수 있다는 점을 배울 수 있었다. 처음 사용해 본 root 가상 선택자, 화살표 함수도 코드의 가독성을 높이는 데에 활용할 수 있어 유익했다. 코드를 비교하면서 다시 만들어보길 잘한 선택이었다!

 

 

 

 

 

참고 : 유튜브 드림코딩 <웹사이트 따라만들기, 반응형 헤더편 | 프론트엔드 개발자 입문편: HTML, CSS, Javascript>