Khi đặt chú thích hoặc trình đơn thả xuống, bạn thường muốn đặt chú thích hoặc trình đơn đó tương ứng với một phần tử khác trên trang. Mặc dù đã có những cách sử dụng tính năng định vị tuyệt đối để đạt được hiệu ứng này, nhưng các yêu cầu phức tạp hơn trước đây thường phải dùng đến việc định vị các mục bằng JavaScript.
Tính năng định vị phần tử neo bằng CSS cung cấp một cách để khai báo vị trí của một phần tử so với một phần tử khác.
Các phần tử chia sẻ Internet
Để biến một phần tử thành một điểm neo, bạn chỉ định cho phần tử đó giá trị anchor-name
là bất kỳ chuỗi nào bắt đầu bằng hai dấu gạch ngang. Đây là giá trị nhận dạng mà phần tử được định vị sẽ dùng để tìm điểm neo của phần tử đó và bạn nên đặt cho giá trị nhận dạng này một tên mô tả. Bạn thậm chí có thể đặt nhiều tên điểm neo cho một phần tử nếu phần tử đó sẽ được dùng làm điểm neo theo nhiều cách.
Bạn sẽ cần đặt một số thuộc tính cho phần tử được định vị để có thể liên kết phần tử đó. Trước tiên, bạn cần kéo phần tử ra khỏi luồng của tài liệu để phần tử đó nổi lên bằng cách đặt position: absolute
hoặc position: fixed
.
Tiếp theo, bạn sẽ cần đặt neo mà bạn muốn liên kết bằng cách đặt position-anchor
thành tên neo mà bạn đã đặt trên neo.
Cuối cùng, bạn cần đặt cách định vị điểm neo. Bạn sẽ tìm hiểu thêm về position-area
trong phần sau của mô-đun này.
#anchor {
anchor-name: --my-anchor;
}
#positionedElement {
position: absolute;
position-anchor: --my-anchor;
position-area: end;
}
Chia sẻ Internet ngầm
Popover (cửa sổ bật lên) còn dễ dàng liên kết hơn. Khi bạn mở một cửa sổ bật lên bằng cách sử dụng nút có popovertarget
hoặc bằng cách đặt source
bằng showPopover({source})
, cửa sổ bật lên sẽ có sẵn "neo ngầm". Vì theo mặc định, một cửa sổ bật lên đã nổi với position: fixed
, nên để định vị cửa sổ bật lên, bạn chỉ cần đặt vị trí.
#anchor{}
#positionedElement {
position-area: end;
margin: unset;
}
Phạm vi của các điểm neo tiềm năng
Bạn có thể triển khai tính năng định vị phần tử neo trong một thành phần để có thể sử dụng một mẫu như trình đơn thả xuống ở nhiều vị trí. Nếu bạn đang sử dụng cùng một anchor-name
nhiều lần, làm cách nào để đảm bảo rằng mỗi phần tử được định vị đều tìm thấy điểm neo chính xác?
Các giải pháp JavaScript liên quan đến việc thêm mã nhận dạng riêng biệt vào mỗi điểm neo, sau đó tham chiếu đến mã nhận dạng đó từ phần tử được định vị. Việc này trở nên rườm rà và CSS có một giải pháp đơn giản hơn với anchor-scope
.
Thuộc tính anchor-scope
đặt tên neo nào sẽ chỉ được so khớp giữa một phần tử và các phần tử con của phần tử đó. Nó chấp nhận danh sách gồm một hoặc nhiều tên điểm neo hoặc từ khoá all
để giới hạn phạm vi của tất cả tên điểm neo đã xác định.
Tốt nhất là bạn nên thêm một anchor-scope
vào tổ tiên của cả phần tử được định vị và phần tử neo không chứa các phần tử neo khác có cùng tên. Thông thường, điều này nằm trên gốc của thành phần có thể dùng lại.
Ví dụ sau đây cho thấy sự khác biệt mà anchor-scope
tạo ra khi được áp dụng cho các phần tử lặp lại có cùng anchor-name
. Trong ví dụ này, tất cả các phần tử <img>
và biểu ngữ hình ảnh đều tham chiếu đến tên điểm neo --image
. Khi anchor-scope
được áp dụng cho các phần tử <li>
, position-anchor: --image
sẽ chỉ khớp với phần tử <img>
trong cùng phần tử <li>
với biểu ngữ, nếu không, position-anchor: --image
sẽ khớp với <img>
được kết xuất gần đây nhất.
Khẳng định vị thế
Giờ đây, khi đã liên kết phần tử với điểm neo, bạn có thể định vị phần tử đó. Tính năng định vị điểm neo cung cấp 2 phương thức định vị – position-area
và hàm anchor()
.
position-area
Thuộc tính position-area
cho phép bạn đặt một phần tử xung quanh điểm neo bằng cách chỉ định một hoặc hai từ khoá. Điều này bao gồm nhiều trường hợp sử dụng phổ biến và thường là một điểm khởi đầu tốt.
Cách hoạt động của position-area
position-area
hoạt động bằng cách tạo một khối chứa mới cho phần tử được định vị trong một vùng do các cạnh của phần tử neo và khối chứa ban đầu của phần tử được định vị tạo ra.
Mặc dù có nhiều từ khoá cho position-area
, nhưng bạn có thể chia các từ khoá này thành một số danh mục để dễ hiểu hơn. Anchor-tool.com là một công cụ hữu ích để khám phá cú pháp.
Từ khoá thực
Bạn có thể sử dụng các từ khoá thực tế: top
, left
, bottom
, right
và center
. Ví dụ: position-area: top right
sẽ đặt phần tử được định vị ở phía trên và bên phải của phần tử cố định. Các từ khoá này cũng có các từ khoá tương đương về trục vật lý: y-start
, x-start
, y-end
và x-end
.
Từ khoá logic
Bạn cũng có thể sử dụng các từ khoá logic, block-start
, block-end
, inline-start
và inline-end
. Ví dụ: position-area: block-end inline-start
sẽ đặt phần tử được định vị bên dưới và bên trái điểm neo trong các ngôn ngữ như tiếng Anh, hoặc sau điểm neo trên trục khối và trước điểm neo trên trục nội tuyến trong chế độ viết của tài liệu. Bạn cũng có thể dùng center
với một từ khoá logic.
Bạn cũng có thể bỏ qua trục nếu đang chỉ định từ khoá logic, với trục khối ở vị trí đầu tiên và trục nội tuyến ở vị trí thứ hai. position-area: start end
giống như position-area: block-start inline-end
hoặc thậm chí là position-area: inline-end block-start
.
Trải rộng trên nhiều vùng lưới
Cho đến nay, có thể bạn đã nhận thấy rằng những lựa chọn này chỉ cho phép bạn đặt phần tử được định vị trong một không gian lưới duy nhất. Việc thêm tiền tố span
vào các thuộc tính thực hoặc logic sẽ thêm khoảng trống lưới trung tâm liền kề. position-area: span-top right
sẽ được đặt ở bên phải của phần tử liên kết, và từ dưới cùng của phần tử liên kết đến đầu khối chứa ban đầu của phần tử được đặt.
position-area: block-end span-inline-end
là vị trí thường gặp của trình đơn thả xuống.
Từ khoá span-all
trải dài trên 3 hàng hoặc cột.
Một từ khoá
Nếu bạn chỉ đặt một từ khoá, thì trục còn lại sẽ được đặt tự động. Tính năng này hoạt động như bạn mong đợi, nhưng bạn nên tìm hiểu cách tính năng này hoạt động.
Nếu từ khoá được cung cấp rõ ràng về trục của nó, thì trục còn lại sẽ được tính là span-all
. Điều này có nghĩa là position-area: bottom
tương đương với position-area: bottom span-all
, và phần tử được định vị sẽ nằm bên dưới phần tử neo, đồng thời có toàn bộ chiều rộng của khối chứa.
Mặt khác, nếu từ khoá không chỉ rõ một trục, thì từ khoá đó sẽ được lặp lại. position-area: start
tương đương với start start
và được đặt ở trên cùng bên trái của điểm neo trong các ngôn ngữ đọc từ trái sang phải.
Hàm anchor()
Đối với các trường hợp sử dụng nâng cao hơn, position-area
có thể không đáp ứng được yêu cầu của bạn. Hàm anchor()
cho phép bạn đặt các thuộc tính lồng ghép riêng lẻ dựa trên vị trí của một phần tử khác. Giá trị này được phân giải thành độ dài CSS, tức là bạn có thể sử dụng giá trị này trong các phép tính và với các hàm CSS khác. Ngoài ra, bạn cũng có thể liên kết các cạnh khác nhau với các điểm neo khác nhau.
Hàm anchor()
lấy tên và phía của điểm neo. Nếu phần tử của bạn có một neo mặc định (được đặt bằng position-anchor
hoặc ngầm, chẳng hạn như với một cửa sổ bật lên), thì bạn có thể bỏ qua tên neo.
.positionedElement {
block-start: anchor(--my-anchor start);
/* OR */
position-anchor: --my-anchor;
block-start: anchor(start);
}
Giá trị dự phòng
Nếu không tìm thấy một điểm neo cho hàm anchor()
, thì toàn bộ khai báo sẽ không hợp lệ. Điều này có thể xảy ra nếu phần tử cố định được hiển thị sau phần tử được định vị hoặc nếu không có phần tử nào có anchor-name
khớp. Để xử lý vấn đề này, bạn có thể đặt độ dài hoặc tỷ lệ phần trăm dự phòng.
.positionedElement {
block-start: anchor(--my-anchor, 100px)
}
Trong ví dụ trước, giá trị bên trái của phần tử được định vị được cố định vào --focused-anchor
, nhưng anchor-name
chỉ tồn tại khi nút đầu tiên được di chuột hoặc lấy tiêu điểm. Vì hàm anchor()
phân giải thành một độ dài, nên bạn có thể dùng một neo khác làm phương án dự phòng. Nếu chúng ta không cung cấp một giải pháp dự phòng, thì phần tử được định vị sẽ không được định vị.
Từ khoá phụ
Giá trị phía cố định chọn cạnh nào của điểm cố định để đặt vào. Tương tự như position-area
, giá trị phía neo hỗ trợ một số loại cú pháp.
Loại | Giá trị | Mô tả |
---|---|---|
Tự nhiên | top , left , bottom , right |
Từ khoá vật lý tương ứng với một phía cụ thể của phần tử neo, nhưng chỉ có thể dùng trên cùng một trục với phần lồng ghép của phần tử được định vị mà bạn đang đặt. Ví dụ: |
Bên cạnh | inside , outside |
Từ khoá Ví dụ: |
Lôgic | start , end , self-start , self-end |
Từ khoá logic đề cập đến các cạnh của phần tử neo dựa trên chế độ viết của phần tử được định vị bằng |
Phần trăm | 0% – 100% |
Giá trị phần trăm đặt phần tử được định vị dọc theo trục từ đầu đến cuối của phần tử neo trên trục đã chỉ định. |
Ví dụ này cho thấy cách giá trị phần trăm luôn đi từ đầu đến cuối trên trục đã chỉ định:
Sử dụng anchor()
Vì anchor()
là một độ dài nên rất linh hoạt. Bạn có thể thao tác với giá trị bằng các hàm CSS như max()
và calc()
.
Một hạn chế là bạn chỉ có thể sử dụng các hàm anchor()
trên các thuộc tính lồng ghép.
Ví dụ trước đó sẽ thêm một nền phía sau bảng chi tiết đang mở, nền này sẽ chuyển động mượt mà khi một bảng điều khiển khác mở ra và kéo dài để bao gồm một bảng chi tiết được di chuột vào. Để thực hiện việc này, nó sử dụng min()
để chọn chiều dài nhỏ hơn giữa hai điểm neo.
#indicator{
/* Use the smaller of the 2 values: */
inset-block-start: min(
/* 1. The start side of the default anchor, which is the open `<details>` element */
anchor(start),
/* 2. The start side of the hovered `<details>` element. */
anchor(--hovered start,
/* If no `<details>` element is hovered, this falls back to infinity px, so that the other value is smaller, and therefore used. */
var(calc(1px * infinity)))
);
}
Ví dụ này cũng sử dụng calc()
để thêm khoảng trống nội tuyến xung quanh bảng điều khiển mở.
Sử dụng kích thước của phần tử liên kết
Bạn cũng có thể dùng hàm anchor-size()
để sử dụng các phương diện của phần tử cố định cho kích thước, vị trí hoặc lề của phần tử được định vị.
anchor-size()
lấy tên của một điểm neo hoặc sử dụng điểm neo mặc định. Theo mặc định, thành phần này sẽ sử dụng kích thước của neo trên trục mà thành phần đang được dùng, vì vậy, width: anchor-size()
sẽ trả về chiều rộng của neo. Bạn cũng có thể sử dụng trục còn lại bằng cách chỉ định độ dài bạn muốn, với các từ khoá vật lý width
và height
hoặc các từ khoá logic block
, inline
, self-block
và self-inline
.
Xử lý nội dung tràn
Bạn đã tạo một thành phần trình đơn thả xuống và sử dụng tính năng định vị phần tử neo để đặt trình đơn thả xuống ở vị trí bạn muốn. Nhưng sau đó, bạn di chuyển trình đơn sang phía bên kia màn hình hoặc sử dụng trình đơn này cho trình đơn người dùng và tên người dùng quá dài. Đột nhiên, trình đơn thả xuống của bạn biến mất khỏi màn hình. Bây giờ bạn phải làm gì?
Tính năng định vị phần tử neo CSS có một hệ thống tích hợp sẵn cho phép bạn nhanh chóng tạo một bộ dự phòng mạnh mẽ khi phần tử được định vị nằm ngoài khối chứa của phần tử đó.
Các lựa chọn dự phòng
Quy tắc position-try-fallbacks
sẽ lấy một danh sách các lựa chọn dự phòng. Khi vị trí mặc định tràn, mỗi lựa chọn sẽ được thử theo thứ tự cho đến khi có một vị trí không tràn.
Bạn có thể dùng bất kỳ giá trị position-area
nào làm lựa chọn dự phòng. Trong ví dụ này, ở các chế độ viết từ trái sang phải như tiếng Anh, phần tử được định vị sẽ cố gắng được định vị ở cuối phần tử neo, trải dài trên cột ở giữa và cột bên phải. Nếu nội dung đó tràn ra, thì nội dung sẽ cố gắng được đặt ở cuối phần tử liên kết, trải dài trên các cột bên trái và ở giữa. Nếu vị trí đó cũng tràn, thì vị trí sẽ quay trở lại vị trí mặc định, ngay cả khi vị trí đó tràn.
.positioned-element {
position-area: block-end span-inline-end;
position-try-fallbacks: block-end span-inline-start;
}
Ngoài ra, còn có một số từ khoá flip-
xử lý các trường hợp dự phòng phổ biến. flip-block
và flip-inline
thử lật phần tử qua các trục khối và trục nội tuyến. Bạn cũng có thể kết hợp các thao tác này với flip-block flip-inline
để lật cả hai trục. Giá trị flip-start
lật phần tử được định vị qua một đường chéo từ góc bắt đầu đến góc kết thúc của phần tử neo.
Bạn cũng có thể tạo một lựa chọn dự phòng tuỳ chỉnh bằng @position-try
. Lựa chọn này cho phép bạn đặt lề, căn chỉnh và thậm chí thay đổi điểm neo.
@position-try --menu-below {
position-area: bottom span-right;
margin-top: 1em;
}
#positioned-element {
position-try: --menu-below;
}
Bạn có thể thêm flip-block
và flip-inline
vào các lựa chọn dự phòng @position-try
để tạo một biến thể.
#positioned-element {
position-try: --menu-below, flip-inline --menu-below;
}
Trong ví dụ trước, trình duyệt sẽ thực hiện các bước sau, dừng lại ngay khi tìm thấy một giải pháp không bị tràn.
- Phần tử được đặt bằng
position-area: end
, ở dưới cùng bên phải của điểm neo. - Nếu phần tử đó tràn, phần tử sẽ được đặt bằng lựa chọn dự phòng tuỳ chỉnh có tên
--bottom-span-right
, lựa chọn này sẽ đặt phần tử đó bằngposition-area: bottom span-right
, có thêm một lề bên dưới. - Nếu nội dung đó tràn ra, phần tử sẽ được đặt bằng
flip-inline --bottom-span-right
, kết hợp lựa chọn dự phòng tuỳ chỉnh vớiflip-inline
, về cơ bản làposition-area: bottom span-left
. - Nếu nội dung đó tràn ra, phần tử sẽ được đặt bằng cách sử dụng lựa chọn dự phòng tuỳ chỉnh
--use-alternate
, lựa chọn này sẽ đặt phần tử bên dưới một điểm neo hoàn toàn khác. - Nếu điều đó vượt quá, phần tử sẽ quay trở lại vị trí ban đầu, với
position-area: end
, mặc dù vị trí đó được biết là vượt quá.
Thứ tự dự phòng
Theo mặc định, khi vị trí ban đầu tràn, trình duyệt sẽ thử từng lựa chọn trong position-try-fallbacks
cho đến khi tìm thấy một vị trí không tràn. Bạn có thể ghi đè hành vi này bằng position-try-order
để kiểm thử từng lựa chọn dự phòng và sử dụng lựa chọn có nhiều khoảng trống nhất trên một trục cụ thể.
Bạn có thể chỉ định trục bằng từ khoá logic (most-block-size
và most-inline-size
) hoặc bằng từ khoá vật lý (most-height
và most-width
).
Bạn có thể kết hợp position-try-order
và position-try-fallbacks
với ký hiệu viết tắt position-try
, trong đó thứ tự xuất hiện trước.
Thao tác cuộn
Khi người dùng cuộn, họ mong đợi trang sẽ di chuyển mượt mà. Để thực hiện việc này, các trình duyệt có giới hạn về cách sử dụng tính năng định vị phần tử liên kết khi cuộn.
Mặc dù bạn có thể liên kết một phần tử được định vị với các điểm neo trong nhiều vùng chứa có thể cuộn, nhưng phần tử đó sẽ chỉ di chuyển khi một trong các điểm neo cuộn. Đây sẽ là điểm neo mặc định, là điểm neo ngầm định trong một cửa sổ bật lên hoặc giá trị của position-anchor
.
Bạn sẽ thấy rằng phần tử được định vị vẫn hiển thị ngay cả khi phần tử neo bị cuộn ra khỏi khung hiển thị. Để ẩn phần tử được định vị khi phần tử neo bị ẩn, hãy đặt position-visibility: anchors-visible
. Điều này không chỉ áp dụng khi phần tử liên kết bị cuộn quá mức mà còn áp dụng nếu phần tử đó bị ẩn theo những cách khác, chẳng hạn như bằng visibility: hidden
.
Kiểm tra mức độ hiểu biết của bạn
Giá trị nào là giá trị hợp lệ cho mặt trong anchor()
?
inside
25%
25px
25px
làm giá trị dự phòng, nhưng bạn chỉ có thể dùng tỷ lệ phần trăm cho phía.block-start
start
Giá trị nào là giá trị hợp lệ cho position-area
?
top
block-end inline-end
block-start block-end
Những thuộc tính nào hỗ trợ hàm anchor()
?
top
margin-left
inset-block-start
transform
Điều gì sẽ xảy ra nếu có nhiều điểm neo có cùng anchor-name
?