Đàn phong cầm độc quyền

Tạo một đàn phong cầm độc quyền với 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. Đây là thành phần bao gồm một số tiện ích công bố có thể 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 chúng một cách trực quan để biểu thị rằng chúng thuộc về nhau.

Bản minh hoạ: Accordion với HTML và CSS.

Đàn phong cầm độc quyền

Hỗ trợ trình duyệt

  • 120
  • 120
  • x
  • 17.2

Một biến thể của mẫu đàn phong cầm là đàn phong cầm độc quyền, trong đó bạn chỉ có thể mở một trong các tiện ích công bố cùng lúc.

Để làm 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 thuộc tính này được dùng, 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 danh sách xếp âm độ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>
Bản minh hoạ: Đàn xếp độc quyền với HTML và CSS.

Một trang có thể có nhiều phong cách độc quyền. Mỗi khi 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.

Bản minh hoạ: Nhiều trình tự âm thanh độc quyền sử dụng HTML và CSS.

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 thành phần đồng cấp. Chúng có thể nằm rải rác trên tài liệu. Thuộc tính name sẽ nhóm các thành phần lại với nhau, chứ không phải đơn đặt hàng DOM.

Xếp bài cho đàn phong cầm độc quyền

Với JavaScript sau, bạn có thể lấp đầy hành vi của đàn phong cầm độ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>name mở, mã này sẽ tìm các phần tử <details> đang mở khác có cùng giá trị với 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 các trình duyệt đó, mã polyfill sẽ không có tác dụng gì. Về mặt nâng cấp dần dần, đây là hành vi được chấp nhận.