ezgif.com-gif-maker (5) 복사본.gif

아코디언 메뉴 헤더를 클릭하면 밑에 콘텐츠가 나타나야 한다. 그리고 헤더를 한 번 더 클릭하면 콘텐츠가 사라진다.

헤더를 클릭하면 두 가지의 변화가 있다.

이 두 가지 변화를 모두 나타내기 위해서 클릭 시 헤더와 콘텐츠에게 클래스를 입히도록 한다.

const handleClickHeader = (header, content) => {
  if (header.classList.contains('accordion__header--open')) {
    header.classList.remove('accordion__header--open')
    content.classList.remove('accordion__content--open')
    return
  }

  header.classList.add('accordion__header--open')
  content.classList.add('accordion__content--open')
}

accordionHeader.addEventListener('click', e => handleClickHeader(accordionHeader, accordionContent))

HTML 요소에 특정 클래스가 있는지 여부를 판단할 수 있는 방식은 HTMLElement.classList.contains(’클래스명’)을 사용하는 것이다. 만약 --open이라는 클래스가 헤더에 있다면 헤더와 컨텐츠에서 해당 클래스를 지워주고, 없다면 추가해준다.

이 코드를 classList.toggle(’클래스명’)을 사용하면 좀 더 간단하게 짤 수 있다.

const handleClickHeader = (header, content) => {
  header.classList.toggle('accordion__header--open')
  content.classList.toggle('accordion__content--open')
}

아코디언의 콘텐츠는 클릭하기 전에는 보이지 않다가 클릭하면 나타나야 한다. 따라서 CSS를 display: none으로 설정해서 사용할 수 있다.

.accordion__content {
  background-color: white;
  height: 100px;
  overflow-y: scroll;
  padding: 8px 16px;
  display: none;
}

.accordion__content--open {
  display: block;
}

accordion.gif

이제 클릭을 하면 컨텐츠가 생기는 것을 볼 수 있다. 그러나 한 가지 아쉬운 점은, 컨텐츠가 나타날 때 다음과 같이 헤더가 위로 밀린다는 점이다. 헤더의 위치는 고정이고, 그 밑으로 컨텐츠가 나타났으면 좋겠다. 이 말은 컨텐츠가 차지하는 공간이 헤더에 영향을 주지 않아야 한다는 말이다. 따라서 컨텐츠의 position을 absolute로 가져가는 방식을 생각해 볼 수 있겠다.

.accordion__header {
	...
  position: relative;
}

.accordion__content {
  ...
  position: absolute;
}

이제 애니메이션을 넣을 차례이다.