Các lựa chọn khác để tạo kiểu <chi tiết>

Ngày xuất bản: Ngày 6 tháng 11 năm 2024

Kể từ Chrome 131, bạn có nhiều lựa chọn hơn để tạo kiểu cho cấu trúc của các phần tử <details><summary>. Giờ đây, bạn có thể sử dụng các phần tử này khi tạo tiện ích thông tin công bố hoặc tiện ích đàn phong cầm.

Cụ thể, các thay đổi được giới thiệu trong Chrome 131 cho phép sử dụng thuộc tính display trên các phần tử này và thêm phần tử giả ::details-content để tạo kiểu cho phần mở rộng và thu gọn.

Hỗ trợ trình duyệt

  • Chrome: 131.
  • Edge: không được hỗ trợ.
  • Firefox: không được hỗ trợ.
  • Safari: không được hỗ trợ.

Thiết lập display trên phần tử <details>

Trước đây, bạn không thể thay đổi loại hiển thị của phần tử <details>. Giờ đây, quy định hạn chế này đã được nới lỏng, cho phép bạn sử dụng bố cục lưới hoặc bố cục flex trên phần tử <details>.

Trong ví dụ sau, đành phong cầm độc quyền bao gồm một số phần tử <details> được đặt cạnh nhau. Khi mở rộng một trong các phần tử <details>, nội dung của phần tử đó sẽ được đặt bên cạnh <summary>.

Bản minh hoạ

Đang ghi

Bản ghi https://codepen.io/web-dot-dev/pen/VwoBQjY trong Chrome 131

Bạn có thể thực hiện việc này bằng cách sử dụng bố cục flex trên phần tử <details>, sử dụng CSS sau:

details {
  display: flex;
  flex-direction: row;
}

Các giá trị hiển thị khác cũng được phép, chẳng hạn như grid.

Lưu ý về cách sử dụng display: inline

Giá trị display có thể có kết quả không mong muốn là inline. Không phải vì không hoạt động mà là do các giới hạn của trình phân tích cú pháp HTML.

Khi đặt một phần tử <details> bên trong một đoạn văn, nó buộc trình phân tích cú pháp HTML phải đóng đoạn mở trước tiên, như định nghĩa trong mục 13.2.6.4.7 của Tiêu chuẩn HTML:

Thẻ bắt đầu có tên thẻ là một trong các thẻ sau: "address", "article", "aside", "blockquote", "center", "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul"

Nếu ngăn xếp các phần tử đang mở có phần tử p trong phạm vi nút, hãy đóng phần tử p. Chèn một phần tử HTML cho mã thông báo.

Do đó, <details> sẽ chảy theo hướng khối, bất kể bạn đã đặt display: inline hay chưa.

Ví dụ: mã đánh dấu sau

<p>Hello <details>…</details> world</p>

Sau khi phân tích cú pháp, sẽ trở thành:

<p>Hello </p><details>…</details> world<p></p>

Bạn có thể tự xem trong bản minh hoạ này bằng cách kiểm tra mã đánh dấu đã phân tích cú pháp bằng Công cụ của Chrome cho nhà phát triển.

Xin lưu ý rằng điều này chỉ áp dụng cho việc lồng <details> bên trong <p>. Bạn có thể sử dụng display: inline trên <details> bên trong <div>.

Phần tử giả ::details-content

Trong các trình duyệt, phần tử <details> được triển khai bằng cách sử dụng Shadow DOM. Phần tử này chứa một <slot> cho phần tóm tắt (có phần tử con tóm tắt mặc định) và một <slot> cho tất cả nội dung còn lại, nghĩa là tất cả phần tử con của phần tử <details> ngoại trừ phần tử <summary>.

<details>
  ↳ #shadow-root (user-agent)
      <slot id="details-summary">
        <summary>Details</summary>
        <!-- The summary goes here -->
      </slot>
      <slot id="details-content">
        <!-- All content goes here -->
      </slot>
</details>

Ngoài việc sử dụng nhiều loại màn hình hơn trên <details>, giờ đây, bạn có thể nhắm mục tiêu đến khung nội dung bằng phần tử giả ::details-content. Bạn có thể sử dụng lớp mô phỏng này để tạo kiểu cho vùng chứa gói nội dung của phần tử <details>.

details::details-content {
  border: 5px dashed hotpink;
}

Để chỉ áp dụng kiểu đã đặt khi phần tử <details> đang ở trạng thái mở, hãy thêm bộ chọn [open] vào đầu phần tử đó.

[open]::details-content {
  border: 5px dashed hotpink;
}

Bạn chỉ nên áp dụng kiểu cho phần tử ::details-content giả khi phần tử <details> ở trạng thái [open].

Bản minh hoạ

Đang ghi

Bản ghi https://codepen.io/web-dot-dev/pen/oNKMEYv trong Chrome 131

Loại display của ::details-content được đặt thành block trong trang tính kiểu UA, trong khi trước đây là display: contents. Thay đổi này có thể gây bất lợi cho bạn trong một số trường hợp, chẳng hạn như nội dung được công bố dựa vào height: 100%. Nếu đây là vấn đề bạn gặp phải, bạn có thể giải quyết bằng cách đặt lại loại display về contents như sau: details[open]::details-content { display: contents; }.

Tạo ảnh động cho phần tử giả ::details-content

Bạn có thể tạo ảnh động cho nội dung của phần tử <details> khi phần tử này mở rộng. Trong ví dụ sau, chiều rộng sẽ tạo ảnh động từ 0px đến 300px.

::details-content {
  transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
  width: 0;
}

[open]::details-content {
  width: 300px;
}

