Giới thiệu API định vị neo CSS

API định vị neo CSS là yếu tố đột phá trong phát triển web vì nó cho phép bạn định vị một cách gốc các phần tử có liên quan đến các phần tử khác, được gọi là neo. API này giúp đơ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ú thích, lựa chọn, nhãn, thẻ, hộp thoại cài đặt, v.v. Với vị trí neo được tích hợp vào trình duyệt, bạn sẽ có thể xây dựng giao diện người dùng theo 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 khả năng sáng tạo.

Tính năng định vị cố định có trong Chrome 125.

Hỗ trợ trình duyệt

  • Chrome: 125.
  • Cạnh: 125.
  • Firefox: không được hỗ trợ.
  • Safari: không được hỗ trợ.

Nguồn

Khái niệm cốt lõi: Neo và các phần tử định vị

Trọng tâm của API này là mối quan hệ giữa cố địnhcác phần tử được định vị. Điểm 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à một phần tử được đặt tương ứng với một điểm neo bằ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ị.

Phần tử neo và phần tử được định vị.

Thiết lập quảng cáo cố định

Rất đơn giản để tạo quảng cáo cố định. Áp dụng thuộc tính tên neo cho phần tử đã chọn và chỉ định giá trị nhận dạng duy nhất cho phần 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 gán một tên neo, .anchor-button sẽ đóng vai trò là một điểm 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 liên kết này với các phần tử khác theo một trong hai cách:

Neo ngầm ẩn

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ử mà 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 cách sử dụ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);
}

Quảng cáo cố định rõ ràng

Ngoài ra, bạn có thể sử dụng tên liên kết ngay trong hàm liên kết (ví dụ: top: anchor(--anchor-el bottom). Đây được gọi là một quảng cáo cố định rõ ràng và có thể hữu ích nếu bạn muốn liên kết đến nhiều phần tử (hãy đọc tiếp để biết 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

Sơ đồ định vị neo với các thuộc tính vật lý.

Vị trí neo được tạo dựa trên vị trí tuyệt đối của 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ị của mình. 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);
}
Biểu đồ các cạnh định vị trên phần tử đã được định vị.

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:

Bản minh hoạ về một neo cơ bản.

Ảnh chụp màn hình bản minh hoạ.

Để sử dụng vị trí logic cho các giá trị này, các 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-itemsalign-items.

Ví dụ này sửa đổi phần tử 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 neo của phần tử đó.

.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;
}
Bản minh hoạ về một quảng cáo cố định được căn giữa bằng justify-center.

Ảnh chụp màn hình bản minh hoạ.

Nhiều quảng cáo cố định

Các thành phần có thể được chia sẻ Internet với nhiều 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 quảng cáo cố định. 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 thành phần được định vị được neo vào phía dưới cùng bên phải của một điểm neo, còn phần dưới cùng bên phải của thành phần được định vị được neo vào phía trên bên trái của điểm neo thứ hai:

.anchored {
  position: absolute;
  top: anchor(--one bottom);
  left: anchor(--one right);
  right: anchor(--two left);
  bottom: anchor(--two top);
}
Bản minh hoạ cho thấy nhiều quảng cáo cố định.

Ảnh chụp màn hình bản minh hoạ.

Vị trí với inset-area

Ngoài việc định hướng theo mặc định từ vị trí tuyệt đối, có một cơ chế bố cục mới có trong API neo được gọi là vùng lồng ghép.

Vùng lồng ghép giúp dễ dàng đặ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 một lưới 9 ô với phần tử neo ở giữa.

Nhiều tuỳ chọn định vị vùng lồng ghép khác nhau, được hiển thị trên lưới 9 ô

Để dùng vùng lồng ghép thay vì vị trí tuyệt đối, hãy sử dụng thuộc tính inset-area có giá trị thực hoặc logic. Ví dụ:

  • Trên cùng chính giữa: inset-area: top hoặc inset-area: block-start
  • Bên trái chính giữa: inset-area: left hoặc inset-area: inline-start
  • Dưới cùng chính giữa: inset-area: bottom hoặc inset-area: block-end
  • Chính giữa bên phải: inset-area: right hoặc inset-area: inline-end
Bản minh hoạ cho thấy nhiều quảng cáo cố định.

Ảnh chụp màn hình bản minh hoạ.

Để khám phá thêm về những vị trí này, hãy khám phá công cụ sau:

Công cụ neo cho các vị trí vùng lồng ghép.

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ị điểm neo, có thể dùng để định kích thước hoặc định vị một phần tử được định vị cố định dựa trên kích thước của phần tử neo đó (chiều rộng, chiều cao hoặc kích thước cùng dòng và khối).

CSS sau đây cho thấy một 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ú thích gấp hai lần chiều cao của điểm 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);
}
Bản minh hoạ cho anchor-size

Ảnh chụp màn hình bản minh hoạ.

