Pemosisian anchor

Saat menempatkan tooltip atau menu drop-down, Anda sering kali ingin memosisikannya relatif terhadap elemen lain di halaman. Meskipun ada cara menggunakan posisi absolut untuk mencapai efek ini, persyaratan yang lebih kompleks secara historis menggunakan posisi item menggunakan JavaScript.

Penempatan anchor CSS menyediakan cara untuk menempatkan elemen secara deklaratif relatif terhadap elemen lain.

Mengikat elemen

Untuk menjadikan elemen sebagai penanda, Anda memberikan nilai anchor-name berupa string apa pun yang dimulai dengan dua tanda hubung. Ini adalah ID yang akan digunakan elemen yang diposisikan untuk menemukan anchornya, dan sebaiknya beri nama yang deskriptif. Anda bahkan dapat memberikan beberapa nama penanda pada suatu elemen, jika elemen tersebut akan digunakan sebagai penanda dengan cara yang berbeda.

Anda harus menetapkan beberapa properti pada elemen yang diposisikan agar dapat diikat. Pertama, Anda perlu menarik elemen keluar dari alur dokumen, sehingga elemen tersebut mengambang, dengan menyetel position: absolute atau position: fixed.

Selanjutnya, Anda harus menetapkan penambat yang ingin Anda ikat, dengan menetapkan position-anchor ke nama penambat yang Anda tetapkan pada penambat.

Terakhir, Anda harus menetapkan cara memosisikan penanda. Anda akan mempelajari position-area lebih lanjut nanti dalam modul ini.

#anchor {
   anchor-name: --my-anchor;
}

#positionedElement {
     position: absolute;
     position-anchor: --my-anchor;
     position-area: end;
}

Penambatan implisit

Pop-up bahkan lebih mudah diikat. Saat Anda membuka popover menggunakan tombol dengan popovertarget atau dengan menyetel source dengan showPopover({source}), popover sudah memiliki "anchor implisit". Karena popover sudah mengambang dengan position: fixed secara default, untuk memosisikan popover, Anda hanya perlu menyetel posisi.

#anchor{}

#positionedElement {
  position-area: end;
  margin: unset;
}

Menentukan cakupan anchor potensial

Anda dapat menerapkan penempatan penanda sebagai bagian dari komponen, sehingga Anda dapat menggunakan pola seperti menu drop-down di beberapa tempat. Jika Anda menggunakan anchor-name yang sama beberapa kali, bagaimana cara memastikan bahwa setiap elemen yang diposisikan menemukan anchor yang benar?

Solusi JavaScript melibatkan penambahan ID unik ke setiap penanda, lalu merujuknya dari elemen yang diposisikan. Hal ini menjadi rumit, dan CSS memiliki solusi yang lebih sederhana dengan anchor-scope.

Properti anchor-scope menetapkan nama penanda mana yang akan dicocokkan hanya di antara elemen dan turunannya. Fungsi ini menerima daftar satu atau beberapa nama penanda atau kata kunci all untuk membatasi cakupan semua nama penanda yang ditentukan.

anchor-scope idealnya ditambahkan ke elemen induk dari elemen yang diposisikan dan elemen penahan yang tidak berisi elemen penahan lain dengan nama yang sama. Sering kali, hal ini ada di root komponen yang dapat digunakan kembali.

Contoh berikut menunjukkan perbedaan yang dihasilkan anchor-scope saat diterapkan ke elemen berulang dengan anchor-name yang sama. Dalam contoh, semua elemen <img> dan banner gambar mereferensikan nama anchor --image. Jika anchor-scope diterapkan ke elemen <li>, position-anchor: --image hanya akan cocok dengan elemen <img> dalam elemen <li> yang sama dengan banner, atau akan cocok dengan <img> yang terakhir dirender.

Positioning

Setelah Anda mengikat elemen ke anchor, saatnya memosisikannya. Pemosisian penahan menyediakan dua metode untuk pemosisian – position-area dan fungsi anchor().

position-area

Properti position-area memungkinkan Anda memosisikan elemen di sekitar penanda dengan menentukan satu atau dua kata kunci. Hal ini mencakup banyak kasus penggunaan umum, dan sering kali merupakan titik awal yang baik.

Cara kerja position-area

position-area berfungsi dengan membuat blok penampung baru untuk elemen yang diposisikan di area yang dihasilkan oleh tepi anchor dan blok penampung asli elemen yang diposisikan.

Meskipun ada banyak kata kunci yang tersedia untuk position-area, kata kunci tersebut dapat dikelompokkan ke dalam beberapa kategori agar lebih mudah dipahami. Anchor-tool.com adalah alat yang bagus untuk mempelajari sintaksis.