Ngoài việc chuyển đổi width, bạn cũng cần chuyển đổi thuộc tính content-visibility. Điều này là do giá trị của thành phần này thay đổi giữa trạng thái chưa mở và đã mở, như được xác định trong biểu định kiểu Tác nhân người dùng. Vì thuộc tính đó là một thuộc tính có thể tạo ảnh động riêng biệt, nên bạn cần có từ khoá allow-discrete để thuộc tính đó hoạt động.

Thêm vào bản minh hoạ độc quyền về accordion đã chia sẻ trước đó, kết quả sẽ như sau:

Bản minh hoạ

Đang ghi

Bản ghi https://codepen.io/web-dot-dev/pen/XWvBZNo trong Chrome 131

height cũng có thể là ảnh động. Để tạo ảnh động cho height: auto, bạn cần sử dụng interpolate-size hoặc calc-size(). Ngoài ra, để nội dung không bị tràn ra khỏi ::details-content giả lập, hãy áp dụng overflow: clip cho nội dung đó.

::details-content {
    transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
    height: 0;
    overflow: clip;
}

/* Browser supports interpolate-size */
@supports (interpolate-size: allow-keywords) {
    :root {
        interpolate-size: allow-keywords;
    }

    [open]::details-content {
        height: auto;
    }
}

/* Fallback for browsers with no interpolate-size support */
@supports not (interpolate-size: allow-keywords) {
    [open]::details-content {
        height: 150px;
        overflow-y: scroll; /* In case the contents should be taller than 150px */
    }
}

Bạn có thể xem mã hoạt động trong bản minh hoạ sau đây, lấy cảm hứng từ ngăn xếp của Material UI. Nội dung của mỗi phần tử <details> tạo hiệu ứng ảnh động rất đẹp.

Bản minh hoạ

Đang ghi

Bản ghi https://codepen.io/web-dot-dev/pen/ExqpQZM trong Chrome 131

Trong các trình duyệt không hỗ trợ ::details-content, thành phần này vẫn hoạt động tốt. Khách truy cập chỉ không thấy ảnh động.

Phát hiện tính năng

Để tính năng phát hiện tính năng hỗ trợ cho giả ::details-content trong CSS, hãy sử dụng đoạn mã sau.

@supports selector(::details-content) {
  
}

Bạn cũng có thể sử dụng tính năng phát hiện này làm cơ sở kiểm tra để biết trình duyệt mà khách truy cập đang sử dụng có hỗ trợ các giá trị hiển thị bổ sung hay không.

Những điểm cần cân nhắc về khả năng hỗ trợ tiếp cận

Việc giới thiệu phần tử giả ::details-content và khả năng thay đổi loại màn hình không ảnh hưởng đến khả năng hỗ trợ tiếp cận của phần tử <details>.

Giống như trước đây, ít nhất là trong các trình duyệt dựa trên Chromium và theo Tiêu chuẩn HTML, phần tử <details> có thể tìm kiếm được và tự động mở rộng khi trình duyệt cố gắng cuộn đến nội dung bị ẩn để phản hồi nội dung tìm trong trang, ScrollToTextFragment và điều hướng mảnh phần tử. Điều này không thay đổi.

Tuy nhiên, trước khi sử dụng các trình đơn accordion độc quyền, hãy cân nhắc xem điều này có hữu ích hay gây hại cho người dùng. Mặc dù việc sử dụng đàn phong cầm độc quyền giúp giảm lượng nội dung hình ảnh chiếm giữ, nhưng người dùng có thể phải mở nhiều vật phẩm để xem toàn bộ thông tin. Điều này có thể gây khó chịu cho những người dùng muốn xem nhiều mục cùng một lúc.

Còn việc tạo kiểu cho điểm đánh dấu thì sao?

Hiện tại, kiểu của điểm đánh dấu danh sách không tương tác được vì có hai phương pháp khác nhau, một phương pháp do Gecko và Chromium (hiện tại) thực hiện và một phương pháp khác do WebKit thực hiện (trước đây được chia sẻ với Chromium).

Sau khi tính năng này có thể tương tác, mục tiêu của chúng tôi là giúp bạn kiểm soát tốt hơn cách tạo kiểu cho điểm đánh dấu.

Các bản minh hoạ khác

Để kết thúc, sau đây là một số bản minh hoạ khác để bạn xem. Tất cả đều sử dụng ::details-content.

Accordion UIKit

Bản minh hoạ

Đang ghi

Bản ghi https://codepen.io/web-dot-dev/pen/rNXrJyQ trong Chrome 131

Bản minh hoạ này được tạo sau UIKit Accordion. Mã này thực tế giống với trình đơn accordion (bật/tắt) Material UI đã được chia sẻ trước đó.

Tiện ích thông tin công bố mở một phần

Bản minh hoạ

Đang ghi

Bản ghi https://codepen.io/web-dot-dev/pen/PoMBQmW trong Chrome 131

Bản minh hoạ này có một tiện ích thông tin công bố đã mở một phần, nội dung của tiện ích này đã hiển thị trên màn hình. Để đạt được điều này, content-visibility luôn được đặt thành visible. height được tạo ảnh động bằng calc-size() vì có một phép tính liên quan.

::details-content {
  content-visibility: visible; /* Make it always visible */
    
  transition: height 0.5s ease;
  height: 150px;
  overflow: clip;
}

[open]::details-content {
  height: calc-size(auto, size + 0.5rem); /* calc-size because we need to add a length */
}

Để thuận tiện cho việc tạo kiểu, nội dung được gói trong một div trình bao bọc. div trình bao bọc sẽ áp dụng các kiểu bố cục như padding::details-content giả lập sẽ được tạo hiệu ứng động.