1. Prompt dan Kasus Penggunaan
Anotasi harga mengikuti sebuah kartu produk. Awal inline-nya sejajar dengan awal konten kartu, dan ukuran inline-nya sesuai dengan kartu tersebut. Hubungan ini harus tetap bertahan dalam mode penulisan kiri-ke-kanan, kanan-ke-kiri, dan vertikal. Sebuah daftar me-render banyak pasangan kartu-dan-anotasi, sementara tampilan lain membentangkan penanda rentang (range marker) di antara dua titik akhir yang terpisah.
Pertanyaan ini membahas tentang model tata letak CSS Anchor Positioning: bagaimana sebuah elemen menjadi jangkar (anchor), bagaimana elemen dengan posisi absolut memilih jangkar default, bagaimana fungsi posisi dan ukuran dihitung (resolve), serta bagaimana cakupan nama (name scope) dan containing block membatasi hubungan tersebut. Tabrakan viewport dan interaksi widget mengambang adalah topik implementasi yang terpisah.
2. Apa yang Diuji oleh Pewawancara
- Apakah Anda memahami bahwa
anchor-namemengekspos jangkar danposition-anchormemilih jangkar default untuk elemen yang diposisikan. - Apakah Anda membedakan
anchor(), yang menghasilkan posisi, darianchor-size(), yang menghasilkan panjang. - Apakah Anda menggunakan inset logis dan ukuran logis untuk mendukung mode penulisan daripada mematok semuanya pada
leftdanright. - Apakah Anda mengetahui bahwa urutan sumber (source order), tree scope, dan
anchor-scopememengaruhi pencocokan nama yang sama. - Apakah Anda memeriksa containing block dari elemen yang diposisikan karena nilai-nilai jangkar tetap berpartisipasi dalam kalkulasi pemosisian normal.
3. Pertanyaan Klarifikasi untuk Diajukan Terlebih Dahulu
- Apakah targetnya berupa
position: absoluteatauposition: fixed, dan elemen mana yang membentuk containing block-nya? - Apakah hubungannya satu-ke-satu, banyak target ke satu jangkar, atau satu target ke beberapa jangkar?
- Apakah halaman mengulang komponen dengan nama yang sama atau melintasi batas pohon (tree boundary) seperti Shadow DOM?
- Haruskah komponen mendukung mode penulisan kanan-ke-kiri dan vertikal? Haruskah komponen menyalin lebar fisik atau ukuran inline logis?
- Nilai pemosisian biasa apa yang harus diterapkan jika jangkar bernama tersebut hilang atau tidak dapat diterima dalam konteks saat ini?
4. Kerangka Jawaban 30 Detik
Beri elemen sumber sebuah pengenal bergaris hubung (dashed identifier) dengan anchor-name, lalu buat target menjadi absolute atau fixed dan pilih sumber tersebut dengan position-anchor. Gunakan anchor() untuk membaca tepi jangkar dan anchor-size() untuk membaca dimensi fisik atau logis; inset target tetap dihitung di dalam containing block-nya sendiri. Gunakan inset-inline-*, inset-block-*, dan inline-size untuk dukungan mode penulisan. Batasi cakupan (scope) nama yang berulang dengan anchor-scope, dan beri nama jangkar secara eksplisit di dalam fungsi saat satu target bergantung pada beberapa sumber.
5. Dari Jangkar Menuju Tata Letak Akhir
Langkah 1: Menetapkan Hubungan Jangkar yang Eksplisit
Sumber mengekspos satu atau lebih nama melalui anchor-name. Target harus diposisikan secara absolut atau tetap (fixed) sebelum position-anchor dapat memilih jangkar default-nya:
.product-card {
anchor-name: --product-card;
}
.price-note {
position: absolute;
position-anchor: --product-card;
}position-anchor hanya menetapkan referensi default. Properti ini tidak menyetel inset atau menggantikan containing block target. Jika nama tidak dapat dihitung menjadi jangkar yang dapat diterima, fungsi dependen akan menggunakan fallback-nya atau menjadi tidak valid, sehingga fallback pemosisian biasa tetap memerlukan hasil yang dapat diprediksi.
Langkah 2: Membaca Posisi dengan anchor()
anchor() menghasilkan panjang untuk properti inset, menghubungkan satu tepi target ke tepi jangkar. Inset logis memungkinkan aturan yang sama mengikuti mode penulisan yang berbeda:
.price-note {
position: absolute;
position-anchor: --product-card;
inset-block-start: anchor(end);
inset-inline-start: anchor(start);
}Di sini, start dan end diselesaikan pada sumbu yang relevan. Untuk mereferensikan sesuatu selain jangkar default, letakkan namanya langsung di dalam fungsi, seperti anchor(--sidebar end). Nama eksplisit memungkinkan properti yang berbeda pada satu target bergantung pada sumber yang berbeda.
Langkah 3: Membangun Hubungan Ukuran dengan anchor-size()
anchor-size() mengembalikan dimensi fisik atau logis, bukan koordinat. Anotasi dapat menyalin lebar logis kartu seperti ini:
.price-note {
inline-size: anchor-size(inline);
max-inline-size: min(32rem, anchor-size(inline));
}width dan height cocok untuk hubungan fisik eksplisit; inline dan block cocok untuk komponen yang mengikuti mode penulisan. Fungsi ini juga dapat berpartisipasi dalam calc(), misalnya untuk menurunkan penspasian dari sebagian ukuran inline jangkar. Fungsi ini hanya menyediakan panjang; posisi elemen tetap mengikuti aturan pemosisian absolut.
Langkah 4: Mereferensikan Lebih dari Satu Jangkar
Sebuah penanda rentang dapat dikaitkan dengan awal sebagai jangkar default-nya sementara membaca akhir secara eksplisit di inset lainnya:
.range-start { anchor-name: --range-start; }
.range-end { anchor-name: --range-end; }
.range-band {
position: absolute;
position-anchor: --range-start;
inset-inline-start: anchor(--range-start center);
inset-inline-end: anchor(--range-end center);
}Elemen yang diposisikan masih hanya memiliki satu jangkar default yang terkait melalui position-anchor; nama-nama lain dapat berpartisipasi dalam perhitungan posisi melalui anchor(). Pengaitan default tersebut juga memengaruhi perilaku seperti scroll attachment. Kedua nilai inset masuk ke dalam persamaan containing-block target, sehingga desain harus menentukan fallback untuk jangkar yang hilang, bersilangan, atau tidak dapat diterima.
Langkah 5: Membatasi Cakupan Nama Jangkar yang Berulang
Jika setiap komponen berulang mendeklarasikan --item, elemen terposisi tanpa cakupan (unscoped) dapat cocok dengan jangkar terakhir yang dapat diterima dalam urutan sumber (source order). anchor-scope membatasi nama yang sama ke sub-pohon komponen:
.result-row {
anchor-scope: --item;
}
.result-row__value { anchor-name: --item; }
.result-row__note {
position: absolute;
position-anchor: --item;
inset-inline-start: anchor(end);
}Ini mengontrol visibilitas nama. Ini tidak dapat memaksakan referensi melintasi tree scope, dan tidak membentuk containing block. Komponen tetap membutuhkan ancestor terposisi yang disengaja.
Langkah 6: Menyertakan Containing Block dalam Model
Posisi yang dikembalikan oleh anchor() dikonversi menjadi panjang yang dapat digunakan oleh inset target, tetapi target tetap ditata letaknya oleh containing block pemosisian absolutnya sendiri. Beralih antara absolute dan fixed, memindahkan target dalam DOM, atau membuat konteks pemosisian baru pada ancestor dapat mengubah hasilnya. Jika penempatannya salah, periksa containing block target sebelum melakukan debug pada pencocokan jangkar.
6. Contoh Jawaban Berkualitas Tinggi
Anchor Positioning pertama-tama menghubungkan elemen sumber ke target yang diposisikan. Sumber mendeklarasikan sebuah nama dengananchor-name; target yang absolute atau fixed memilih sumber default-nya denganposition-anchor.anchor()menyediakan posisi ke sebuah inset, sedangkananchor-size()menyediakan dimensi fisik atau logis. Saya menggunakan inset logis daninline-sizeuntuk penulisan kanan-ke-kiri atau vertikal. Target yang membutuhkan dua sumber memilih satu pengaitan default dan menamai setiap sumber di dalamanchor()yang relevan; komponen daftar yang berulang menggunakananchor-scopeuntuk mengisolasi nama yang sama. Saya juga memverifikasi containing block target, karena fungsi jangkar tidak mengabaikan model pemosisian absolut.
7. Kesalahan Umum
- Hanya mendeklarasikan
anchor-namedan mengharapkan pergerakan → belum ada hubungan pemosisian yang terbentuk → jadikan target absolute atau fixed dan referensikan namanya. - Memperlakukan
anchor()sebagai fungsi pengatur ukuran → tanggung jawab posisi dan dimensi menjadi tertukar → gunakananchor()untuk tepi dananchor-size()untuk dimensi. - Menuliskan kode statis (hard-code)
leftdanwidth→ penulisan kanan-ke-kiri atau vertikal membalikkan hubungan yang dimaksudkan → pilih inset logis dan ukuran logis. - Menggunakan kembali satu nama di seluruh item daftar tanpa scope → target mengikuti jangkar bernama sama yang terakhir → setel
anchor-scopepada setiap kontainer komponen. - Memperlakukan
anchor-scopesebagai containing block → pencocokan sudah benar tetapi koordinat masih salah → periksa ancestor yang diposisikan secara terpisah. - Menyetel satu default
position-anchoruntuk target multi-jangkar → properti lain tetap membaca sumber yang salah → beri nama setiap sumber secara eksplisit dalamanchor()-nya.
8. Pertanyaan Lanjutan dan Tanggapan
Pertanyaan Lanjutan 1: Apa perbedaan anchor() dengan position-area?
anchor() mengubah tepi jangkar tertentu menjadi panjang untuk sebuah inset, yang berguna untuk hubungan tepi-ke-tepi yang presisi. position-area menempatkan target dalam kisi area yang berpusat pada jangkar, yang mengekspresikan wilayah penempatan yang lebih luas. Keduanya termasuk dalam model yang sama tetapi menyelesaikannya pada tingkat yang berbeda.
Pertanyaan Lanjutan 2: Apakah anchor-size() membuat target mengikuti pergerakan jangkar?
Tidak. Fungsi tersebut menghitung panjang. Pelacakan posisi berasal dari anchor(), position-area, atau aturan pemosisian lainnya. Menyetel hanya inline-size: anchor-size(inline) menyinkronkan ukuran logis, bukan lokasi.
Pertanyaan Lanjutan 3: Apa yang terjadi jika beberapa elemen berbagi satu anchor-name?
Target memilih jangkar yang dapat diterima sesuai dengan aturan pencocokan, sehingga komponen yang berulang semuanya dapat dihitung ke sumber bernama sama yang muncul kemudian. Batasi cakupan (scope) nama di dalam setiap komponen dengan anchor-scope, atau berikan nama berbeda yang eksplisit pada setiap instans.
Pertanyaan Lanjutan 4: Mengapa target bisa bergeser (offset) ketika jangkarnya sudah benar?
Inset-nya tetap berpartisipasi dalam pemosisian absolut. Containing block, mode penulisan, margin, dan ukuran target semuanya memengaruhi hasil akhir. Periksa containing block target terlebih dahulu, lalu verifikasi jangkar default-nya dan nilai yang dihitung dari setiap fungsi.