Kata kunci fisik

Anda dapat menggunakan kata kunci fisik, top, left, bottom, right, dan center. Misalnya, position-area: top right akan menempatkan elemen yang diposisikan di atas dan di sebelah kanan anchor. Kata kunci ini juga memiliki padanan sumbu fisik, y-start, x-start, y-end, dan x-end.

Kata kunci logis

Anda juga dapat menggunakan kata kunci logis, block-start, block-end, inline-start, dan inline-end. Misalnya, position-area: block-end inline-start akan menempatkan elemen yang diposisikan di bawah dan di sebelah kiri penanda dalam bahasa seperti Inggris, atau setelah penanda pada sumbu blok dan sebelum penanda pada sumbu sebaris dalam mode penulisan dokumen. center juga dapat digunakan dengan kata kunci logis.

Anda juga dapat menghilangkan sumbu jika menentukan kata kunci logis, dengan sumbu blok terlebih dahulu dan sumbu sebaris kedua. position-area: start end sama dengan position-area: block-start inline-end atau bahkan position-area: inline-end block-start.

Mencakup beberapa area petak

Sejauh ini, Anda mungkin telah memperhatikan bahwa opsi ini hanya memungkinkan Anda menempatkan elemen yang diposisikan dalam satu ruang petak. Menambahkan awalan span ke properti fisik atau logis akan menambahkan ruang petak tengah yang berdekatan. position-area: span-top right akan diposisikan di sebelah kanan anchor, dan dari bagian bawah anchor ke bagian atas blok penampung asli elemen yang diposisikan.

Area posisi umum untuk menu drop-down adalah position-area: block-end span-inline-end.

Kata kunci span-all mencakup 3 baris atau kolom.

Satu kata kunci

Jika Anda hanya menetapkan satu kata kunci, sumbu lainnya akan ditetapkan secara otomatis. Sebagian besar berfungsi seperti yang Anda harapkan, tetapi mungkin berguna untuk memahami cara kerjanya.

Jika kata kunci yang diberikan jelas tentang sumbunya, sumbu lainnya dihitung sebagai span-all. Artinya, position-area: bottom setara dengan position-area: bottom span-all, dan elemen yang diposisikan akan berada di bawah penahan, serta memiliki seluruh lebar blok penampung yang tersedia.

Di sisi lain, jika kata kunci tidak menunjukkan sumbu dengan jelas, kata kunci tersebut akan diulang. position-area: start setara dengan start start, dan ditempatkan di kiri atas penanda dalam bahasa kiri ke kanan.

Fungsi anchor()

Untuk kasus penggunaan yang lebih canggih, position-area mungkin tidak memenuhi persyaratan Anda. Fungsi anchor() memungkinkan Anda menetapkan properti inset individual berdasarkan posisi elemen lain. Ini diselesaikan ke panjang CSS, yang berarti Anda dapat menggunakannya dalam perhitungan dan dengan fungsi CSS lainnya. Selain itu, Anda juga dapat menambatkan sisi yang berbeda ke penanda yang berbeda.

Fungsi anchor() mengambil nama penanda dan sisi penanda. Jika elemen Anda memiliki penahan default, baik yang ditetapkan dengan position-anchor atau secara implisit, misalnya dengan popover, Anda dapat menghilangkan nama penahan.

.positionedElement {
  block-start: anchor(--my-anchor start);
  /*  OR  */
  position-anchor: --my-anchor;
  block-start: anchor(start);
}

Nilai penggantian

Jika penanda tidak dapat ditemukan untuk fungsi anchor(), seluruh deklarasi akan tidak valid. Hal ini dapat terjadi jika penanda dirender setelah elemen yang diposisikan, atau jika tidak ada elemen dengan anchor-name yang cocok. Untuk menanganinya, Anda dapat menetapkan durasi atau persentase penggantian.

.positionedElement {
   block-start: anchor(--my-anchor, 100px)
}

Dalam contoh sebelumnya, nilai kiri elemen yang diposisikan ditambatkan ke --focused-anchor, tetapi anchor-name hanya ada saat tombol pertama diarahkan atau difokuskan. Karena fungsi anchor() diubah menjadi panjang, Anda dapat menggunakan anchor lain sebagai penggantian. Jika kita tidak menyediakan penggantian, elemen yang diposisikan tidak akan diposisikan.

Kata kunci sisi anchor

Nilai sisi penahan memilih tepi penahan mana yang akan diposisikan. Mirip dengan position-area, nilai sisi penahan mendukung beberapa jenis sintaksis yang berbeda.

