Dukungan lapisan atas di Chrome DevTools

Chrome DevTools menambahkan dukungan untuk elemen lapisan atas, sehingga memudahkan developer men-debug kode yang menggunakan elemen lapisan atas.

Artikel ini menjelaskan apa yang dimaksud dengan elemen lapisan atas, cara DevTools membantu memvisualisasikan konten lapisan atas untuk memahami dan men-debug struktur DOM yang berisi elemen lapisan atas, dan cara dukungan lapisan atas DevTools diterapkan.

Apa yang dimaksud dengan lapisan atas dan elemen lapisan atas?

Apa yang sebenarnya terjadi secara internal saat Anda membuka <dialog> sebagai modal? 🤔

Lapisan ini ditempatkan ke lapisan atas. Konten lapisan atas dirender di atas semua konten lainnya. Misalnya, dialog modal harus muncul di atas semua konten DOM lainnya, sehingga browser otomatis merender elemen ini di 'lapisan atas', bukan memaksa penulis untuk bertarung dengan z-index secara manual. Elemen lapisan atas muncul di atas elemen meskipun dengan indeks z tertinggi.

Lapisan atas dapat dijelaskan sebagai 'lapisan penyusunan tertinggi'. Setiap dokumen memiliki satu area pandang terkait dan, oleh karena itu, juga satu lapisan atas. Beberapa elemen dapat berada di dalam lapisan atas secara bersamaan. Jika hal itu terjadi, keduanya akan ditumpuk, yang terakhir di atas. Dengan kata lain, semua elemen lapisan atas ditempatkan dalam tumpukan last in, first out (LIFO) di lapisan atas.

Elemen <dialog> bukan satu-satunya elemen yang dirender browser ke lapisan atas. Saat ini, elemen lapisan atas adalah: popover, dialog modal, dan elemen dalam mode layar penuh.

Periksa implementasi dialog berikut:

<main>
  <button onclick="window.dialog.showModal();">Open Dialog</button>
</main>
<dialog id="dialog"></dialog>

Berikut adalah demo dengan beberapa dialog yang memiliki gaya yang diterapkan ke latar belakangnya (latar belakang dijelaskan di bawah):

Apa yang dimaksud dengan latar belakang?

Untungnya, ada cara untuk menyesuaikan konten di bawah elemen lapisan atas.

Setiap elemen di lapisan atas memiliki pseudo-elemen CSS yang disebut latar belakang.

Latar Belakang adalah kotak berukuran area pandang yang langsung dirender di bawah elemen lapisan atas. Pseudo-elemen ::backdrop memungkinkan Anda mengaburkan, menata gaya, atau sepenuhnya menyembunyikan semua yang terletak di bawah elemen jika elemen tersebut adalah elemen paling atas di lapisan atas.

Saat Anda membuat beberapa elemen modal, browser akan menggambar latar belakang tepat di bawah elemen tersebut yang paling depan dan di atas elemen layar penuh lainnya.

Berikut cara menata gaya latar belakang:

/* The browser displays the backdrop only when the dialog.showModal() function opens the dialog.*/
dialog::backdrop {
    background: rgba(255,0,0,.25);
}

Bagaimana cara menampilkan latar belakang pertama saja?

Setiap elemen lapisan atas memiliki latar belakang yang termasuk dalam kelompok lapisan atas. Latar belakang ini dirancang untuk tumpang-tindih satu sama lain, sehingga jika opasitas latar belakang tidak 100%, latar belakang di bawahnya akan terlihat.

Jika hanya latar belakang pertama di tumpukan lapisan atas yang perlu terlihat, Anda dapat melakukannya dengan melacak ID item di tumpukan lapisan atas.

Jika elemen yang ditambahkan bukan yang pertama di lapisan atas, fungsi yang dipanggil saat elemen dimasukkan ke lapisan atas akan menerapkan class hiddenBackdrop ke ::backdrop. Class ini dihapus saat elemen dihapus dari lapisan atas.

Lihat kode dalam contoh demo ini:

Desain dukungan lapisan atas di DevTools

Dukungan DevTools untuk lapisan atas membantu developer memahami konsep lapisan atas dan memvisualisasikan perubahan konten lapisan atas. Fitur ini membantu developer mengidentifikasi hal berikut:

  • Elemen di lapisan atas kapan saja dan urutannya.
  • Elemen di bagian atas stack kapan saja.

Selain itu, dukungan lapisan atas DevTools membantu memvisualisasikan posisi pseudo-elemen latar belakang di tumpukan lapisan atas. Meskipun bukan elemen hierarki, elemen ini memainkan peran penting dalam cara kerja lapisan atas dan dapat berguna bagi developer.

