Bối cảnh và thông tin tổng quan
Thông thường, tác giả sẽ cần thực hiện các thay đổi theo bối cảnh đối với thiết kế của một thành phần. Trước đây, tác giả cần sử dụng bộ chọn để áp dụng những thay đổi đó. Điều này thường có nghĩa là mặc dù nhiều mã thông báo thiết kế của họ có thể tồn tại dưới dạng thuộc tính tuỳ chỉnh, nhưng mã thông báo thiết kế bậc cao hơn chỉ có thể được mã hoá dưới dạng mẫu bộ chọn (tức là sử dụng quy ước tên lớp hoặc thuộc tính) hoặc dưới dạng thuộc tính/bối cảnh trong khung JavaScript.
Truy vấn kiểu vùng chứa cho phép tác giả tạo kiểu cho các phần tử dựa trên giá trị thuộc tính tuỳ chỉnh được tính toán của một phần tử đối tượng cấp trên. Điều này có nghĩa là tác giả có thể viết các giá trị mã thông báo thiết kế có ý nghĩa trong biểu định kiểu của họ thay vì dựa vào mã đánh dấu hoặc JavaScript để trình bày.
Cách triển khai
Việc triển khai mã thông báo thiết kế thích ứng bằng truy vấn kiểu vùng chứa khá đơn giản:
- Đặt mã thông báo thiết kế bậc cao hơn làm thuộc tính tuỳ chỉnh trên vùng chứa. Đây không nhất thiết phải là một thuộc tính tuỳ chỉnh đã đăng ký.
- Sử dụng quy tắc
@container style()để truy vấn giá trị của thuộc tính tuỳ chỉnh đó. - Áp dụng kiểu phù hợp cho phần tử con trong vùng chứa.
Một vài điều cần nhớ:
- Vùng chứa được truy vấn bằng truy vấn kiểu không cần phải đặt
container-typehoặccontainer-name, tuy nhiên,container-namecó thể cho phép truy vấn cụ thể hơn. - Bản thân vùng chứa không thể được tạo kiểu bằng truy vấn kiểu vùng chứa.
Sau đây là ví dụ cơ bản về các bước triển khai nêu trên.
<div class="features">
<div class="card"></div>
<div class="card"></div>
</div>
<div class="bugs">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
.features {
--density: spacious;
}
.bugs {
--density: compact;
}
@container style(--density: compact) {
.card {
padding: 8px;
}
}
@container style(--density: spacious) {
.card {
padding: 24px;
}
}
Chiến lược dự phòng
Cho đến khi có Baseline hỗ trợ truy vấn kiểu vùng chứa, bạn KHÔNG NÊN sử dụng các truy vấn này cho các tính năng cốt lõi phải có trên tất cả trình duyệt, vì việc tạo một phương án dự phòng cho các truy vấn này không hề đơn giản, không làm mất đi lợi ích của các truy vấn này hoặc có những hạn chế riêng. Ví dụ: nếu lựa chọn ưu tiên của người dùng về mật độ giao diện người dùng không được coi là một tính năng cốt lõi phải có trong mọi trải nghiệm, thì bạn có thể sử dụng truy vấn kiểu vùng chứa để triển khai tính năng này mà không cần phương án dự phòng.
Sử dụng bộ chọn để thay thế
Đối với các tính năng cốt lõi, bạn nên sử dụng một phương pháp thay thế bằng bộ chọn. Ví dụ này sử dụng thuộc tính data-density để mã hoá mã thông báo thiết kế mật độ trong mã đánh dấu thay vì dưới dạng thuộc tính tuỳ chỉnh:
<div class="features" data-density="spacious">
<div class="card"></div>
<div class="card"></div>
</div>
<div class="bugs" data-density="compact">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
/* This example uses `:where()` to avoid increasing specificity */
:where([data-density="compact"]) .card {
padding: var(--card-padding-compact);
}
:where([data-density="spacious"]) .card {
padding: var(--card-padding-spacious);
}
Một hạn chế lớn của phương pháp dự phòng này là không hỗ trợ các phần tử lồng nhau có đặt thuộc tính data-density, vì độ đặc hiệu của bộ chọn là như nhau, thứ tự xuất hiện sẽ được dùng để xác định kiểu (tức là [data-density="spacious"] sẽ luôn được ưu tiên hơn [data-density="compact"]).
Sử dụng truy vấn kiểu làm cải tiến tăng dần
Mặc dù KHÔNG ĐƯỢC KHUYẾN KHÍCH, nhưng nếu muốn sử dụng truy vấn kiểu làm tính năng cải tiến tăng dần cho một tính năng cốt lõi, thì để tránh trùng lặp, bạn có thể tạo một số thuộc tính tuỳ chỉnh, sau đó thêm các truy vấn kiểu. Đảm bảo phương pháp dự phòng sử dụng :where() khi chọn các phần tử vùng chứa để tránh tăng độ cụ thể.
.card {
--card-padding-compact: 8px;
--card-padding-spacious: 24px;
}
:where([data-density="compact"]) .card {
padding: var(--card-padding-compact);
}
:where([data-density="spacious"]) .card {
padding: var(--card-padding-spacious);
}
/* Use style queries as a progressive enhancement: same specificity, so order of appearance is used */
@container style(--density: compact) {
.card {
padding: var(--card-padding-compact);
}
}
@container style(--density: spacious) {
.card {
padding: var(--card-padding-spacious);
}
}
Kiểm tra tính năng chỉ bằng CSS
Nếu cần kiểm tra tính năng truy vấn kiểu vùng chứa để hiển thị có điều kiện một số giao diện người dùng dựa vào tính năng đó, bạn có thể sử dụng truy vấn kiểu để làm việc này:
:root {
--style-queries-supported: check;
}
.density-toggle {
display: none;
}
@container style(--style-queries-supported) {
.density-toggle {
display: revert;
}
}
Kiểm tra tính năng bằng JavaScript
Đối với việc kiểm tra tính năng bằng JavaScript, việc này phức tạp hơn một chút vì giao diện CSSContainerRule đã tồn tại trước khi thêm truy vấn kiểu vùng chứa, vì vậy, giao diện này không đáng tin cậy cho mục đích này. Thay vào đó, bạn cần kiểm tra giá trị được tính toán của một thuộc tính đã biết đang được đặt bằng truy vấn kiểu.
Ví dụ này sử dụng một thuộc tính tuỳ chỉnh vì thuộc tính này sẽ không có hiệu ứng hình ảnh:
:root {
--style-queries-supported: check;
}
@container style(--style-queries-supported: check) {
body {
--style-queries-supported: yes;
}
}
Sau đó, hãy kiểm tra giá trị được tính toán trong JavaScript như sau:
if (getComputedStyle(document.body).getPropertyValue("--style-queries-supported") === "yes") {
// Use container style queries
} else {
// Use fallback strategy
}