Jenis Nilai Deskripsi
Fisik top, left, bottom, right

Kata kunci fisik sesuai dengan sisi tertentu dari penahan, tetapi hanya dapat digunakan pada sumbu yang sama dengan inset elemen yang diposisikan yang Anda tetapkan.

Misalnya, top: anchor(bottom) memosisikan bagian atas elemen di bagian bawah anchor, tetapi left: anchor(top) tidak akan berfungsi.

Sisi inside, outside

Kata kunci inside sesuai dengan sisi yang sama dengan properti inset, dan kata kunci outside sesuai dengan sisi yang berlawanan pada sumbu yang sama.

Misalnya, inset-block-start: anchor(inside) merujuk pada sisi block-start penahan, dan inset-inline-end: (outside) merujuk pada sisi inline-start penahan.

Logis start, end, self-start, self-end

Kata kunci logis merujuk pada sisi penahan berdasarkan mode penulisan elemen yang diposisikan dengan self-start dan self-end, atau dengan mode penulisan blok penampung elemen yang diposisikan dengan start dan end.

Persentase 0% - 100%

Nilai persentase menempatkan elemen yang diposisikan di sepanjang sumbu dari awal hingga akhir penahan pada sumbu yang ditentukan. 0% berada di sisi start penahan, dan 100% berada di sisi akhir penahan. center setara dengan 50%. Jika Anda menggunakan persentase pada inset sisi akhir seperti bottom, hal ini tidak dibalik—0% tetap merupakan sisi start anchor.

Contoh ini menunjukkan cara nilai persentase selalu bergerak dari awal hingga akhir pada sumbu yang ditentukan:

Menggunakan anchor()

Karena anchor() adalah panjang, maka sangat fleksibel. Anda dapat memanipulasi nilai dengan fungsi CSS seperti max() dan calc().

Salah satu batasannya adalah Anda hanya dapat menggunakan fungsi anchor() pada properti inset.

Contoh sebelumnya menambahkan latar belakang di belakang panel detail yang terbuka yang dianimasikan dengan lancar saat panel lain dibuka, dan direntangkan untuk menyertakan panel detail yang di-hover. Untuk melakukannya, min() digunakan untuk memilih panjang yang lebih kecil di antara dua anchor.

#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)))
  );
}

Contoh ini juga menggunakan calc() untuk menambahkan ruang inline di sekitar panel yang terbuka.

Menggunakan ukuran penahan

Anda juga dapat menggunakan fungsi anchor-size() untuk menggunakan dimensi penahan bagi ukuran, posisi, atau margin elemen yang diposisikan.

anchor-size() mengambil nama penanda, atau menggunakan penanda default. Secara default, ukuran penanda akan digunakan pada sumbu yang sedang digunakan, sehingga width: anchor-size() akan menampilkan lebar penanda. Anda juga dapat menggunakan sumbu lainnya dengan menentukan panjang yang diinginkan, dengan kata kunci fisik width dan height atau kata kunci logis block, inline, self-block, dan self-inline.

Menangani konten yang berlebih

Anda telah membuat komponen menu dropdown, dan menggunakan penempatan anchor untuk menempatkan menu dropdown di tempat yang Anda inginkan. Namun, Anda memindahkan menu ke sisi lain layar, atau menggunakannya untuk menu pengguna, dan nama pengguna sangat panjang. Tiba-tiba, menu drop-down Anda tidak terlihat di layar. Selanjutnya bagaimana?

Penempatan anchor CSS memiliki sistem bawaan yang memungkinkan Anda dengan cepat membangun serangkaian penggantian yang andal saat elemen yang ditempatkan berakhir di luar blok penampungnya.

Opsi penggantian

Aturan position-try-fallbacks mengambil daftar opsi penggantian. Jika posisi default meluap, setiap opsi akan dicoba secara berurutan hingga ada posisi yang tidak meluap.

Anda dapat menggunakan nilai position-area apa pun sebagai opsi penggantian. Dalam contoh ini, dalam mode penulisan kiri ke kanan seperti bahasa Inggris, elemen yang diposisikan akan mencoba diposisikan di bagian bawah penanda, yang mencakup kolom tengah dan kanan. Jika meluap, item akan mencoba diposisikan di bagian bawah penanda, yang mencakup kolom kiri dan tengah. Jika juga meluap, posisi akan kembali ke posisi default, meskipun meluap.

.positioned-element {
  position-area: block-end span-inline-end;
  position-try-fallbacks: block-end span-inline-start;
}