Dengan fitur dukungan lapisan atas, Anda dapat:

  1. Amati elemen mana yang berada di tumpukan lapisan atas kapan saja. Stack representasi lapisan atas berubah secara dinamis saat elemen ditambahkan atau dihapus dari lapisan atas.
  2. Lihat posisi elemen di tumpukan lapisan atas.
  3. Beralih dari elemen lapisan atas atau pseudo-elemen latar belakang elemen dalam hierarki ke elemen atau pseudo-elemen latar belakang dalam penampung representasi lapisan atas dan kembali.

Mari kita lihat cara menggunakan fitur ini.

Penampung lapisan atas

Untuk membantu memvisualisasikan elemen lapisan atas, DevTools menambahkan penampung lapisan atas ke hierarki elemen. Tag ini berada setelah tag </html> penutup.

Penampung ini memungkinkan Anda mengamati elemen di tumpukan lapisan atas kapan saja. Penampung lapisan atas adalah daftar link ke elemen lapisan atas dan latar belakangnya. Stack representasi lapisan atas berubah secara dinamis saat elemen ditambahkan atau dihapus dari lapisan atas.

Untuk menemukan elemen lapisan atas dalam hierarki elemen atau penampung lapisan atas, klik link dari representasi elemen lapisan atas di penampung lapisan atas ke elemen yang sama di hierarki elemen dan kembali.

Untuk beralih dari elemen penampung lapisan atas ke elemen hierarki lapisan atas, klik tombol tampilkan di samping elemen dalam penampung lapisan atas.

Berpindah dari link penampung lapisan atas ke elemen.

Untuk beralih dari elemen hierarki lapisan atas ke link di penampung lapisan atas, klik badge lapisan atas di samping elemen.

Berpindah dari elemen ke link penampung lapisan atas.

Anda dapat menonaktifkan badge apa pun, termasuk badge lapisan atas. Untuk menonaktifkan badge, klik kanan badge, pilih Setelan badge, lalu hapus centang di samping badge yang ingin disembunyikan.

Menonaktifkan badge.

Urutan elemen dalam tumpukan lapisan atas

Penampung lapisan atas menampilkan elemen seperti yang muncul dalam kelompok, tetapi dalam urutan terbalik. Bagian atas elemen stack adalah elemen terakhir dalam daftar elemen penampung lapisan atas. Artinya, elemen terakhir dalam daftar penampung lapisan atas adalah elemen yang saat ini dapat Anda gunakan untuk berinteraksi dalam dokumen.

Badge di samping elemen hierarki menunjukkan apakah elemen tersebut termasuk dalam lapisan atas dan berisi nomor posisi elemen dalam stack.

Dalam screenshot ini, tumpukan lapisan atas terdiri dari dua elemen, dengan elemen kedua berada di bagian atas tumpukan. Jika Anda menghapus elemen kedua, elemen pertama akan dipindahkan ke atas.

Urutan elemen dalam stack.

Latar belakang di penampung lapisan atas

Seperti yang disebutkan di atas, setiap elemen lapisan atas memiliki elemen pseudo CSS yang disebut latar belakang. Anda dapat menata gaya elemen ini, jadi sebaiknya periksa juga dan lihat representasinya.

Dalam hierarki elemen, elemen latar belakang berada sebelum tag penutup elemen yang menjadi bagiannya. Namun, di penampung lapisan atas, link latar belakang dicantumkan tepat di atas elemen lapisan atas yang terkait.

Posisi data sebelumnya latar belakang.

Perubahan pada hierarki DOM

ElementsTreeElement, class yang bertanggung jawab untuk membuat dan mengelola setiap elemen hierarki DOM di DevTools, tidak memadai untuk menerapkan penampung lapisan atas.

Untuk menampilkan penampung lapisan atas sebagai node dalam hierarki, kami menambahkan class baru yang membuat node elemen hierarki DevTools. Sebelumnya, class yang bertanggung jawab untuk membuat hierarki elemen DevTools melakukan inisialisasi setiap TreeElement dengan DOMNode, yang merupakan class dengan backendNodeId dan properti terkait backend lainnya. backendNodeId, pada gilirannya, ditetapkan di backend.

Node penampung lapisan atas, yang memiliki daftar link ke elemen lapisan atas, diperlukan untuk berperilaku sebagai node elemen hierarki biasa. Namun, node ini bukan node DOM 'sebenarnya' dan backend tidak perlu membuat node penampung lapisan atas.

Untuk membuat node frontend yang mewakili lapisan atas, kami menambahkan jenis node frontend baru yang dibuat tanpa DOMNode. Elemen penampung lapisan atas ini adalah node frontend pertama yang tidak memiliki DOMNode, yang berarti hanya ada di frontend dan backend tidak 'mengetahui'nya. Agar memiliki perilaku yang sama dengan node lain, kita membuat class TopLayerContainer baru yang memperluas class UI.TreeOutline.TreeElement yang bertanggung jawab atas perilaku node frontend.

