아코디언 메뉴 헤더를 클릭하면 밑에 콘텐츠가 나타나야 한다. 그리고 헤더를 한 번 더 클릭하면 콘텐츠가 사라진다.
헤더를 클릭하면 두 가지의 변화가 있다.
이 두 가지 변화를 모두 나타내기 위해서 클릭 시 헤더와 콘텐츠에게 클래스를 입히도록 한다.
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;
}
이제 클릭을 하면 컨텐츠가 생기는 것을 볼 수 있다. 그러나 한 가지 아쉬운 점은, 컨텐츠가 나타날 때 다음과 같이 헤더가 위로 밀린다는 점이다. 헤더의 위치는 고정이고, 그 밑으로 컨텐츠가 나타났으면 좋겠다. 이 말은 컨텐츠가 차지하는 공간이 헤더에 영향을 주지 않아야 한다는 말이다. 따라서 컨텐츠의 position을 absolute로 가져가는 방식을 생각해 볼 수 있겠다.
.accordion__header {
...
position: relative;
}
.accordion__content {
...
position: absolute;
}
이제 애니메이션을 넣을 차례이다.