Dico

아코디언(accordion)을 만들어보자.

안녕하세요 Lovefield입니다.

이번글도 지인이 요청해준 JavaScript로 Accordion을 만드는법에 대해서 알려드리겠습니다.

기능을 만들기위해 가장먼저 해야하는 조건들을 서술해볼까요?

  1. 버튼을 클릭하면 버튼이 속해있는 영역의 컨텐츠가 토글되어야한다.
  2. 그륩속성을 가지고 있으면 같은 다른 영역의 컨텐츠는 가려져야 한다.

저번 탭과 는 다르게 굉장히 심플하죠?

HTML 구조입니다.

<div class="accordion_area">
  <button class="btn btn_toggle">Whit is accordion?</button>
  <div class="content_area">
    Accordion is accordion.
  </div>
</div>

<div class="accordion_area">
  <button class="btn btn_toggle">Whit is accordion?</button>
  <div class="content_area">
    Accordion is accordion.
  </div>
</div>

<div class="accordion_area" data-group="one">
  <button class="btn btn_toggle">Whit is accordion?</button>
  <div class="content_area act">
    Accordion is accordion.
  </div>
</div>

<div class="accordion_area" data-group="one">
  <button class="btn btn_toggle">Whit is accordion?</button>
  <div class="content_area">
    Accordion is accordion.
  </div>
</div>

<div class="accordion_area" data-group="one">
  <button class="btn btn_toggle">Whit is accordion?</button>
  <div class="content_area">
    Accordion is accordion.
  </div>
</div>

2개의 개별 아코디언과 3개의 그룹으로 묶은 아코디언을 구성했습니다.

그룹인 것을 구분하기 위해 data-*타입을 이용해 같은 이름을 부여했습니다.

각 아코디언 영역은 accordion_area 클레스로 지정했습니다.

컨텐츠 영역의 활성화는 act를 사용했습니다.

act 는 active의 약어로써 많이 사용하는 편입니다.

그룹으로 지정된 영역 중 첫 번째 영역의 컨텐츠에 act를 이용해 미리 펼쳐놓았습니다.

html

HTML을 작성하면 위처럼 나오게 됩니다.

다음은 CSS입니다.

body{background:#f4f4f4}
.btn{padding:0;background:transparent;border:0;outline:0}

.accordion_area{width:600px;margin:20px auto;border:1px solid #000}
.accordion_area .btn_toggle{display:block;width:100%;height:30px;padding:0 10px;background:#fff;font-size:14px;text-align:left;line-height:30px;box-sizing:border-box}
.accordion_area .btn_toggle::before{display:inline;content:'Q.'}
.accordion_area .content_area{display:none;padding:10px;background:#f4f4ff}
.accordion_area .content_area::before{display:inlnie;content:'A.'}
.accordion_area .content_area.act{display:block}

reset CSS는 생략했습니다.

css

모양이 준비되었으니 이제 JavaScript를 적용할 차례입니다.

function bindingAccordionEvent(wrap){
  
}

우선 함수를 하나 만들어줍니다.

class 명을 받아서 이벤트를 부여하는 역할을 할것이므로 이름도 이벤트를 적용한다는 뜻으로 지어줍니다.

function bindingAccordionEvent(wrap){
  let areaArr = document.querySelectorAll(wrap);
  
  areaArr.forEach(function(area){
    
  });
}

인자로 넘어오는 class 명을 이용해 엘리먼트를 선택해줍니다.

forEach를 통해 각각의 아코디언 영역이 따로 동작하도록 해줍니다.

areaArr.forEach(function(area){
  let hasGroup = area.dataset['group'] !== undefined ? true : false;
  // 아코디언 영역에 data-group의 값이 있으면 true 아닐 경우 false (삼항 연산자)
  let btn = area.querySelector('.btn_toggle');
});

우선 영역 안에서 필요한 값들을 지정합니다.

삼항연산자를 이용해서 영역이 group 값을 가졌는지에 대해서 유무를 저장합니다.

이벤트를 부여할 버튼도 선택해줍니다.

btn.addEventListener('click', function(){
  if(hasGroup === true){ // 그룹이 있을경우
    let name = area.dataset['group'];
    // 그룹명 가져오기
    let groupArr = document.querySelectorAll(wrap + '[data-group="'+ name +'"]');
    // 그룹명을 가지고 있는 아코디언 영역을 전부 선택
    let thisContent = area.querySelector('.content_area');
    // 현재 아코디언 영역의 컨텐츠 영역
    
    groupArr.forEach(function(group){
       let content = group.querySelector('.content_area');
      content.classList.remove('act');
    });
    thisContent.classList.add('act');
  }else{ // 그룹이 없을경우
    let content = area.querySelector('.content_area');
    // 현재 아코디언 영역의 컨텐츠 영역
    content.classList.toggle('act');
  }
});

이제 버튼에 click 이벤트를 부여합니다.

그룹이 있을경우와 없을경우를 처리해야 하므로 이전에 얻은 값인 hasGroup을 이용해 if문으로 분기해줍니다.

그룹이 있을 경우는 다음처럼 작동합니다.

  1. 그룹명을 가져옵니다.
  2. 해당 그룹명을 가지고 있는 아코디언의 컨텐츠 영역을 모두 가립니다.
  3. 현재 아코디언의 컨텐츠 영역을 보여줍니다.

그룹이 없을 경우는 다음과 같이 작동합니다

  1. act 클레스가 있으면 없애준다.
  2. act 클레스가 없으면 부여한다.

이제 작성한 함수를 실행 시켜 줍니다.

bindingAccordionEvent('.accordion_area');

아코디언은 상당히 간단한 기능입니다.

결과물은 아래에서 혹은 codepen에서 보실 수 있습니다.