Untuk mencapai penempatan yang diinginkan, class yang merender elemen akan melampirkan TopLayerContainer sebagai sibling berikutnya dari tag <html>.

Badge lapisan atas baru menunjukkan bahwa elemen berada di lapisan atas dan berfungsi sebagai link ke pintasan elemen ini di elemen TopLayerContainer.

Desain awal

Awalnya, rencananya adalah menduplikasi elemen lapisan atas ke penampung lapisan atas, bukan membuat daftar link ke elemen. Kami tidak menerapkan solusi ini karena cara pengambilan turunan elemen di DevTools. Setiap elemen memiliki pointer induk yang digunakan dalam mengambil turunan dan tidak mungkin memiliki beberapa pointer. Oleh karena itu, kita tidak dapat memiliki node yang diperluas dengan benar dan berisi semua turunan di beberapa tempat dalam hierarki. Secara umum, sistem tidak dibuat dengan mempertimbangkan sub-pohon duplikat.

Kompromi yang kami capai adalah membuat link ke node DOM frontend, bukan menduplikasi node tersebut. Class yang bertanggung jawab membuat link ke elemen di DevTools adalah ShortcutTreeElement, yang memperluas UI.TreeOutline.TreeElement. ShortcutTreeElement memiliki perilaku yang sama dengan elemen hierarki DOM DevTools lainnya, tetapi tidak memiliki node yang sesuai di backend dan memiliki tombol yang ditautkan ke ElementsTreeElement. Setiap ShortcutTreeElement ke node lapisan atas memiliki ShortcutTreeElement turunan yang ditautkan ke representasi elemen pseudo ::backdrop di hierarki DOM DevTools.

Desain awal:

Desain awal.

Perubahan Chrome DevTools Protocol (CDP)

Untuk menerapkan dukungan lapisan atas, perubahan pada Chrome DevTools Protocol (CDP) diperlukan. CDP berfungsi sebagai protokol komunikasi antara DevTools dan Chromium.

Kita perlu menambahkan hal berikut:

  • Perintah untuk dipanggil dari frontend kapan saja.
  • Peristiwa yang akan dipicu di frontend dari sisi backend.

CDP: Perintah DOM.getTopLayerElements

Untuk menampilkan elemen lapisan atas saat ini, kita memerlukan perintah CDP eksperimental baru yang menampilkan daftar ID node elemen yang berada di lapisan atas. DevTools memanggil perintah ini setiap kali DevTools dibuka atau saat elemen lapisan atas berubah. Perintahnya terlihat seperti berikut:

  # Returns NodeIds of the current top layer elements.
  # Top layer renders closest to the user within a viewport, therefore, its elements always
  # appear on top of all other content.
  experimental command getTopLayerElements
    returns
      # NodeIds of the top layer elements.
      array of NodeId nodeIds

CDP: Peristiwa DOM.topLayerElementsUpdated

Untuk mendapatkan daftar terbaru elemen lapisan atas, kita memerlukan setiap perubahan elemen lapisan atas untuk memicu peristiwa CDP eksperimental. Peristiwa ini memberi tahu frontend tentang perubahan yang kemudian memanggil perintah DOM.getTopLayerElements dan menerima daftar elemen baru.

Peristiwanya akan terlihat seperti berikut:

  # Called by the change of the top layer elements.
  experimental event topLayerElementsUpdated

Pertimbangan CDP

Ada beberapa opsi tentang cara penerapan dukungan CDP dari lapisan atas. Opsi lain yang kami pertimbangkan adalah membuat peristiwa yang akan menampilkan daftar elemen lapisan atas, bukan hanya memberi tahu frontend tentang penambahan atau penghapusan elemen lapisan atas.

Atau, kita dapat membuat dua peristiwa, bukan perintah: topLayerElementAdded dan topLayerElementRemoved. Dalam hal ini, kita akan menerima elemen dan harus mengelola array elemen lapisan atas di frontend.

Saat ini, peristiwa frontend memanggil perintah getTopLayerElements untuk mendapatkan daftar elemen yang diperbarui. Jika kita mengirim daftar elemen atau elemen tertentu yang menyebabkan perubahan setiap kali peristiwa dipicu, kita dapat menghindari satu langkah untuk memanggil perintah. Namun, dalam hal ini, frontend akan kehilangan kontrol atas elemen yang didorong.

Kami menerapkannya dengan cara ini karena, menurut kami, lebih baik jika frontend memutuskan kapan harus meminta node lapisan atas. Misalnya, jika lapisan atas diciutkan di UI atau pengguna menggunakan panel DevTools yang tidak memiliki hierarki elemen, tidak perlu mendapatkan node tambahan yang mungkin lebih dalam ke dalam hierarki.