Xuất bản: Ngày 6 tháng 11 năm 2024
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>
và <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 báo công khai hoặc tiện ích dạng accordion.
Cụ thể, những 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 một giả phần tử ::details-content
để tạo kiểu cho phần mở rộng và thu gọn.
Đặt 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, 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 linh hoạt trên phần tử <details>
.
Trong ví dụ sau, accordion độc quyền bao gồm một số phần tử <details>
được đặt cạnh nhau. Khi bạn 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
Điều này được thực hiện bằng cách sử dụng bố cục linh hoạt 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 như grid
cũng được cho phép.
Lưu ý về việc sử dụng display: inline
Giá trị display
có thể mang lại kết quả không mong muốn là inline
. Không phải vì nó không hoạt động mà là do những hạn chế của trình phân tích cú pháp HTML.
Khi đặt phần tử <details>
vào bên trong một đoạn văn, phần tử này sẽ buộc trình phân tích cú pháp HTML trước tiên phải đóng đoạn văn đang mở, như được xác định trong mục 13.2.6.4.7 của Tiêu chuẩn HTML:
Một 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ử mở có một phần tử p trong phạm vi nút, hãy đóng một phần tử p. Chèn một phần tử HTML cho mã thông báo.
Do đó, <details>
sẽ có hướng theo 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>
Trở thành như sau sau khi phân tích cú pháp:
<p>Hello </p><details>…</details> world<p></p>
Bạn có thể tự mình 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ụ cho nhà phát triển của Chrome.
Lưu ý rằng điều này chỉ áp dụng cho việc lồng <details>
bên trong một <p>
. Việc sử dụng display: inline
trên <details>
bên trong <div>
hoạt động bình thường.
Phần tử giả ::details-content
Trong trình duyệt, phần tử <details>
được triển khai bằng Shadow DOM. Nội dung này chứa một <slot>
cho phần tóm tắt (với một 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, tức 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 hiển thị hơn trên <details>
, giờ đây, bạn có thể nhắm đến vị trí nội dung bằng cách sử dụng phần tử giả ::details-content
. Bạn có thể dùng phần tử giả này để tạo kiểu cho vùng chứa bao bọc 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>
ở trạng thái mở, hãy thêm bộ chọn [open]
vào trước phần tử đó.
[open]::details-content {
border: 5px dashed hotpink;
}
Bạn chỉ nên áp dụng kiểu cho giả ::details-content
khi phần tử <details>
ở trạng thái [open]
.
Bản minh hoạ
Đang ghi
Loại display
của ::details-content
được đặt thành block
trong biểu định kiểu UA, trong khi trước đây là display: contents
. Trong một số trường hợp, thay đổi này có thể gây bất lợi cho bạn, chẳng hạn như nội dung được công bố dựa vào height: 100%
. Nếu gặp vấn đề này, bạn có thể giải quyết bằng cách đặt loại display
trở lại thành 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ẽ chuyển động từ 0px
sang 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
. Lý do là giá trị của thuộc tính 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 User-Agent. Vì thuộc tính đó là một thuộc tính có thể tạo hiệu ứng chuyển động riêng biệt, nên bạn cần từ khoá allow-discrete
để làm cho thuộc tính đó hoạt động.
Ngoài bản minh hoạ accordion độc quyền được chia sẻ trước đó, kết quả sẽ như sau:
Bản minh hoạ
Đang ghi
Bạn cũng có thể tạo ảnh động cho height
. Để tạo hiệu ứng chuyển động đến height: auto
, bạn cần sử dụng interpolate-size
hoặc calc-size()
. Ngoài ra, để ngăn nội dung tràn ra khỏi giả ::details-content
, 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ã này hoạt động trong bản minh hoạ sau đây, lấy cảm hứng từ thành phần accordion của Material UI. Nội dung của mỗi phần tử <details>
đều có hiệu ứng động đẹp mắt.
Bản minh hoạ
Đang ghi
Trong các trình duyệt không hỗ trợ ::details-content
, thành phần này vẫn hoạt động bình thường. Điều duy nhất mà khách truy cập không thấy được là ảnh động.
Phát hiện đối tượng
Để phát hiện tính năng hỗ trợ cho ::details-content
giả 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 như một dấu hiệu để xác định xem 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 hiển thị 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 và tự động mở rộng khi trình duyệt cố gắng cuộn đến nội dung bị ẩn của phần tử này để phản hồi tính năng tìm kiếm trong trang, ScrollToTextFragment và tính năng điều hướng đến đoạn nội dung của phần tử. Việc này không thay đổi.
Tuy nhiên, trước khi sử dụng các thành phần accordion độc quyền, hãy cân nhắc xem liệu thành phần đó có hữu ích hay gây hại cho người dùng. Mặc dù việc sử dụng một bảng xếp hình độc quyền sẽ giảm lượng không gian trực quan mà nội dung chiếm dụng, nhưng người dùng có thể phải mở nhiều mục để sử dụng tất cả thông tin. Điều này có thể khiến những người dùng muốn xem nhiều mục cùng một lúc cảm thấy khó chịu.
Còn việc tạo kiểu cho điểm đánh dấu thì sao?
Hiện tại, việc tạo kiểu cho 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à (hiện tại) Chromium 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, bạn có thể xem thêm một số bản minh hoạ khác. Tất cả đều sử dụng ::details-content
.
UIKit Accordion
Bản minh hoạ
Đang ghi
Bản minh hoạ này được xây dựng sau UIKit Accordion. Mã này gần như giống với mã của thành phần accordion trong Material UI mà chúng ta đã chia sẻ trước đây.
Tiện ích công bố được mở một phần
Bản minh hoạ
Đang ghi
Bản minh hoạ này có một tiện ích công bố được mở một phần và nội dung của tiện ích này đã xuất hiện trên màn hình. Để đạt được mục đích này, content-visibility
luôn được đặt thành visible
. height
được tạo hiệu ứng động bằng cách sử dụ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 bao bọc trong một div trình bao bọc. Div trình bao bọc sẽ nhận được các kiểu bố cục như padding
được áp dụng và giả ::details-content
được tạo hiệu ứng động.