toggle button + navigation bar

김동하·2020년 9월 10일
0

wecode

목록 보기
5/25

만들던 자기소개 페이지를 엎고 다시 시작했다. 레퍼런스를 찾으면 찾을수록 나의 밑천이 드러나 무척 힘들다. 정말 감각적인 디자인이나 쿨한 레이아웃은 많은데 도저히 모르겠다... 일단 내가 할 수 있는 범위에서 열심히 해보리다.

새롭게 자기소개 페이지를 만들며 예전에 봤던 귀여운 toggle 버튼 기능을 추가하려고 한다. 이제부터 시작!

버거라 불리는 흰 막대기 3개를 누르면 오른쪽에서 숨어있던 navigation bar가 튀어나오는 기능인데 css와 약간의 js로 만들 수 있다. width와 responsive와 translate 등 css 의 여러 개념이 들어가 다시 복습하기 좋은 기능이다.

먼저 html

<body>
    <nav>
      <div class="log">
         <h4>The Nav</h4>
      </div>
      
      <ul class="nav-links">
         <li><a href="#">Home</a></li>
         <li><a href="#">About</a></li>
         <li><a href="#">Work</a></li>
      </ul>
      
      <div class="toggle">
         <div class="line-1"></div>
         <div class="line-2"></div>
         <div class="line-3"></div>
      </div>
      
    </nav>

</body>

간단한 html 끝!

css

nav {
    display: flex;
    justify-content: space-around;
    align-items: center;
    background-color: sandybrown;
    height: 8vh;
}

nav 전체에 height를 8vh만 주었다.

대략 이런 모습. 스타일링하는 것은 생략하고 nav-link(ul)에 width 40%를 준다. 이제 햄버거 손질에 들어가면 된다.


.toggle div {
    margin: 3px;
    transition: all 0.3s ease;
    width: 23px;
    height: 3px;
    background: black;
}

이제부터 반응형이다. 반응형은 아직도 잘 모르겠다. 직관적인 느낌으로 이해하기가 어려워 많이 배워야할 부분이다. 그럼 반응형 갑시다.

@media screen and (max-width: 1024px) {
    .nav-links {
        width: 60%;
    }
}

하나씩 보자면 @media screen 이 부분은 브라우저에게 반응할 타입을 지정해주는 것이고 여기서는 screen이다 (max-width: 1024px) 이 부분은 screen의 최대 너비를 지정해주는 것인데 최대가 1024px이니 1024px보다 작은 screen에서 적용될 property를 아래 적으면 된다.

아이폰X에서 보았을 때

@media screen and (max-width: 768px) {

    .nav-links {
        background-color: rebeccapurple;
        display: flex;
        align-items: center;
        flex-direction: column;
    }
    
}

768px 이하에서 .nav-links가 어떻게 변할지 지정해주는 것이다. 중요한 것만 보자면 direction을 column으로 바꿨다.

이제 저 녀석을 화면 오른쪽에 위치시켜야 한다.

@media screen and (max-width: 768px) {

    .nav-links {
        background-color: rebeccapurple;
        display: flex;
        align-items: center;
        flex-direction: column;
        
        position: absolute;
        right: 0px;
        top: 8vh;
    }
    
}

주황 nav의 height만큼 top에 8vh를 주었다. 이제 width와 height를 주면 된다.

@media screen and (max-width: 768px) {

    .nav-links {
        background-color: rebeccapurple;
        display: flex;
        align-items: center;
        flex-direction: column;
        position: absolute;
        right: 0px;
        top: 8vh;
        
        height: 92vh;
        width: 30%;
    }
    
}

top에서 떨어진 만큼을 빼고 height에 92vh를 주었다.

얼추 모양이 잡혔다. 이제 저 햄버거 버튼을 누르면 보라색 ul이 오른쪽에서 튀어나오면 된다. 그러므로 화면 밖으로 일단 퇴장시켜야 한다.

    transform: translateX(100%);
    transition: transform 0.5s ease-in;

요 두 개를 추가해주면 되는데 transform: translateX(100%)는 X축으로 100%만큼 이동하라는 것이다. 다시 말해 보라 ul이 차지하는 영역만큼 X축(오른쪽)으로 이동하면 된다. 음수면 당연히 반대인 왼쪽이 된다. transition: transform 0.5s ease-in 은 저 transform이 발동할 때 얼마나 앙증맞게 움직일지 결정하는 것인데 transform 이 녀석을 0.5초 동안 ease-in 한다 라는 뜻이다.

@media screen and (max-width: 768px) {
    .nav-links {
        background-color: rebeccapurple;
        display: flex;
        align-items: center;
        flex-direction: column;
        position: absolute;
        right: 0px;
        top: 8vh;
        height: 92vh;
        width: 30%;
        transform: translateX(100%);
        transition: transform 0.5s ease-in;
    }
    
   .nav-links li {
        opacity: 0;
    }
   .nav-links .toggle {
     
        display: block;
    }
    
}

