VanilaJS 로 아코디언 메뉴 구현하기
- Published on
아코디언 메뉴는 웹사이트에서 정보를 효과적으로 표시하고 사용자 경험을 향상시키는 데 자주 사용됩니다. 이번 글에서는 VanillaJS만을 사용하여 간단한 아코디언 메뉴를 구현하는 방법을 설명하겠습니다. 별도의 라이브러리나 프레임워크 없이 순수 자바스크립트만으로 구현할 수 있습니다.
시작하기
먼저, 아코디언 메뉴를 포함할 HTML 구조를 만들어봅니다. 각 아코디언 항목인 .accordion-item
에는 제목이 들어갈 button
과 내용이 들어갈 section
으로 구분됩니다.
HTML
<div id="accordion">
<div class="accordion-item">
<button>Section 1</button>
<section>
<p>내용</p>
</section>
</div>
</div>
CSS 스타일링
아코디언의 기본 스타일을 CSS로 정의해보겠습니다. 기본적으로, 내용은 숨겨져 있어야 하므로 section에 height:0
을 주었습니다.
아코디언이 열린 상태.active
이면 배경색과 글자색을 변경합니다.
.accordion-item button {
width: 100%;
padding: 10px;
margin: 0;
border: none;
text-align: left;
font-weight: bold;
font-size: 18px;
background-color: #eee;
cursor: pointer;
transition:
background-color 0.2s ease-in-out,
color 0.2s ease-in-out;
}
.accordion-item section {
border-bottom: 1px solid #ccc;
height: 0;
overflow: hidden;
transition: height 0.4s ease;
}
.accordion-item section p {
padding: 10px;
}
.accordion-item.active button {
background-color: #333;
color: #efefef;
}
자바스크립트로 동작 추가하기
이제 VanillaJS를 사용하여 아코디언 메뉴의 동작을 구현해보겠습니다. 아코디언 제목button
을 클릭하면 section
의 높이를 지정합니다. 그리고 브라우저 사이즈 변경 시 열려있는 아코디언 아이템의 section
의 높이를 새로 지정해줍니다.
// 아코디언 전체
const accordion = document.getElementById('accordion');
// 아코디언 클릭 트리거
const triggers = accordion.querySelectorAll('.accordion-item button');
// 트리거에 클릭 이벤트 추가
for (let i = 0; i < triggers.length; i++) {
triggers[i].addEventListener('click', toggleTrigger);
}
function toggleTrigger() {
const item = this.parentNode;
const section = this.nextElementSibling;
const p = section.querySelector('p');
if (item.classList.contains('active')) {
section.style.height = 0 + 'px';
} else {
section.style.height = p.clientHeight + 'px'; // section의 높이 지정
}
item.classList.toggle('active');
}
// 화면 사이즈 변경시 열려 있는 아코디언 아이템의 높이 조절
window.addEventListener('resize', () => {
const items = accordion.querySelectorAll('.accordion-item ');
items.forEach((item) => {
// 활성화된 아코디언이면 텍스트의 높이를 가져와서 section의 높이에 지정
if (item.classList.contains('active')) {
const section = item.querySelector('section');
const p = section.querySelector('p');
section.style.height = p.clientHeight + 'px';
}
});
});
전체 코드
아래는 전체 코드입니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="initial-scale=1.0, minimum-scale=1.0, width=device-width, viewport-fit=cover"
/>
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
.accordion-item button {
width: 100%;
padding: 10px;
margin: 0;
border: none;
text-align: left;
font-weight: bold;
font-size: 18px;
background-color: #eee;
cursor: pointer;
transition:
background-color 0.2s ease-in-out,
color 0.2s ease-in-out;
}
.accordion-item section {
border-bottom: 1px solid #ccc;
height: 0;
overflow: hidden;
transition: height 0.4s ease;
}
.accordion-item section p {
padding: 10px;
}
.accordion-item.active button {
background-color: #333;
color: #efefef;
}
</style>
<title>VanilaJS Accordion</title>
</head>
<body>
<div id="accordion">
<div class="accordion-item">
<button>Section 1</button>
<section>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text
ever since the 1500s, when an unknown printer took a galley of type
and scrambled it to make a type specimen book. It has survived not
only five centuries, but also the leap into electronic typesetting,
remaining essentially unchanged.
</p>
</section>
</div>
<div class="accordion-item">
<button>Section 2</button>
<section>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text
ever since the 1500s, when an unknown printer took a galley of type
and scrambled it to make a type specimen book. It has survived not
only five centuries, but also the leap into electronic typesetting,
remaining essentially unchanged. It was popularised in the 1960s
with the release of Letraset sheets containing Lorem Ipsum passages,
and more recently with desktop publishing software like Aldus
PageMaker including versions of Lorem Ipsum.
</p>
</section>
</div>
<div class="accordion-item">
<button>Section 3</button>
<section>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text
ever since the 1500s, when an unknown printer took a galley of type
and scrambled it to make a type specimen book.
</p>
</section>
</div>
</div>
<script>
// 아코디언 전체
const accordion = document.getElementById('accordion');
// 아코디언 클릭 트리거
const triggers = accordion.querySelectorAll('.accordion-item button');
// 트리거에 클릭 이벤트 추가
for (let i = 0; i < triggers.length; i++) {
triggers[i].addEventListener('click', toggleTrigger);
}
function toggleTrigger() {
const item = this.parentNode;
const section = this.nextElementSibling;
const p = section.querySelector('p');
if (item.classList.contains('active')) {
section.style.height = 0 + 'px';
} else {
section.style.height = p.clientHeight + 'px'; // section의 높이 지정
}
item.classList.toggle('active');
}
// 화면 사이즈 변경시 열려 있는 아코디언 아이템의 높이 조절
window.addEventListener('resize', () => {
const items = accordion.querySelectorAll('.accordion-item ');
items.forEach((item) => {
// 활성화된 아코디언이면 텍스트의 높이를 가져와서 section의 높이에 지정
if (item.classList.contains('active')) {
const section = item.querySelector('section');
const p = section.querySelector('p');
section.style.height = p.clientHeight + 'px';
}
});
});
</script>
</body>
</html>