Tạo một đàn phong cầm độc quyền gồm nhiều phần tử <details>
có cùng name
.
Đàn phong cầm
Mẫu giao diện người dùng phổ biến trên web là thành phần đàn phong cầm. Đây là thành phần bao gồm một số tiện ích thông tin công bố có thể mở rộng (hoặc thu gọn) một cách riêng lẻ để hiện (hoặc ẩn) nội dung.
Để triển khai mẫu này trên web, bạn sẽ kết hợp một vài phần tử <details>
và thường nhóm lại một cách trực quan để cho biết các phần tử này thuộc về nhau.
Đàn phong cầm độc quyền
Hỗ trợ trình duyệt
Một biến thể của mẫu đàn phong cầm là đàn phong cầm độc quyền, trong đó chỉ có thể mở một trong các tiện ích thông tin công bố cùng một lúc.
Để thực hiện việc này trên web, giờ đây, bạn có thể thêm thuộc tính name
vào các phần tử <details>
. Khi bạn 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à chúng sẽ hoạt động như một nhóm ngữ nghĩa riêng. Khi bạn mở một trong các phần tử <details>
của nhóm, phần tử bạn đã 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 phong cầm độc quyền. Bất cứ khi nào bạn sử dụng một giá trị name
mới trên phần tử <details>
, một nhóm logic mới sẽ được tạo.
Xin lưu ý rằng các phần tử <details>
thuộc một đàn phong cầm độc quyền không nhất thiết phải là các phần tử đồng cấp. Chúng có thể nằm rải rác trên tài liệu. Đó là thuộc tính name
giúp nhóm các hình ảnh đó, chứ không phải thứ tự DOM.
Polyfill (Người chơi đàn phong cầm độc quyền)
Với JavaScript sau đây, bạn có thể polyfill hành vi của đàn 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ở, mã này sẽ tìm các phần tử <details>
mở khác có cùng giá trị cho thuộc tính name
rồi đóng các phần tử đó lại.
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 các trình duyệt đó, mã polyfill sẽ không có tác dụng gì. Về tính năng nâng cao tăng dần, đây là hành vi được chấp nhận.