Khi tạo chú giải công cụ hoặc cửa sổ bật lên bằng tính năng Định vị neo CSS, trình duyệt có thể tự động "lật" phần tử sang vị trí dự phòng nếu phần tử đó tràn khung nhìn. Khi điều này xảy ra, bạn có thể điều chỉnh kiểu của nội dung được định vị, chẳng hạn như định vị lại mũi tên trỏ từ nội dung được định vị đến neo.
Truy vấn vùng chứa cố định giải quyết vấn đề này bằng cách cho phép bạn truy vấn trạng thái định vị đang hoạt động của một phần tử và áp dụng kiểu cho phù hợp. Để biết thông tin chung về cách định vị trình đơn thả xuống và trình đơn thả nổi được neo bằng tính năng lật khi va chạm với khung nhìn (không cần định kiểu lại mũi tên chỉ hướng), hãy xem bài viết Trình đơn thả xuống nhận biết khung nhìn.
Vấn đề
Hãy tưởng tượng một chú thích xuất hiện phía trên điểm neo theo mặc định. Biểu tượng này có mũi tên "xuống" ở dưới cùng. Nếu người dùng cuộn và chú thích lật để xuất hiện bên dưới neo, thì mũi tên hiện đang chỉ sai hướng và nằm sai phía của chú thích.
Giải pháp: Truy vấn vùng chứa cố định
Bằng cách đặt container-type: anchored trên phần tử được định vị, bạn sẽ biến phần tử đó thành một vùng chứa truy vấn biết về trạng thái được định vị neo của chính nó. Sau đó, bạn có thể sử dụng truy vấn @container anchored() để cập nhật các phần tử con hoặc phần tử giả của vùng chứa đó.
1. Tạo chú thích và điều kiện kích hoạt
Sử dụng Popover API để tạo chú thích. Việc gọi cửa sổ bật lên thông qua popovertarget sẽ tự động thiết lập kết nối neo ngầm ẩn với nút kích hoạt, vì vậy, bạn không cần phải có anchor-name hoặc position-anchor rõ ràng.
<button popovertarget="tooltip" id="anchor" aria-describedby="tooltip">anchor</button>
<div id="tooltip" popover role="tooltip"></div>
Đặt lại kiểu lề và lề trong của cửa sổ bật lên để sử dụng với tính năng định vị neo, nhưng chỉ khi tính năng định vị neo được hỗ trợ.
@supports (anchor-name: --my-anchor) {
[popover] {
inset: auto;
margin: unset;
}
}
2. Thiết lập vùng chứa
Áp dụng container-type: anchored cho phần tử đang được định vị. Phần tử này cũng phải xác định position-try-fallbacks để bật hành vi lật.
#tooltip {
position: fixed;
position-area: block-start;
position-try-fallbacks: flip-block;
/* Enable anchored container queries */
container-type: anchored;
}
3. Tạo kiểu dựa trên dữ liệu dự phòng
Sử dụng @container anchored(fallback: <value>) để áp dụng kiểu khi một phương án dự phòng cụ thể đang hoạt động.
Giống như tất cả truy vấn vùng chứa, @container chỉ có thể tạo kiểu cho phần tử con của vùng chứa. Một chiến lược phổ biến để tạo mũi tên là sử dụng các phần tử giả ::before và ::after. Các phần tử này được coi là phần tử con và có thể được tạo kiểu trực tiếp. Tuy nhiên, để tạo kiểu cho chính chú thích (như trong bước 4), chúng ta sẽ thêm một phần tử con vào chú thích và tạo mũi tên trong phần tử giả ::before của chú thích.
<div id="tooltip" popover role="tooltip">
<div class="tooltip-content">Tooltip</div>
</div>
.tooltip-content::before {
/* Default "down" arrow for the 'top' position */
content: "▼";
position: absolute;
inset-block-end: 0;
inset-inline-start: 1rem;
}
/* Update to an "up" arrow when the 'flip-block' fallback (bottom) is active */
@container anchored(fallback: flip-block) {
.tooltip-content::before {
content: "▲";
inset-block-start: 0;
inset-block-end: auto;
}
}
4. Định kiểu cho chính vùng chứa
Nếu cần thay đổi các thuộc tính trên chính vùng chứa (như margin hoặc background-color) khi vùng chứa lật, bạn nên sử dụng phần tử trình bao bọc bên trong.
- Áp dụng
container-type: anchoredcho phần tử được định vị bên ngoài. - Nhắm đến phần tử bên trong khối
@container.
@container anchored(fallback: flip-block) {
.tooltip-content {
border-radius: 0 0 .5rem .5rem;
margin-block-start: 0.25rem;
}
}
Các phương pháp hay nhất
- Ưu tiên dự phòng logic: Sử dụng các từ khoá như
flip-blockvàflip-inlinetrongposition-try-fallbackscho các truy vấn đơn giản hơn, tự động xử lý RTL và các chế độ viết khác nhau. - Sử dụng phần tử giả cho mũi tên: Mũi tên chú thích chỉ mang tính trang trí và là lựa chọn hoàn hảo cho
::beforehoặc::after. Bạn có thể tạo kiểu cho các phần tử này thông qua truy vấn vùng chứa được neo mà không cần thêm DOM.
Chiến lược dự phòng
Việc định vị mũi tên dựa trên phương án dự phòng được áp dụng là một điểm cải tiến tăng dần và không có cách nào khác để phản ứng với vị trí dự phòng. Để ẩn mũi tên trong các trình duyệt không hỗ trợ truy vấn vùng chứa vị trí neo, hãy kiểm tra khả năng hỗ trợ CSS bằng @supports (container-type: anchored).
@supports (container-type: anchored) {
.tooltip-content::before {
content: "▼";
}
}
Phương án dự phòng và hỗ trợ trình duyệt cho Popover
Popover API chủ yếu là cải tiến tăng dần, nhưng các hành vi xác định của API này (quảng bá lớp trên cùng, đóng nhẹ và gọi popovertarget) không có hành vi tương đương chỉ dùng CSS. Các trình duyệt cũ cần có polyfill hoặc phương án dự phòng thủ công nếu bạn không muốn cung cấp polyfill.
Polyfill: Để hỗ trợ thuộc tính popover trong các trình duyệt cũ, hãy tải @oddbird/popover-polyfill theo điều kiện. BẮT BUỘC: Phát hiện tính năng bằng cách kiểm tra thuộc tính popover trên HTMLElement.prototype và chỉ tải polyfill khi thiếu tính năng hỗ trợ gốc — KHÔNG tải polyfill vô điều kiện.
Với trình đóng gói hoặc bản đồ nhập:
// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
import("@oddbird/popover-polyfill");
}
Nếu không có trình đóng gói, hãy nhập từ CDN bên trong <script type="module">:
<script type="module">
if (!("popover" in HTMLElement.prototype)) {
import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
}
</script>
Lưu ý về kiểu: Polyfill không thể xác định lớp giả :popover-open thực, vì vậy, lớp này sẽ áp dụng lớp .\:popover-open. BẮT BUỘC: Kết hợp cả hai bằng :is() hoặc :where(), nếu không, các trình duyệt thiếu :popover-open sẽ loại bỏ toàn bộ quy tắc:
[popover]:is(:popover-open, .\:popover-open) {
display: block;
}
Ngoài ra, đối với phương án dự phòng cũ không có polyfill, hãy sử dụng position: fixed và tính toán toạ độ theo cách thủ công thông qua getBoundingClientRect() hoặc dựa vào vị trí mặc định bằng inset: auto nếu điều đó phù hợp với trường hợp sử dụng.
Các trình duyệt không hỗ trợ Popover API cũng không hỗ trợ tính năng định vị neo, vì vậy, chú giải công cụ sẽ xuất hiện ở giữa màn hình.