Tạo một trình đơn accordion độc quyền có nhiều phần tử <details>
có cùng một name
.
Accordion
Một mẫu giao diện người dùng phổ biến trên web là thành phần xếp nếp. Đây là một thành phần bao gồm một số tiện ích thông tin công bố có thể được mở rộng (hoặc thu gọn) riêng lẻ để hiển thị (hoặc ẩn) nội dung của chúng.
Để triển khai mẫu này trên web, bạn kết hợp một vài phần tử <details>
và thường nhóm các phần tử đó lại với nhau để cho biết rằng chúng thuộc cùng một nhóm.
Hộp xếp độc quyền
Hỗ trợ trình duyệt
Một biến thể của mẫu accordion là accordion độc quyền, trong đó chỉ có thể mở một trong các tiện ích công bố cùng một lúc.
Để tạo một trình đơn accordion độc quyền trên web, bạn thêm thuộc tính name
vào các phần tử <details>
. Khi sử dụng thuộc tính này, nhiều phần tử <details>
có cùng giá trị name
sẽ tạo thành một nhóm ngữ nghĩa và các phần tử này sẽ hoạt động như một ngăn xếp độc quyền. Khi bạn mở một trong các phần tử <details>
của nhóm, phần tử đã mở trước đó sẽ tự động đóng.
<details name="learn-css">
<summary>Welcome to Learn CSS!</summary>
<p>…</p>
</details>
<details name="learn-css">
<summary>Box Model</summary>
<p>…</p>
</details>
<details name="learn-css">
<summary>Selectors</summary>
<p>…</p>
</details>
Một trang có thể có nhiều ngăn xếp độc quyền. Bất cứ khi nào bạn sử dụng giá trị name
mới trên phần tử <details>
, một nhóm logic mới sẽ được tạo.
Các phần tử <details>
thuộc một ngăn xếp độc quyền không nhất thiết phải là phần tử đồng cấp. Các phần tử này có thể nằm rải rác trong tài liệu. Thuộc tính name
là thuộc tính nhóm các thành phần này, chứ không phải thứ tự DOM của các thành phần đó.
Thêm tính năng tự động điền cho accordion độc quyền
Với JavaScript sau đây, bạn có thể polyfill hành vi của accordion độc quyền. Mã này dựa vào sự kiện toggle
của phần tử <details>
.
Khi một phần tử <details>
có name
mở ra, mã sẽ tìm các phần tử <details>
đang mở khác có cùng giá trị cho thuộc tính name
và đóng các phần tử đó.
document.querySelectorAll("details[name]").forEach(($details) => {
$details.addEventListener("toggle", (e) => {
const name = $details.getAttribute("name");
if (e.newState == "open") {
document
.querySelectorAll(`details[name=${name}][open]`)
.forEach(($openDetails) => {
if (!($openDetails === $details)) {
$openDetails.removeAttribute("open");
}
});
}
});
});
Một số phiên bản trình duyệt cũ không kích hoạt sự kiện toggle
này. Trong những trình duyệt đó, mã polyfill sẽ không làm gì cả. Về tính năng cải tiến dần, đây là hành vi được chấp nhận.