li 는 숨기고 .toggle 에는 block을 해준다.

이제 toggle(햄버거)를 달래야 한다. toggle 버튼을 누르면 toggle이 변하는 animation 을 줄 건데 js에서 classlist.toggle을 해야하니 일단 toggle에 추가할 class만 만들어주면 된다. 3단 막대는 클릭하는 순간 "X"로 변할 것이다. 헷갈리니(내가) 하나씩 살펴보자.

    .toggleAnimation .line-1 {
        transform: rotate(-45deg)
    }
    .toggleAnimation .line-2 {
        opacity: 0;
    }
    .toggleAnimation .line-3 {
        transform: rotate(45deg)
    }
    

첫 번째 line은 -45도 만큼 회전했고
두 번째 line은 종적을 감췄다. 그리고 세 번째는 45도 만큼 회전해 저런 모습이 되었다. 이제 첫 번째와 세번째 line을 살살 움직여 "X"를 만들면 된다.

   .toggleAnimation .line-1 {
   
        transform: rotate(-45deg) translate(-4px, 5px);
    }
    .toggleAnimation .line-2 {
        opacity: 0;
    }
    .toggleAnimation .line-3 {
    
        transform: rotate(45deg) translate(-3px, -5px);
    }

자연스럽게 "X"가 되기 위해서는 약간의 노가다가 필요한데 하나씩 대입하면서 가장 자연스럽게 변하는 것을 찾으면 된다.

이제 저 햄버거 버튼을 누르면 "X"로 변한다. "X"가 되는 순간 숨어있던 보라 ul도 나와야 한다. js의 도움이 필요하기에

 .nav-active {
            transform: translateX(0%);
        }

를 넣어주면 된다. class에 .nav-active가 추가되면 보라 ul이 원래 자리로 나온다는 뜻이다.

이제 숨겼던 보라 ul 속 li을 나타나게 하면 된다. css의 @keyframes 문법을 사용한다. @keyframes은 시간에 변화에 따라 나타나거나 사라질 때 사용한다.

 @keyframes navLinkFade {
        from {
            opacity: 0;
            transform: translateX(5px);
        }
        to {
            opacity: 1;
            transform: translateX(0px);
        }
    }

navLinkFade라는 animation이 적용되면 투명도가 0이고 X축으로 5px로 갔다 투명도가 1로 되면서 원점으로 돌아오게 된다. 이제 마지막 javascript 부분.

javascipt

const toggleBtn = document.querySelector(".toggle")
const ul = document.querySelector(".nav-links")
const li = document.querySelectorAll(".nav-links li")


function toggleHandler() {
    toggleBtn.classList.toggle("toggleAnimation")
    ul.classList.toggle("nav-active")
    
    li.forEach((link, index) => {
        console.log(link)
        if (link.style.animation) {
            link.style.animation = "";
        } else {
            link.style.animation = "navLinkFade 0.5s ease forwards 0.4s";
        }
    })
}

function init() {
    toggleBtn.addEventListener("click", toggelHandler)


}

init()

보기에 요란하고 복잡한데 간단하게 설명하자면 init()은 실행 함수고 init() 함수 안에는 소위 햄버거라 불리는 toggleBtn를 누르면 toggleHandler라는 함수를 실행할 것이라는 정의가 있다.

toggleHandler() 함수에는 총 3가지 이벤트가 있는데 toggle 버튼을 누를 때 "X"로 만드는toggleAnimation을 활성화 할 거라는
toggleBtn.classList.toggle("toggleAnimation")

그리고 보라 ul이 튀어나오는 "nav-active" 를 ul에 추가할 것이라는

ul.classList.toggle("nav-active")

마지막으로 각 li에 navLinkFade를 주는 forEach 함수가 있다.

 li.forEach((link, index) => {
       console.log(link, index)
       if (link.style.animation) {
           link.style.animation = "";
       } else {
           link.style.animation = `navLinkFade 0.5s ease forwards ${index / 3 + 1}s`;
       }
   })

forEach 함수를 후려치자면 각 li를 link라 하고 index는 link에 부여된 색인이다. 만약 link에 animation이 있으면 그냥 두고 없다면 navLinkFade animation을 추가하는 건데 ease forwards 는 스리슬쩍 앞으로 나온다는 뜻이다.

forwards 뒤에 초(s)가 들어간다. 만약 link가 순서대로 하나씩 나오길 원한다면 각 index를 전체 li 수인 3으로 나눈 값에 1을 더한 ${index / 3 + 1}s 를 작성해주면 된다.

완성뀨

출처 : https://www.youtube.com/watch?v=gXkqy0b4M5g&t=31s

profile
프론트엔드 개발

0개의 댓글