[jQuery - 실습] Making a Accordion Menu

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

jQuery

목록 보기
8/11

💡 학습목표

아코디언 메뉴(Accordion Menu)란 컨텐츠를 담는 방식 중 하나로 네비게이션을 클릭하면 컨텐츠를 담은 컨테이너가 열리고 다른 네비게이션을 클릭하면 열려있는 컨테이너는 닫히고 클릭한 컨테이너가 열리는 구조이다.

이번 포스팅에서는 jQuery 메서드인 slideUp()slideDown()을 사용하여 아코디언 메뉴를 구현하고 효율적인 코드작성을 위해 관련 선택자를 필터링하는 메서드를 학습한다.

HTML

<!DOCTYPE html>
<html lang="ko">
 <head>
   <meta charset="UTF-8" />
   <title>아코디언</title>
   <meta name="description" content="아코디언" />
   <link rel="stylesheet" href="./css/initial.min.css" />
   <link rel="stylesheet" href="./css/style.css" />
   <script type="text/javascript" src="./js/jquery_3.5.1.js"></script>
   <script type="text/javascript" src="./js/common.js"></script>
 </head>
 <body>
   <dl>
     <dt>시험안내</dt>
     <dd>
       <ul>
         <li>2021년 제3회 임기제공무원 경력경쟁임용시험 최종합격</li>
         <li>
           2022학년도 서울특별시 공립 유치원 선정경쟁시험 사전예고 연기 안내
         </li>
         <li>2021년도 제1회 초졸·중졸·고졸 검정고시 합격자 발표 공고</li>
         <li>
           2021년 서울특별시교육청 지방공무원(운전직렬 9급) 시행계획 공고
         </li>
       </ul>
     </dd>
     <dt>보도/설명 자료</dt>
     <dd>
       <ul>
         <li>보직교사 수당 인상 제안</li>
         <li>[참고]21.5.14.(금) 코로나19 대책 관련 일일 브리핑 자료</li>
         <li>[입장문]중앙고 이대부고 판결에 대한 서울시교육청 입장</li>
         <li>2021 신규교사 성장지원을 위한 멘토 운영</li>
       </ul>
     </dd>
     <dt>더보기</dt>
     <dd>
       <ul>
         <li>기타1</li>
         <li>기타2</li>
         <li>기타3</li>
         <li>기타4</li>
       </ul>
     </dd>
   </dl>
 </body>
</html>

body안에 dl > dt + dd > ul > li 구조로 넣어주었고 탭을 총 3개 만들고 싶으므로 같은 구조로 3개를 만들어주면 된다.

(텍스트는 서울시청 홈페이지에서 임의로 가져왔다!)

dl, dt, dd

dl, dt, dd를 쓸 일이 잘 없어서 헷갈리게 되는데 각각 무엇의 약자인지 생각하면 이해하기 쉽다!

  • dl : Description-List
  • dt : Description-Term
  • dd : Description-Description

💡 CSS

@charset "UTF-8";

html,
body {
 height: 100%;
}

body {
 font-family: 'Noto Sans KR', sans-serif;
 color: #666666;
}

ul,
ol {
 list-style: none;
}

dl {
 width: 600px;
 margin: 50px auto;
}

dt {
 font-size: 18px;
 height: 50px;
 line-height: 50px;
 text-indent: 30px;
 color: #fff;
 background: black;
 cursor: pointer;
}

body > dl > dt:first-child {
 background: rgb(50, 192, 145);
}

body > dl > dt:nth-child(3) {
 background: rgb(126, 126, 126);
}

dd {
 padding: 30px;
 background: #d4d0c8;
}

dd ul li {
 padding-bottom: 10px;
}

컨텐츠가 들어간 박스형태가 되도록 스타일링한다. 교육청 홈페이지에서 컨텐츠를 가져왔기 때문에 정보를 전달하기 쉽게 잔잔한 색으로 입혀주었다!☺️

💡 로직 구현

$('dd:not(:first)').css('display', 'none');

본격적으로 로직을 짜볼 차례이다.

먼저 아코디언 메뉴의 첫 화면을 생각해보면 첫번째 컨테이너 이외의 모든 컨테이너 메뉴는 닫혀있다. 이 상태를 구현하기 위해 첫번째 dd 이외의 dd는 모두 dislplay:none을 주어 숨겨주었다.

이 때 선택자는 두번째, 세번째 dd를 선택하는 방식도 있지만 요소를 하나만 선택하는 것이 효율적이기 때문에 :not() 메서드를 사용하여 필터링하였다.

  • not()
    선택한 요소 중 특정 선택자를 제외한 요소를 선택한다.
    $(selector).not(notSelector)

