Topik wawancara representatif

Wawancara Frontend: Model dan Primitif CSS Anchor Positioning

FrontendSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Jelaskan model tata letak CSS Anchor Positioning. Gunakan anotasi yang terpasang pada kartu untuk mendemonstrasikan penamaan jangkar (anchor), pengaitan posisi, fungsi posisi dan ukuran, serta scoping.

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-name mengekspos jangkar dan position-anchor memilih jangkar default untuk elemen yang diposisikan.
  • Apakah Anda membedakan anchor(), yang menghasilkan posisi, dari anchor-size(), yang menghasilkan panjang.
  • Apakah Anda menggunakan inset logis dan ukuran logis untuk mendukung mode penulisan daripada mematok semuanya pada left dan right.
  • Apakah Anda mengetahui bahwa urutan sumber (source order), tree scope, dan anchor-scope memengaruhi 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

  1. Apakah targetnya berupa position: absolute atau position: fixed, dan elemen mana yang membentuk containing block-nya?
  2. Apakah hubungannya satu-ke-satu, banyak target ke satu jangkar, atau satu target ke beberapa jangkar?
  3. Apakah halaman mengulang komponen dengan nama yang sama atau melintasi batas pohon (tree boundary) seperti Shadow DOM?
  4. Haruskah komponen mendukung mode penulisan kanan-ke-kiri dan vertikal? Haruskah komponen menyalin lebar fisik atau ukuran inline logis?
  5. 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:

css
.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:

css
.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:

css
.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:

css
.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:

css
.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 dengan anchor-name; target yang absolute atau fixed memilih sumber default-nya dengan position-anchor. anchor() menyediakan posisi ke sebuah inset, sedangkan anchor-size() menyediakan dimensi fisik atau logis. Saya menggunakan inset logis dan inline-size untuk penulisan kanan-ke-kiri atau vertikal. Target yang membutuhkan dua sumber memilih satu pengaitan default dan menamai setiap sumber di dalam anchor() yang relevan; komponen daftar yang berulang menggunakan anchor-scope untuk mengisolasi nama yang sama. Saya juga memverifikasi containing block target, karena fungsi jangkar tidak mengabaikan model pemosisian absolut.

7. Kesalahan Umum

  • Hanya mendeklarasikan anchor-name dan 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 → gunakan anchor() untuk tepi dan anchor-size() untuk dimensi.
  • Menuliskan kode statis (hard-code) left dan width → 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-scope pada setiap kontainer komponen.
  • Memperlakukan anchor-scope sebagai containing block → pencocokan sudah benar tetapi koordinat masih salah → periksa ancestor yang diposisikan secara terpisah.
  • Menyetel satu default position-anchor untuk target multi-jangkar → properti lain tetap membaca sumber yang salah → beri nama setiap sumber secara eksplisit dalam anchor()-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.

Sumber publik

Pertanyaan terkait