간단하게 아코디언 메뉴 만들기

JavaScript

자바스크립트를 사용해서 정말 간단하게 아코디언 메뉴를 만드는 방법을 기록한다.

미리보기

HTML

<ul>
  <li class="on">
    <button class="button">menu1</button>
    <p id="menu1" class="content">description</p>  
  </li>
  <li>
    <button class="button">menu2</button>
    <p id="menu2" class="content">description</p>  
  </li>
  <li>
    <button class="button">menu3</button>
    <p id="menu3" class="content">description</p>  
  </li>
  <li>
    <button class="button">menu4</button>
    <p id="menu4" class="content">description</p>  
  </li>
</ul>

ul>li 태그로 하지 않아도 된다.
중요한건 class="on", 버튼을 눌렀을 때 부모 태그에 on class를 추가한다.

코드상에선 기본으로 on class가 추가되어 있지만, 빠져도 상관없다.

버튼의 경우 <a>, <button> 중 어느것을 사용할지 고민했는데 이번엔 <a> 태그를 사용했다.
모종의 이유로 브라우저가 CSS, JS가 출력되지 않는 경우 A 태그의 엥커 이동 기능이 작동되게 하기 위함이다.

+ 2022-10-06 내용 추가
접근성을 지키려면 페이지 이동이 발생하는 <a> 태그 대신, <button> 태그를 사용하라고 한다.
무언가를 만들었을 때 접근성을 알고싶다면 부트스트랩 사이트를 참고하면 아주 좋다.

⛔️ 주의사항1
div로 버튼을 만들지 말자.
div로 만들면 키보드의 “Tab”으로 버튼에 focus 하는게 불가능하기 때문이다.

⛔️ 주의사항2
<a> 태그 안에는 <div>, <span>, … 등등 비교적 자유롭게 태그가 포함할 수 있지만, <button> 태그 안에는 블록 태그는 포함하면 안되고 인라인 태그만 사용해야한다. (참고)

CSS

ul {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 0;
  padding: 0;
  max-width: 500px;
  width: 100%;
  list-style: none;
}

li {
  .button {
    display: block;
    padding: 20px;
    width: 100%;
    color: #000;
    text-align: left;
    background-color: #ddd;
    border: 0;
    cursor: pointer;
  }

  .content {
    display: none;
    margin: 0;
    padding: 20px;
    background-color: #fff;
    border-top: 1px solid #ddd;
  }
  
  &.on {
    .button {
      background-color: #fff;
      font-weight: bold;
    }
    
    .content {
      display: block;
    }
  }
}

ul 의 스타일은 모양을 잡아주기 위해 추가했기 때문에 크게 신경쓰지 않아도 된다. li 안의 스타일을 커스텀 해서 사용하면 된다.

마크업을 변경했다면 스타일도 함께 변경하는걸 잊지말자.

JavaScript

const buttons = document.querySelectorAll('.button');

buttons.forEach(function(button, index) {
  button.addEventListener('click', function(e) {
    e.preventDefault();
    
    this.parentNode.classList.toggle('on');
    
    buttons.forEach(function(button2, index2) {
      if ( index !== index2 ) {
        button2.parentNode.classList.remove('on');
      }
    });
  });
});

간단하게 .button을 전부 가져와서 JavaScriot forEach를 사용해 반복문을 돌렸다.

반복되는 모든 버튼에 클릭 이벤트를 추가했고 preventDefault();로 기본 클릭 이벤트를 제거했다.
그리고 클릭할 때 마다 나(this)에게 on class를 넣었다 뺄 수 있게 toggle 로 했다.

마지막으로 반복문 안에 다시 버튼 전체에 대한 반복문을 돌려서, 지금 클릭한 버튼의 index와 일치하지 않은 index를 가진 모든 버튼에서 on class를 제거한다.

accordionjavascriptmenu아코디언아코디언 메뉴
블로그
프로젝트
스터디