API CSS Anchor Positioning (Định vị neo CSS) cho phép bạn định vị các phần tử tương ứng với các phần tử khác, được gọi là neo. API này đơn giản hoá các yêu cầu phức tạp về bố cục cho nhiều tính năng giao diện như trình đơn và trình đơn con, chú giải công cụ, lựa chọn, nhãn, thẻ, hộp thoại cài đặt và nhiều tính năng khác. Với tính năng định vị neo được tích hợp sẵn trong trình duyệt, bạn có thể tạo giao diện người dùng phân lớp mà không cần dựa vào thư viện của bên thứ ba, mở ra một thế giới đầy khả năng sáng tạo.
Khái niệm chính: Neo và các phần tử định vị
Cốt lõi của API này là mối quan hệ giữa đinh neo và các phần tử được định vị. Neo là một phần tử được chỉ định làm điểm tham chiếu bằng thuộc tính anchor-name
. Phần tử được định vị là phần tử được đặt tương ứng với một neo bằng cách sử dụng thuộc tính position-anchor
hoặc sử dụng anchor-name
một cách rõ ràng trong logic định vị của phần tử đó.
Thiết lập neo
Việc tạo một liên kết cố định rất đơn giản. Áp dụng thuộc tính anchor-name cho phần tử đã chọn và chỉ định cho phần tử đó một giá trị nhận dạng duy nhất. Giá trị nhận dạng duy nhất này phải được thêm hai dấu gạch ngang vào trước, giống như biến CSS.
.anchor-button {
anchor-name: --anchor-el;
}
Sau khi được chỉ định tên neo, .anchor-button
sẽ đóng vai trò là neo, sẵn sàng hướng dẫn vị trí của các phần tử khác. Bạn có thể kết nối phần tử liên kết này với các phần tử khác theo một trong hai cách sau:
Neo ngầm
Cách đầu tiên để kết nối một liên kết với một phần tử khác là bằng một liên kết ngầm ẩn như trong mã ví dụ sau. Thuộc tính position-anchor
được thêm vào phần tử bạn muốn kết nối với quảng cáo cố định và có giá trị là tên của neo (trong trường hợp này là --anchor-el
).
.positioned-notice {
position-anchor: --anchor-el;
}
Với mối quan hệ liên kết ngầm ẩn, bạn có thể định vị các phần tử bằng hàm anchor()
mà không cần chỉ định rõ ràng tên liên kết ở đối số đầu tiên.
.positioned-notice {
position-anchor: --anchor-el;
top: anchor(bottom);
}
Liên kết rõ ràng
Ngoài ra, bạn có thể sử dụng tên neo trực tiếp trong hàm neo (ví dụ: top: anchor(--anchor-el bottom
). Đây được gọi là neo rõ ràng và có thể hữu ích nếu bạn muốn neo đến nhiều phần tử (hãy đọc tiếp để xem ví dụ).
.positioned-notice {
top: anchor(--anchor-el bottom);
}
Vị trí các phần tử tương ứng với quảng cáo cố định
Vị trí neo được xây dựng dựa trên vị trí tuyệt đối CSS Để sử dụng các giá trị vị trí, bạn cần thêm position: absolute
vào phần tử được định vị. Sau đó, dùng hàm anchor()
để áp dụng các giá trị định vị. Ví dụ: để định vị một phần tử neo ở trên cùng bên trái của phần tử neo, hãy sử dụng vị trí sau:
.positioned-notice {
position-anchor: --anchor-el;
/* absolutely position the positioned element */
position: absolute;
/* position the right of the positioned element at the right edge of the anchor */
right: anchor(right);
/* position the bottom of the positioned element at the top edge of the anchor */
bottom: anchor(top);
}
Bây giờ, bạn đã có một phần tử được liên kết với một phần tử khác, như sau:
Để sử dụng vị trí logic cho các giá trị này, các giá trị tương đương như sau:
top
=inset-block-start
left
=inset-inline-start
bottom
=inset-block-end
right
=inset-inline-end
Căn giữa một phần tử được định vị bằng anchor-center
Để dễ dàng căn giữa phần tử được định vị cố định tương ứng với phần neo của phần tử đó, có một giá trị mới tên là anchor-center
có thể dùng với các thuộc tính justify-self
, align-self
, justify-items
và align-items
.
Ví dụ này sửa đổi ví dụ trước bằng cách sử dụng justify-self: anchor-center
để căn giữa phần tử được định vị trên đầu phần tử neo.
.positioned-notice {
position: absolute;
/* Anchor reference */
position-anchor: --anchor-el;
/* Position bottom of positioned elem at top of anchor */
bottom: anchor(top);
/* Center justification to the anchor */
justify-self: anchor-center;
}
Nhiều neo
Các thành phần có thể được chia sẻ Internet với nhiều điểm neo. Điều này có nghĩa là bạn có thể cần đặt các giá trị vị trí được định vị tương ứng với nhiều neo. Bạn có thể thực hiện việc này bằng cách sử dụng hàm anchor()
và nêu rõ bạn đang tham chiếu đến neo nào trong đối số đầu tiên. Trong ví dụ sau, phần trên cùng bên trái của một phần tử được định vị được neo vào phần dưới cùng bên phải của một neo và phần dưới cùng bên phải của phần tử được định vị được neo vào phần trên cùng bên trái của neo thứ hai:
.anchored {
position: absolute;
top: anchor(--one bottom);
left: anchor(--one right);
right: anchor(--two left);
bottom: anchor(--two top);
}
Vị trí bằng position-area
API liên kết bao gồm một cơ chế bố cục mới sử dụng thuộc tính position-area
.
Thuộc tính này cho phép bạn đặt các phần tử được định vị neo tương ứng với các neo tương ứng và hoạt động trên lưới 9 ô với phần tử neo ở giữa.
Để sử dụng position-area
thay vì vị trí tuyệt đối, hãy sử dụng thuộc tính position-area
với các giá trị thực hoặc logic. Ví dụ:
- Trên cùng chính giữa:
position-area: top
hoặcposition-area: block-start
- Trái giữa:
position-area: left
hoặcposition-area: inline-start
- Dưới cùng chính giữa:
position-area: bottom
hoặcposition-area: block-end
- Chính giữa bên phải:
position-area: right
hoặcposition-area: inline-end
Để khám phá thêm về những vị trí này, hãy khám phá công cụ sau:
Kích thước các phần tử có anchor-size()
Hàm anchor-size()
, cũng là một phần của API định vị neo, có thể được dùng để định cỡ hoặc định vị một phần tử được định vị neo dựa trên kích thước của neo (chiều rộng, chiều cao hoặc kích thước nội tuyến và khối).
CSS sau đây cho thấy ví dụ về cách sử dụng thuộc tính này cho chiều cao,sử dụng anchor-size(height)
trong hàm calc()
để đặt chiều cao tối đa của chú giải công cụ bằng hai lần chiều cao của neo.
.positioned-notice {
position-anchor: --question-mark;
/* set max height of the tooltip to 2x height of the anchor */
max-height: calc(anchor-size(height) * 2);
}
Sử dụng neo với các thành phần lớp trên cùng như cửa sổ bật lên và hộp thoại
Vị trí neo hoạt động rất hiệu quả với các phần tử lớp trên cùng như popover
. và <dialog>
. Mặc dù các phần tử này được đặt trong một lớp riêng biệt với phần còn lại của cây con DOM, nhưng vị trí neo cho phép bạn liên kết lại các phần tử đó và cuộn cùng với các phần tử không nằm trong lớp trên cùng. Đây là một lợi thế lớn cho giao diện phân lớp.
Trong ví dụ sau, một nhóm cửa sổ bật lên của chú giải công cụ được kích hoạt mở bằng một nút. Nút là phần neo và chú giải công cụ là phần tử được định vị. Bạn có thể tạo kiểu cho phần tử đã định vị giống như mọi phần tử cố định khác. Trong ví dụ cụ thể này, anchor-name
và position-anchor
là các kiểu cùng dòng trên nút và chú thích. Vì mỗi quảng cáo cố định cần một tên duy nhất, nên khi tạo nội dung động, cùng dòng là cách dễ nhất để thực hiện việc này.
Điều chỉnh vị trí neo bằng @position-try
Khi đã có được vị trí neo ban đầu, bạn có thể điều chỉnh vị trí đó nếu neo chạm đến các cạnh của khối chứa nó. Để tạo các vị trí neo thay thế, bạn có thể sử dụng lệnh @position-try
cùng với thuộc tính position-try-fallbacks
.
Trong ví dụ sau, trình đơn phụ xuất hiện ở bên phải trình đơn. Trình đơn và trình đơn con là một cách sử dụng hiệu quả API định vị neo cùng với thuộc tính cửa sổ bật lên, vì các trình đơn này thường được neo vào nút kích hoạt.
Đối với trình đơn phụ này, nếu không có đủ không gian theo chiều ngang, bạn có thể di chuyển trình đơn phụ đó xuống bên dưới trình đơn. Để làm việc này, trước tiên, hãy thiết lập vị trí ban đầu:
#submenu {
position: absolute;
position-anchor: --submenu;
/* initial position */
margin-left: var(--padding);
position-area: right span-bottom;
}
Sau đó, hãy thiết lập các vị trí neo dự phòng bằng @position-try
:
/* alternate position */
@position-try --bottom {
margin: var(--padding) 0 0 var(--padding);
posotion-area: bottom;
}
Cuối cùng, hãy kết nối hai phần này với position-try-fallbacks
. Tất cả đều có giao diện như sau:
#submenu {
position: absolute;
position-anchor: --submenu;
/* initial position */
margin-left: var(--padding);
position-area: right span-bottom;
*/ connect with position-try-fallbacks */
position-try-fallbacks: --bottom;
}
/* alternate position */
@position-try --bottom {
margin: var(--padding) 0 0 var(--padding);
position-area: bottom;
}
Tự động lật từ khoá theo vị trí liên kết
Nếu có một thao tác điều chỉnh cơ bản, chẳng hạn như lật từ trên xuống dưới hoặc từ trái sang phải (hoặc cả hai), thậm chí bạn có thể bỏ qua bước tạo phần khai báo @position-try
tuỳ chỉnh và sử dụng các từ khoá lật được tích hợp sẵn được trình duyệt hỗ trợ như flip-block
và flip-inline
. Các giá trị này hoạt động như phần thay thế cho các nội dung khai báo @position-try
tuỳ chỉnh và có thể được sử dụng kết hợp với nhau:
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
Tính năng lật từ khoá có thể đơn giản hoá đáng kể mã neo của bạn. Chỉ với một vài dòng, bạn có thể tạo một neo có đầy đủ chức năng với các vị trí khác nhau:
#my-tooltip {
position-anchor: --question-mark;
position-area: top;
position-try-fallbacks: flip-block;
}
position-visibility
cho neo trong thanh cuộn phụ
Trong một số trường hợp, bạn có thể muốn neo một phần tử trong thanh cuộn phụ của trang. Trong những trường hợp này, bạn có thể kiểm soát chế độ hiển thị của neo bằng position-visibility
. Khi nào phần neo vẫn hiển thị? Khi nào thông báo này biến mất? Bạn có thể kiểm soát các lựa chọn này bằng tính năng này. Bạn sử dụng position-visibility: anchors-visible
khi muốn phần tử được định vị vẫn hiển thị cho đến khi phần neo không còn trong khung nhìn:
#tooltip {
position: fixed;
position-anchor: --anchor-top-anchor;
position-visibility: anchors-visible;
bottom: anchor(top);
}
Ngoài ra, bạn có thể sử dụng position-visibility: no-overflow
để ngăn phần neo tràn ra khỏi vùng chứa.
#tooltip {
position: absolute;
position-anchor: --anchor-top-anchor;
position-visibility: no-overflow;
bottom: anchor(top);
}
Phát hiện tính năng và polyfill
Vì tính năng hỗ trợ trình duyệt bị hạn chế tại thời điểm này, nên bạn nên sử dụng API này với một số biện pháp phòng ngừa. Trước tiên, bạn có thể trực tiếp kiểm tra dịch vụ hỗ trợ trong CSS bằng cách sử dụng truy vấn tính năng @supports
. Cách thực hiện việc này là gói các kiểu neo của bạn theo cách sau:
@supports (anchor-name: --myanchor) {
/* Anchor styles here */
}
Ngoài ra, bạn có thể polyfill tính năng định vị neo bằng polyfill định vị neo CSS của Oddbird. Tính năng này hoạt động trên Firefox 54, Chrome 51, Edge 79 và Safari 10. Trình bổ trợ này hỗ trợ hầu hết các tính năng vị trí neo cơ bản, mặc dù cách triển khai hiện tại chưa hoàn chỉnh và chứa một số cú pháp đã lỗi thời. Bạn có thể sử dụng đường liên kết unpkg hoặc nhập trực tiếp đường liên kết đó trong trình quản lý gói.
Lưu ý về khả năng hỗ trợ tiếp cận
Mặc dù API định vị neo cho phép một phần tử được định vị tương ứng với các phần tử khác, nhưng bản chất API này không tạo ra bất kỳ mối quan hệ ngữ nghĩa có ý nghĩa nào giữa các phần tử đó. Nếu thực sự có mối quan hệ ngữ nghĩa giữa phần tử liên kết và phần tử được định vị (ví dụ: phần tử được định vị là một nhận xét ở thanh bên về văn bản liên kết), thì một cách để thực hiện việc đó là sử dụng aria-details
để trỏ từ phần tử liên kết đến(các) phần tử được định vị. Phần mềm trình đọc màn hình vẫn đang tìm hiểu cách xử lý lỗi aria-chi tiết, nhưng khả năng hỗ trợ sẽ ngày càng cải thiện.
<div class="anchor" aria-details="sidebar-comment">Main content</div>
<div class="positioned" id="sidebar-comment">Sidebar content</div>
.anchor {
anchor-name: --anchor;
}
.positioned {
position: fixed;
position-anchor: --anchor;
}
Nếu bạn đang dùng vị trí neo bằng thuộc tính popover
hoặc phần tử <dialog>
, trình duyệt sẽ xử lý các chỉnh sửa điều hướng tiêu điểm để có khả năng hỗ trợ tiếp cận phù hợp, do đó bạn không cần cửa sổ bật lên hoặc hộp thoại theo thứ tự DOM. Đọc thêm về ghi chú về khả năng hỗ trợ tiếp cận trong thông số kỹ thuật.