Collapsible dan Accordion adalah komponen web yang mampu menampilkan dan menyembunyikan isi konten ketika judul dari konten tersebut diklik. Komponen ini umum digunakan pada konten yang menyajikan informasi tentang pertanyaan yang paling sering ditanyakan atau Frequently Asked Questions (FAQ).
Artikel ini akan membahas pembuatan komponen tersebut dengan memanfaatkan elemen HTML <details>
dan <summary
>. Untuk Collapsible kita akan membuatnya menggunakan CSS saja, sementara JavaScript baru akan kita pakai ketika membuat Accordion.
Sebelum mulai, berikut saya lampirkan kode latihan jika kamu ingin sambil mempraktikkannya:
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Membuat Collapsible dan Accordion | divClassId</title>
<link rel="stylesheet" href="./style.css">
<script defer src="./script.js"></script>
</head>
<body>
<aside class="faq">
<h3>Frequently Asked Questions</h3>
<div class="faq__items">
<details open>
<summary>
<strong>Apa itu HTML?</strong>
<img src="./chevron.svg" alt="">
</summary>
<p>HTML adalah bahasa <em>markup</em> yang digunakan untuk menyusun struktur web.</p>
</details>
<details>
<summary>
<strong>Apa itu CSS?</strong>
<img src="./chevron.svg" alt="">
</summary>
<p>CSS adalah bahasa <em>stylesheet</em> yang digunakan untuk mengatur tampilan atau visual web.</p>
</details>
<details>
<summary>
<strong>Apa itu JavaScript?</strong>
<img src="./chevron.svg" alt="">
</summary>
<p>JavaScript adalah bahasa pemrograman yang digunakan pada web agar bisa tampil dinamis dan interaktif.</p>
</details>
</div>
</aside>
</body>
</html>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--color-black: #111111;
--color-green: #0b6758;
--color-white: #fcfcfc;
}
html {
height: 100%;
}
body {
background-color: var(--color-green);
color: var(--color-black);
font-family: sans-serif;
height: 100%;
line-height: 1.5;
}
.faq {
padding: 20px 10px;
}
.faq > h3 {
color: var(--color-white);
font-size: 1.25rem;
text-align: center;
}
.faq__items {
}
.faq__items > details {
}
.faq__items > details > summary {
}
.faq__items > details[open] > summary > img {
}
.faq__items > details > p {
}
Untuk gambar chevron.svg bisa kamu unduh pada tautan berikut:
Sekarang, mari kita buat!
Membuat Collapsible
Jika kamu menjalankan latihan di atas, kamu akan melihat bahwa penggunaan elemen <details>
dan <summary>
akan langsung menghasilkan komponen ini. Jadi, tugas kita selanjutnya adalah hanya tinggal mengatur tampilannya saja.
Untuk permulaan, kita beri style berikut terlebih dahulu agar elemen container FAQ memiliki background putih dan tampil di tengah (seperti judulnya):
.faq__items {
background-color: var(--color-white);
margin: 10px auto 0;
max-width: 360px;
padding: 10px;
}
.faq__items > details {
margin-bottom: 1px;
}
max-width: 360px
ditambahkan agar lebar container responsif dengan lebar maksimalnya sebesar 360px saja.margin: 10px auto 0
ditambahkan untuk memberi jarak antara container dengan judul di atasnya sebesar 10px dan nilaiauto
akan membuatnya berada di tengah secara horizontal.padding: 10px
ditambahkan agar konten di dalam container dengan tepinya memiliki jarak sebesar 10px.margin-bottom: 1px
pada selector.faq__items > details
ditambahkan agar ada sedikit jarak antara item atau masing-masing FAQ (efeknya akan terlihat nanti).
Selanjutnya, kita beri style berikut untuk mengatur tampilan dari setiap judul (item) FAQ:
.faq__items > details > summary {
align-items: center;
background-color: var(--color-green);
color: var(--color-white);
cursor: pointer;
display: flex;
justify-content: space-between;
list-style: none;
padding: 10px;
}
list-style: none
ditambahkan untuk menghilangkan tanda panah bawaan elemen<summary>
.cursor: pointer
ditambahkan agar kursor mouse berubah ketika berada di atas judul item menjadi ikon yang menandakan bahwa itu bisa diklik.display: flex
danalign-items: center
ditambahkan untuk mengaktifkan CSS Flexbox pada elemen ini sehingga kita bisa mengatur posisi elemen-elemen di dalamnya agar ke tengah secara vertikal.justify-content: space-between
ditambahkan agar jarak antara judul dan tanda chevron saling berjauhan.
Saat ini tampilan dari setiap judul item sudah lebih baik. Namun, masih ada satu hal lagi yang bisa kita percantik, yaitu tanda chevron yang akan menyesuaikan arahnya tergantung apakah item FAQ sedang terbuka atau tidak.
Untuk persoalan ini CSS masih dapat menanganinya dengan memanfaatkan selector details[open]
dan mengubah arah chevron-nya menggunakan fungsi CSS rotateX()
milik property transform
, seperti berikut:
.faq__items > details[open] > summary > img {
transform: rotateX(180deg);
}
Terakhir, kita hanya perlu mengatur jarak paragraf di dalamnya dengan style berikut:
.faq__items > details > p {
padding: 10px;
}
Membuat Accordion
Accordion sebenarnya serupa dengan Collapsible. Bedanya, komponen ini hanya dapat menampilkan satu item FAQ saja dan akan menyembunyikan item lainnya yang sedang terbuka.
Karena serupa, sekarang kita hanya tinggal membuat efek tersebut saja dengan bantuan JavaScript. Berikut adalah kodenya:
document.addEventListener('DOMContentLoaded', () => {
const faq = Array.from(document.querySelectorAll('.faq__items > details'));
faq.forEach((item) => {
item.addEventListener('click', (event) => {
const active = faq.find((item) => item.open);
if (!event.currentTarget.open && active) {
active.open = false;
}
});
});
});
Berikut penjelasannya:
document.addEventListener('DOMContentLoaded', () => { ... });
Event
DOMContentLoaded
ditambahkan untuk memastikan kode JavaScript di dalamnya baru akan tereksekusi setelah kode HTML selesai dimuat dan tersedia pada DOM.const faq = Array.from(document.querySelectorAll('.faq__items > details'));
Kode ini akan mengambil semua elemen
<details>
dan menyimpannya ke dalam variabelfaq
.Perlu diperhatikan bahwa terjadi konversi tipe data dari yang semula berbentuk NodeList object menjadi Array. Ini penting karena nantinya kita akan menggunakan method
find()
yang hanya tersedia pada Array.faq.forEach((item) => { item.addEventListener('click', (event) => { ... }); });
Kode ini akan melakukan perulangan pada variabel
faq
sehingga kita dapat menempatkan eventclick
untuk setiap item (elemen) yang ditampungnya.const active = faq.find((item) => item.open);
Kode ini akan mencari elemen
<details>
yang sedang terbuka (memiliki atributopen
) dan menyimpannya ke dalam variabelactive
.if (!event.currentTarget.open && active) { active.open = false; }
Kode ini akan mencocokkan variabel
active
yang bernilaitrue
dengan nilai dari!event.currentTarget.open
. Perlu diperhatikan bahwa tanda!
di awal kodeevent.currentTarget.open
akan membalik nilainya dari yang semulafalse
menjaditrue
.Dengan begitu, variabel
active
yang menampung elemen<details>
dengan atributopen
dapat kita ubah nilainya menjadifalse
, sehingga item FAQ lainnya yang sedang terbuka akan otomatis tertutup dan tinggal menyisakan item yang baru saja kita klik yang terbuka.
Demikian pembahasan tentang membuat Collapsible dan Accordion. Semoga bermanfaat.