Dukungan lapisan atas di Chrome DevTools

Alina Varkki
Alina Varkki

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, bagaimana DevTools membantu memvisualisasikan konten lapisan atas untuk memahami dan men-debug struktur DOM yang berisi elemen lapisan atas, dan bagaimana dukungan lapisan atas DevTools diimplementasikan.

Apa saja elemen lapisan atas dan lapisan atas?

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

Data tersebut ditempatkan di lapisan atas. Konten lapisan atas dirender di atas semua konten lainnya. Misalnya, dialog modal harus muncul di atas semua konten DOM lain, sehingga browser secara otomatis merender elemen ini di 'lapisan atas' alih-alih memaksa penulis untuk melawan indeks z secara manual. Elemen lapisan teratas muncul di atas elemen bahkan dengan indeks z tertinggi.

Lapisan atas dapat dijelaskan sebagai 'lapisan tumpukan 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. Ketika itu terjadi, mereka menumpuk di atas satu sama lain, yang terakhir di atas. Dengan kata lain, semua elemen lapisan atas ditempatkan dalam tumpukan masuk terakhir, keluar pertama (LIFO) di lapisan atas.

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

Periksa penerapan dialog berikut:

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

Berikut adalah demo dengan beberapa dialog yang menerapkan gaya ke tampilan latarnya (latar belakang dijelaskan di bawah):

Apa itu tampilan latar?

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

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

Tampilan Latar adalah kotak seukuran area pandang yang dirender langsung di bawah elemen lapisan atas. Elemen semu ::backdrop memungkinkan untuk menyamarkan, menata gaya, atau menyembunyikan semua yang ada di bawah elemen jika elemen tersebut adalah yang paling atas di lapisan atas.

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

Berikut cara menata gaya tampilan latar:

