Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> CSS

Tạo Accordion với CSS và JavaScript

Để 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 button
  • aria-controls="panel-id" liên kết với panel
  • id trê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'));