Sử dụng điểm neo với các phần tử 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 chia sẻ Internet về các phần tử đó với nhau và cuộn cùng với các phần tử không ở lớp trên cùng. Đây là một thắng lợi lớn cho giao diện nhiều lớp.

Trong ví dụ sau, một nhóm cửa sổ bật lên chú thích sẽ được kích hoạt bằng một nút. Nút là điểm neo và chú thích 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-nameposition-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.

Bản minh hoạ sử dụng quảng cáo cố định với popover

Ảnh chụp màn hình bản minh hoạ.

Đ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ể dùng lệnh @position-try cùng với thuộc tính position-try-options.

Trong ví dụ sau, một trình đơn phụ xuất hiện ở bên phải của một trình đơn. Trình đơn và trình đơn con là cách sử dụng tốt cho API định vị điểm neo cùng với thuộc tính cửa sổ bật lên, vì các trình đơn này có xu hướng liên kết với một nút điều kiện 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 bên dưới trình đơn. Để thực hiện 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);
  inset-area: right span-bottom;
}

Sau đó, hãy thiết lập vị trí cố định dự phòng bằng cách sử dụng @position-try:

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}

Cuối cùng, hãy kết nối cả hai với position-try-options. Tất cả đều có giao diện như sau:

#submenu {
  position: absolute;
  position-anchor: --submenu;
  /* initial position */
  margin-left: var(--padding);
  inset-area: right span-bottom;
  */ connect with position-try options */
  position-try-options: --bottom;
}

/* alternate position */
@position-try --bottom {
  margin: var(--padding) 0 0 var(--padding);
  inset-area: bottom;
}
Bản minh hoạ sử dụng quảng cáo cố định với popover

Từ khoá tự động lật ở vị trí cố định

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), bạn thậm chí 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-blockflip-inline. Các mã này hoạt động như một giá trị thay thế cho phần khai báo @position-try tuỳ chỉnh và có thể kết hợp với nhau:

position-try-options: flip-block, flip-inline, flip-block flip-inline;

Việc lật từ khoá có thể đơn giản hoá đáng kể mã liên kết 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;
  inset-area: top;
  position-try-options: flip-block;
}
Sử dụng tính năng tự động lật với position-try-options: flip-block

position-visibility cho quảng cáo cố định trong cuộn phụ

Có một số trường hợp mà bạn có thể muốn neo một phần tử vào trong một cuộn phụ của trang. Trong các trường hợp này, bạn có thể kiểm soát chế độ hiển thị của quảng cáo cố định bằng cách sử dụng position-visibility. Khi nào quảng cáo cố định duy trì hiển thị? Vấn đề này biến mất khi nào? 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ử đã định vị ở trong khung hiển thị cho đến khi điểm neo nằm ngoài khung hiển thị:

#tooltip {
  position: fixed;
  position-anchor: --anchor-top-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
}
Bản minh hoạ position-visibility: anchors-visible

Ngoài ra, bạn có thể sử dụng position-visibility: no-overflow để ngăn quảng cáo cố định tràn vùng chứa.

#tooltip {
  position: absolute;
  position-anchor: --anchor-top-anchor;
  position-visibility: no-overflow;
  bottom: anchor(top);
}
Bản minh hoạ position-visibility: no-overflow

Phát hiện tính năng và chèn polyfill

Do trình duyệt hỗ trợ còn hạn chế tại thời điểm này, bạn có thể muố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 kiểu neo của bạn như sau:

@supports (anchor-name: --myanchor) {

  /* Anchor styles here */

}

Ngoài ra, bạn có thể chèn polyfill tính năng định vị neo bằng polyfill định vị neo CSS của Oddbird, hoạt động trên Firefox 54, Chrome 51, Edge 79 và Safari 10. Tệp polyfill này hỗ trợ hầu hết các tính năng vị trí neo cơ bản, mặc dù quá trình triển khai hiện tại chưa hoàn tất 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 huỷpkg hoặc nhập đường liên kết này trực tiếp 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 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 chúng. Nếu thực sự có mối quan hệ ngữ nghĩa giữa phần tử neo 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ì có một cách để thực hiện việc đó là sử dụng aria-details để trỏ từ phần tử neo đế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 sử 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ề hỗ trợ tiếp cận trong thông số kỹ thuật.

Kết luận

Đây là một tính năng hoàn toàn mới và chúng tôi rất vui được chứng kiến những gì bạn tạo ra nhờ tính năng này. Đến nay, chúng ta đã thấy một số trường hợp sử dụng thực sự gọn gàng từ cộng đồng như nhãn động trong biểu đồ, đường kết nối, chú thích cuối trang và tham chiếu chéo hình ảnh. Trong khi bạn thử nghiệm vị trí neo, chúng tôi rất mong nhận được ý kiến phản hồi của bạn và nếu bạn phát hiện bất kỳ lỗi nào, hãy cho chúng tôi biết.

Tài liệu đọc thêm