안녕하세요

6월10일18일차 - 다단메뉴 반응형 구현 본문

프론트엔드 국비교육

6월10일18일차 - 다단메뉴 반응형 구현

sakuraop 2022. 6. 10. 22:47

[중요한 기능인 다단메뉴 반응형을 구현했습니다.]

어려운 기능들이 많지만 어려울수록 재밌게 배울 수 있습니다.

다음 주부터는 스스로 시안을 만들고 웹 페이지를 구현하게 됩니다.

지금까지 배운 내용들을 빠짐 없이 넣어서 구현할 수 있도록 해야겠습니다.

다단메뉴
화면 크기에 반응해 메뉴가 사라졌다 버튼을 클릭하면 다시 나타납니다.
모바일 웹에서는 메뉴들이 position: static으로 공간을 차지합니다.

 


<a href="#!">link</a> !는 링크를 작동하지 않도록 합니다.


/ root로 이동합니다.
./ 의 경우에는 생략이 가능합니다.


다단메뉴 만들기
          <nav class="gnb"> 
네비게이션 태그 클래스는 gnb(global navigation bars)를 쓰기도 하고, nav 그대로 쓰기도 합니다.
이외에도 lnb(Local Navigation Bar)가 있습니다.


글씨만이 아니라 메뉴 칸 전체를 a로 만들기 위해서는 block과 padding을 이용합니다.
      .header .gnb > ul > li a {
        display: block;
        padding: 0 25px;
      }


다단메뉴 반응형으로 만드는 방법입니다.
웹을 먼저 구현한 뒤 @media max-width를 적용하여 필요한 속성을 골라 변경하면 됩니다.
      @media (max-width: 768px) {
        body {
          background: #369;
        }
      }
css 설정을 @media에 그대로 붙여넣습니다.
width: 1200px과 같이 고정된 사이즈로 인해서 축소된 화면에서는 스크롤 바가 생깁니다.

auto로 바꿉니다. width: 1200px; -> auto
        .header .container {
          width: auto; 
        } 
메뉴가 만들어질 위치와 크기를 조절합니다.        
        .header .gnb {
          position: fixed;
          top: 0;
          left: 0;
          z-index: 999;
          width: calc(100% - 90px);
          height: 100vh;
        }
메뉴를 세로로 배치합니다.
        .header .gnb > ul {
          display: flex;
          flex-direction: column;
        }
position: static; 속성으로 서브메뉴들이 레이아웃을 다시 차지하도록 합니다.
        .header .gnb > ul > li ul {
          position: static;
        }
hover대신 click 이벤트에 반응하여 나타나도록 할 것이니 보이지 않도록 합니다..
        .header .gnb > ul > li:hover ul {
          display: none;
        }


JS로 클릭 이벤트에 반응해 클릭한 menu가 나타나고, 다른 menu가 나타난 상태라면 사라지는 기능을 추가합니다.
        $(".gnb>ul>li>a").on("click", function (e) {
          e.preventDefault();
          $(".gnb>ul>li>a").next().hide();
          $(this).next().show();
        });
동일하게 부모 형제들의 ul을 감추도록 하여도 됩니다.
          $(this).parent().siblings().children("ul").hide();
children 대신 후손 선택자 중에서 찾는 find 기능이 있습니다.
          $(this).parent().siblings().find("ul").hide();


슬라이드 기능은 slideDown, sildeUp 입니다.
          $(this).next().slideDown();
          $(this).parent().siblings().find("ul").slideUp();
toggle로 열고 닫기를 할 수 있습니다.
          $(this).next().slideToggle();
          $(this).parent().siblings().find("ul").slideUp();
stop 기능을 추가하면 슬라이드 액션이 끝나기 전, 진행 중에 열고 닫기를 할 수 있습니다.
          $(this).next().stop().slideToggle();
          $(this).parent().siblings().find("ul").stop().slideUp();


html로 돌아가 메뉴 창을 나타나고 숨길 button을 만듭니다.
          <div class="mbtn">
            <i class="xi-bars"></i>
          </div>
큰화면에서는 보이지 않고
      .mbtn {
        display: none;
      }
@media max-width: 768px 이하의 작은 화면에서는 보이도록 합니다.
      .mbtn {
        display: block;
      }
btn을 클릭하면 메뉴 창이 나타나도록 합니다.
우선 기본 display를 보이지 않게 하고,
        .header .gnb {
          left: -100%;
          transition: 0.5s;
        }
on이 붙으면 나타나게 합니다.
        .header .gnb.on {
          left: 0;
        }
js 로 toggle 기능을 추가합니다.
        $(".mbtn").on("click", function () {
          $(".gnb").toggleClass("on");
        });

웹 추세는 css에서 최대한으로 설계를 한 뒤에 js에서는 최소한의 기능만을 줍니다. 
class="on" 으로 조절을 하는 방식입니다.


남은 문제들을 해결합니다. 

pc사이즈로 되돌아가면 클래스 on 이 붙어 있기 때문에 click 이벤트가 적용됩니다.
if 와 width() 를 사용해 모바일 사이즈의 화면에서만 이벤트가 작동하도록 조건을 만듭니다.
          if ($(window).width() < 769) {
            e.preventDefault();
            // $(".gnb>ul>li>a").next().hide();
            $(this).next().stop().slideToggle();
            $(this).parent().siblings().find("ul").stop().slideUp();
          }


또는 hasClass를 사용해 'on' 이 붙어 있을 경우에만 작동하도록 조건을 만들 수 있습니다.
          if ($('.gnb').hasClass('on')) {}
resize 이벤트가 발생하면 on 클래스와 현재 지니고 있는 style을 모두 지우면 됩니다.
        $(window).on("resize", function () {
          $(".gnb").removeClass("on");
          $(".gnb>ul ul").removeAttr("style");
        });


다시 메뉴 버튼을 눌렀을 때 slideUp으로 펼쳐진 슬라이드가 닫히도록 할 수 있습니다.
        $(".mbtn").on("click", function () {
          $(".gnb").toggleClass("on");
          $(".gnb>ul>li>a").next().stop().slideUp();
        });

jquery 메서드 종류는 [맑은 커뮤니케이션 - jquery 메서드 정리표]에 잘 정리되어 있습니다.