Để tạo một Accordion (menu thu gọn/mở rộng) với CSS và JavaScript, code như sau:
Ví dụ hoàn chỉnh
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.demo {
background-color: #eee;
cursor: pointer;
padding: 25px;
width: 100%;
border: none;
text-align: left;
font-size: 1rem;
transition: background-color 0.3s;
}
.demo:hover,
.demo.active {
background-color: #ccc;
}
.panel {
padding: 0 18px;
display: none;
background-color: #F0F8FF;
overflow: hidden;
max-height: 0;
transition: max-height 0.3s ease-out, padding 0.3s;
}
.panel.open {
display: block;
max-height: 500px; /* đủ lớn cho content */
padding: 18px;
}
</style>
</head>
<body>
<h2>Examination</h2>
<p>Following is the information on exams:</p>
<button class="demo">Admit Card</button>
<div class="panel"><p>Admit Card will release on 25th March.</p></div>
<button class="demo">Exam Date</button>
<div class="panel"><p>Exam will held on 30th March.</p></div>
<script>
document.querySelectorAll('.demo').forEach(btn => {
btn.addEventListener('click', function() {
this.classList.toggle('active');
const panel = this.nextElementSibling;
panel.classList.toggle('open');
});
});
</script>
</body>
</html>
Cải tiến: Chỉ mở một panel tại một thời điểm (Single open)
document.querySelectorAll('.demo').forEach(btn => {
btn.addEventListener('click', function() {
// Đóng các panel khác
document.querySelectorAll('.panel.open').forEach(p => {
if (p !== this.nextElementSibling) p.classList.remove('open');
p.previousElementSibling.classList.remove('active');
});
// Toggle panel hiện tại
this.classList.toggle('active');
this.nextElementSibling.classList.toggle('open');
});
});
CSS-only Accordion (Không cần JS) - với <details>/<summary>
<details class="accordion">
<summary>Admit Card</summary>
<p>Admit Card will release on 25th March.</p>
</details>
<details class="accordion">
<summary>Exam Date</summary>
<p>Exam will held on 30th March.</p>
</details>
<style>
.accordion summary {
background: #eee; padding: 1rem; cursor: pointer;
list-style: none; /* Ẩn marker mặc định */
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion[open] summary { background: #ccc; }
.accordion p { padding: 1rem; margin: 0; background: #f0f8ff; }
/* Animation (hạn chế) */
.accordion summary::after {
content: "+"; float: right; transition: transform 0.3s;
}
.accordion[open] summary::after { transform: rotate(45deg); }
Accessibility
- Dùng
<button>cho trigger (focusable, keyboard accessible) aria-expanded="true/false"trên buttonaria-controls="panel-id"liên kết với panelidtrên panel,role="region"
<button class="demo" aria-expanded="false" aria-controls="panel1">Admit Card</button>
<div class="panel" id="panel1" role="region" hidden>...</div>
/* JS update aria */
btn.setAttribute('aria-expanded', panel.classList.contains('open'));