그리고 클릭을 할 때 동작이 발생하기 때문에 on()을 이용해 클릭 이벤트바인딩을 한다.

컨텐츠를 숨김/노출을 반복 할 때 가장 쉽게 생각할 수 있는 로직은 display이다. 만약 제목을 클릭했을 때 컨텐츠가 숨겨진 상태라면 노출시키고 해당 제목에 해당하지 않는 컨텐츠는 모드 숨겨라!

하지만 탭 좀 만들어본 사람이라면 동시다발적인 숨김/노출을 제어하기 위해 선택된 순간 먼저 모든 요소에 적용된 효과를 없애줘야 한다는 것도 알기때문에 아래와 같은 코드를 작성할 수 있다.

💡 javascript

$(function () {
  $('dd:not(:first)').css('display', 'none');
  $('dl dt').on('click', function () {
    if ($(this).next().css('display') == 'none') {
      $('dl dd').css('display', 'none');
      $(this).next().css('display', 'block');
    } else {
      $(this).next().css('display', 'none');
    }
  });
});

이렇게 하면 일단 원했던 동작은 성공적으로 구현했다! 하지만 이것이 아코디언인가? 아코디언의 핵심은 아코디언을 접었다 펼 때 줄었다가 늘어나는 것에 있다.

하지만 요소를 display로 제어하면 요소는 순간이동 하는 것 처럼 생겼다 사라졌다 하기때문에 animation을 걸어 줄 수 없다. 학생 때 교과서 귀퉁이에 그림 그려서 만화를 만드는 것을 생각하면 된다. animaition은 단계가 없으면 존재할 수 없다.

그래서 JQuery가 제공하는 메서드인 .slideUp를 사용한다.

$(function () {
  $('dd:not(:first)').css('display', 'none');
  $('dl dt').on('click', function () {
    if ($('+dd', this).css('display') == 'none') {
      $('dl dd').slideUp('slow');
      $('+dd', this).slideDown('slow');
    }
  });
});

slideUp(),slideDown()

  • slideUp()
    선택한 요소를 위쪽으로 서서히 사라지게 한다.
    .slideUp( [duration ][, easing ] [, complete ] )
  • slideDown()
    선택한 요소를 아래쪽으로 서서히 나타나게 한다.
    .slideUp( [duration ][, easing ] [, complete ] )

slideUp()slideDown()의 정의를 보면 요소를 마법처럼 제어하는 메서드처럼 보이지만 API를 확인해보면 요소의 높이를 조절하고 그 사이에 애니메이션을 주어 서서히 사라지는 것처럼 보여준다는 것을 알 수 있다.

위의 코드를 해석하면 아래와 같다.

dt를 클릭했을 때,
만약 this (클릭된 dt 뒤에 있는 dd)가 display : none 상태라면,
모든 dd를 사라지게 하고, 해당 dd를 나타나게 한다.

즉 열려있는 컨텐츠말고 다른 컨텐츠를 클릭했을 때 항상 display : none 상태이기 때문에 컨텐츠가 모두 닫혔다가 해당 컨텐츠만 열리는 동작이 반복되는 원리로 간단한 코드만으로 아코디언 메뉴를 구현할 수 있다!

slideToggle()

slideToggle()
선택한 요소가 현재 사라진 상태라면 .slideDown() 메소드의 동작을 수행하고, 나타나 있는 상태라면 .slideUp() 메소드의 동작을 수행한다.

만약 요소의 .slideDown() .slideUp() 동작만 반복하고 싶다면 $('+dd', this).slideToggle(); 처럼 요소를 선택하고 slideToggle()을 쓰는 것만으로 구현할 수 있다.

👩‍💻

jQuery에서 제공하는 메서드를 사용하면 원하는 효과를 간단하게 구현할 수 있지만 대부분의 로직은 순수 JS로 개발할 때와 유사하기 때문에 해당 메서드가 어떤 원리로 동작하는지 API를 확인하면서 정밀하게 제어하는 방식으로 개발을 진행해야 겠다!

조금의 잡담
slideUp()은 up이라는 단어가 주는 긍정적인 느낌때문에(ㅋㅋ) 왠지 요소를 나타나게 해줄것 같아서 조금 헷갈렸다 창문 블라인드를 생각하면 블라인드가 올라가면서 너비가 줄어드는게 당연한데!!

자매품으로 JS API 중 배열 앞에서 부터 배열값을 추가하는 unshift()가 있다. un 때문에 왠지 부정적으로 들려서 배열값을 삭제할 것 같다 (ㅋㅋ)


[참고] https://api.jquery.com/slidedown/

0개의 댓글