/* 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 tampilan latar pertama saja?

Setiap elemen lapisan atas memiliki tampilan latar milik tumpukan lapisan teratas. Latar belakang ini dirancang untuk saling tumpang tindih, jadi jika opasitas tampilan latar tidak 100%, tampilan latar di bawahnya akan terlihat.

Jika hanya tampilan latar 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 bagaimana konten lapisan atas berubah. Fitur ini membantu developer mengidentifikasi hal berikut:

  • Elemen di lapisan teratas kapan saja beserta urutannya.
  • Elemen di bagian atas tumpukan kapan saja.

Selain itu, dukungan lapisan atas DevTools membantu memvisualisasikan posisi elemen semu tampilan latar di tumpukan lapisan atas. Meskipun bukan elemen pohon, ini memainkan peran penting dalam cara kerja lapisan atas dan dapat berguna bagi pengembang.

Dengan fitur dukungan lapisan teratas, Anda dapat:

  1. Amati elemen mana yang ada di tumpukan lapisan teratas kapan saja. Tumpukan representasi lapisan teratas berubah secara dinamis saat elemen ditambahkan atau dihapus dari lapisan atas.
  2. Melihat posisi elemen dalam tumpukan lapisan teratas.
  3. Berpindah dari satu atau beberapa elemen lapisan atas elemen semu tampilan latar dalam hierarki ke elemen semu tampilan latar atau elemen semu tampilan latar dalam container 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. Elemen ini berada setelah tag </html> penutup.

Penampung ini memungkinkan Anda mengamati elemen di tumpukan lapisan teratas kapan saja. Penampung lapisan atas adalah daftar link ke elemen lapisan atas dan latar belakangnya. Tumpukan representasi lapisan teratas 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 dalam penampung lapisan atas ke elemen yang sama dalam hierarki elemen dan kembali.

Untuk melompat dari elemen penampung lapisan atas ke elemen hierarki lapisan atas, klik tombol buka di samping elemen dalam penampung lapisan atas.

Beralih dari link container lapisan teratas ke elemen.

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

Beralih dari elemen ke link container lapisan teratas.

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

Menonaktifkan badge.

Urutan elemen dalam tumpukan lapisan teratas

Penampung lapisan atas menampilkan elemen seperti yang muncul dalam tumpukan tetapi dalam urutan terbalik. Bagian atas elemen stack adalah yang terakhir dalam daftar elemen penampung lapisan atas. Ini berarti bahwa elemen terakhir dalam daftar container lapisan atas adalah elemen yang saat ini dapat berinteraksi dengan Anda dalam dokumen.

Lencana di samping elemen pohon menunjukkan apakah elemen tersebut termasuk dalam lapisan teratas dan berisi nomor posisi suatu elemen dalam tumpukan.

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

Urutan elemen dalam tumpukan.

Tampilan latar di penampung lapisan atas

Seperti yang disebutkan di atas, setiap elemen lapisan atas memiliki elemen semu CSS yang disebut tampilan latar. Anda dapat menata gaya elemen ini, sehingga berguna juga untuk memeriksanya dan melihat representasinya.

Dalam hierarki elemen, elemen tampilan latar berada sebelum tag penutup elemen yang memilikinya. Namun, dalam penampung lapisan atas, link tampilan latar dicantumkan tepat di atas elemen lapisan atas yang memilikinya.

Posisi tumpukan tampilan latar.

Perubahan pada hierarki DOM

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

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

Node penampung lapisan teratas, yang berisi daftar link ke elemen lapisan atas, perlu berperilaku sebagai node elemen hierarki reguler. Namun, node ini bukan node 'real' Node DOM dan backend tidak perlu membuat node penampung lapisan teratas.

Untuk membuat node frontend yang merepresentasikan 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, artinya hanya ada di frontend dan backend tidak 'mengetahui'. lebih lanjut. Agar memiliki perilaku yang sama seperti node lain, kami 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 seinduk berikutnya dari tag <html>.

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

Desain awal

Pada awalnya, rencananya adalah menduplikasi elemen lapisan atas ke dalam penampung lapisan atas, alih-alih membuat daftar tautan ke elemen. Kita tidak mengimplementasikan solusi ini karena cara pengambilan turunan elemen bekerja 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 pada pohon. Secara umum, sistem tidak dibuat dengan mempertimbangkan subtree duplikat.

Kompromi yang kita hadapi adalah membuat link ke node DOM frontend, bukan menduplikasi node tersebut. Class yang bertanggung jawab untuk 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 pada backend dan memiliki tombol yang menautkan ke ElementsTreeElement. Setiap ShortcutTreeElement ke node lapisan atas memiliki ShortcutTreeElement turunan yang ditautkan ke representasi elemen semu ::backdrop di hierarki DOM DevTools.

{i>Initial design<i} (Desain awal):

Desain awal.

Perubahan Protokol Chrome DevTools (CDP)

Untuk mengimplementasikan dukungan lapisan teratas, diperlukan perubahan pada Protokol Chrome DevTools (CDP). 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 ada 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, setiap perubahan pada elemen lapisan atas perlu dilakukan untuk memicu peristiwa CDP eksperimental. Peristiwa ini memberi tahu frontend tentang perubahan yang kemudian memanggil perintah DOM.getTopLayerElements dan menerima daftar elemen baru.

Peristiwa tersebut akan terlihat seperti berikut:

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

Pertimbangan CDP

Ada beberapa opsi terkait bagaimana dukungan CDP untuk lapisan atas dapat diterapkan. Opsi lain yang kami pertimbangkan adalah membuat peristiwa yang akan menampilkan daftar elemen lapisan atas, bukan hanya menginformasikan bagian 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 perlu 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 pemanggilan perintah. Namun, dalam kasus ini, frontend akan kehilangan kontrol atas elemen mana yang didorong.

Kami menerapkannya dengan cara ini karena, menurut kami, akan 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 bisa berada lebih dalam ke dalam hierarki.