Ada juga beberapa kata kunci flip- yang menangani kasus penggantian umum. flip-block dan flip-inline mencoba membalik elemen di atas sumbu blok dan inline. Transformasi ini juga dapat digabungkan dengan flip-block flip-inline untuk membalikkan kedua sumbu. Nilai flip-start membalik elemen yang diposisikan di atas garis diagonal dari sudut awal ke sudut akhir penanda.

Anda juga dapat membuat opsi penggantian kustom dengan @position-try—hal ini memungkinkan Anda menetapkan margin, perataan, dan bahkan mengubah anchor.

@position-try --menu-below {
  position-area: bottom span-right;
  margin-top: 1em;
}

#positioned-element {
  position-try: --menu-below;
}

flip-block dan flip-inline dapat ditambahkan ke opsi penggantian @position-try untuk membuat varian.

#positioned-element {
  position-try: --menu-below, flip-inline --menu-below;
}

Pada contoh sebelumnya, browser mengikuti langkah-langkah ini, dan berhenti segera setelah menemukan solusi yang tidak meluap.

  1. Elemen ditempatkan dengan position-area: end, di kanan bawah anchor.
  2. Jika meluap, elemen ditempatkan dengan opsi penggantian kustom bernama --bottom-span-right, yang menempatkannya dengan position-area: bottom span-right, dengan margin tambahan di bawahnya.
  3. Jika meluap, elemen ditempatkan dengan flip-inline --bottom-span-right, yang menggabungkan opsi penggantian kustom dengan flip-inline, yang pada dasarnya adalah position-area: bottom span-left.
  4. Jika meluap, elemen akan ditempatkan menggunakan opsi penggantian kustom --use-alternate, yang menempatkannya di bawah anchor yang sama sekali berbeda.
  5. Jika meluap, elemen akan kembali ke penempatan aslinya, dengan position-area: end, meskipun diketahui meluap.

Urutan penggantian

Secara default, saat posisi awal meluap, browser akan mencoba setiap opsi di position-try-fallbacks hingga menemukan posisi yang tidak meluap. Anda dapat mengganti perilaku ini dengan position-try-order untuk menguji setiap opsi penggantian, dan menggunakan opsi yang memiliki ruang paling banyak pada sumbu tertentu.

Anda dapat menentukan sumbu dengan kata kunci logis, most-block-size dan most-inline-size, atau dengan kata kunci fisik most-height dan most-width.

position-try-order dan position-try-fallbacks dapat digabungkan dengan singkatan position-try, dengan urutan yang muncul terlebih dahulu.

Scroll

Saat men-scroll, pengguna berharap halaman bergerak dengan lancar. Untuk melakukannya, browser memiliki batasan tentang cara penggunaan penempatan anchor saat men-scroll.

Meskipun Anda dapat menambatkan elemen yang diposisikan ke penanda dalam penampung scroll yang berbeda, elemen hanya akan bergerak sebagai respons terhadap scroll salah satu penanda. Ini akan menjadi penahan default, yang merupakan penahan implisit dari popover, atau nilai position-anchor.

Anda akan melihat bahwa elemen yang diposisikan tetap terlihat meskipun anchor di-scroll keluar dari tampilan. Untuk menyembunyikan elemen yang diposisikan saat anchor disembunyikan, tetapkan position-visibility: anchors-visible. Hal ini tidak hanya berlaku saat penanda di-scroll berlebih, tetapi juga jika disembunyikan dengan cara lain, misalnya dengan visibility: hidden.

Periksa pemahaman Anda

Manakah nilai yang valid untuk sisi dalam anchor()?

inside
Benar.
25%
Benar.
25px
Salah. Meskipun panjang seperti 25px dapat digunakan sebagai nilai penggantian, hanya persentase yang dapat digunakan untuk sisi.
block-start
Salah
start
Benar.

Manakah nilai yang valid untuk position-area?

top
Benar.
block-end inline-end
Benar.
block-start block-end
Salah. Anda hanya dapat menentukan satu kolom atau baris pada setiap sumbu.

Properti mana yang mendukung fungsi anchor()?

top
Benar.
margin-left
Salah.
inset-block-start
Benar.
transform
Salah.

Jika ada beberapa penanda dengan anchor-name yang sama, apa yang terjadi?

Elemen yang diposisikan diduplikasi dan diikat ke setiap kecocokan.
Salah.
Elemen yang diposisikan diikat ke elemen pertama dalam dokumen.
Salah.
Elemen yang diposisikan terikat pada elemen terakhir dalam dokumen.
Benar.
Elemen yang diposisikan diikat ke anchor terdekat.
Salah.