Unterstützung der obersten Ebene in den Chrome-Entwicklertools

Die Chrome DevTools unterstützen jetzt Elemente der obersten Ebene. So können Entwickler ihren Code, der solche Elemente verwendet, leichter debuggen.

In diesem Artikel erfahren Sie, was Elemente der obersten Schicht sind, wie Sie mit den DevTools die Inhalte der obersten Schicht visualisieren können, um die DOM-Struktur zu verstehen und zu debuggen, die Elemente der obersten Schicht enthält, und wie die Unterstützung der obersten Schicht in den DevTools implementiert ist.

Was sind die oberste Ebene und die Elemente der obersten Ebene?

Was passiert genau intern, wenn Sie ein <dialog> als modales Fenster öffnen? 🤔

Es wird in eine oberste Schicht eingefügt. Inhalte der obersten Ebene werden über allen anderen Inhalten gerendert. Wenn ein modales Dialogfeld beispielsweise über allen anderen DOM-Inhalten angezeigt werden soll, rendert der Browser dieses Element automatisch in einer „oberen Schicht“, anstatt die Autoren dazu zu zwingen, sich manuell mit dem Z-Index auseinanderzusetzen. Ein Element der obersten Ebene wird auch über einem Element mit dem höchsten Z-Index angezeigt.

Die oberste Schicht kann als „höchste Stapelschicht“ beschrieben werden. Jedem Dokument ist ein einzelner Ansichtsbereich und damit auch eine einzelne oberste Ebene zugeordnet. In der obersten Ebene können sich mehrere Elemente gleichzeitig befinden. In diesem Fall werden sie übereinander gestapelt, wobei der letzte oben liegt. Mit anderen Worten: Alle Elemente der obersten Ebene werden in der obersten Ebene in einem LIFO-Stapel (Last In, First Out) platziert.

Das <dialog>-Element ist nicht das einzige Element, das der Browser in einer oberen Ebene rendert. Derzeit sind das Pop-ups, modale Dialogfelder und Elemente im Vollbildmodus.

Sehen wir uns die folgende Dialogimplementierung an:

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

Hier ist eine Demo mit einigen Dialogen, auf deren Hintergründe Stile angewendet wurden (siehe unten):

Was ist ein Hintergrund?

Glücklicherweise gibt es eine Möglichkeit, die Inhalte unter dem Element der obersten Ebene anzupassen.

Jedes Element in der obersten Ebene hat ein CSS-Pseudoelement namens backdrop.

Der Hintergrund ist ein Feld in der Größe des Darstellungsbereichs, das direkt unter allen Elementen der obersten Ebene gerendert wird. Mit dem Pseudo-Element ::backdrop können Sie alles, was sich unter dem Element befindet, verdecken, stilisieren oder vollständig ausblenden, wenn es sich auf der obersten Ebene befindet.

Wenn Sie mehrere Elemente modal machen, zeichnet der Browser den Hintergrund direkt unter dem vordersten Element und über anderen Vollbildelementen.

So gestalten Sie einen Hintergrund:

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

Wie kann ich nur den ersten Hintergrund anzeigen lassen?

Jedes Element der obersten Ebene hat einen Hintergrund, der zu einem Stapel der obersten Ebene gehört. Diese Hintergründe sind so konzipiert, dass sie sich überlappen. Wenn die Deckkraft eines Hintergrunds also nicht 100 % beträgt, sind die darunter liegenden Hintergründe sichtbar.

Wenn nur der erste Hintergrund im Stapel der obersten Ebene sichtbar sein soll, können Sie dies erreichen, indem Sie die Artikel-IDs im Stapel der obersten Ebene im Auge behalten.

Wenn das hinzugefügte Element nicht das erste in der obersten Ebene ist, wendet die Funktion, die beim Einfügen des Elements in die oberste Ebene aufgerufen wird, eine hiddenBackdrop-Klasse auf das ::backdrop an. Diese Klasse wird entfernt, wenn das Element aus der obersten Ebene entfernt wird.

Sehen Sie sich den Code in dieser Beispieldemo an:

Design für die oberste Schicht in den Entwicklertools

Die DevTools-Unterstützung für die oberste Schicht hilft Entwicklern, das Konzept der obersten Schicht zu verstehen und zu visualisieren, wie sich die Inhalte der obersten Schicht ändern. Mit diesen Funktionen können Entwickler Folgendes ermitteln:

  • Die Elemente in der obersten Ebene und ihre Reihenfolge.
  • Das Element, das sich zu einem bestimmten Zeitpunkt ganz oben im Stapel befindet.

Außerdem hilft die Unterstützung der obersten Ebene in den DevTools, die Position des Pseudoelements „backdrop“ im Stapel der obersten Ebene zu visualisieren. Auch wenn es kein Baumelement ist, spielt es eine wichtige Rolle bei der Funktionsweise der obersten Schicht und kann für Entwickler nützlich sein.

Mit den Supportfunktionen der obersten Schicht können Sie:

  1. Beobachten Sie jederzeit, welche Elemente sich im Stapel der obersten Ebene befinden. Der Darstellungsstapel der obersten Ebene ändert sich dynamisch, wenn Elemente der obersten Ebene hinzugefügt oder daraus entfernt werden.
  2. Die Position des Elements im Stapel der obersten Ebene.
  3. Springen Sie im Baum vom Element oder vom Pseudoelement „Hintergrund“ der Elemente der obersten Ebene zum Element oder Pseudoelement „Hintergrund“ im Darstellungscontainer der obersten Ebene und zurück.

Sehen wir uns an, wie du diese Funktionen verwendest.

Container der obersten Ebene

Zur besseren Visualisierung der Elemente der obersten Ebene wird in den DevTools dem Elementbaum ein Container der obersten Ebene hinzugefügt. Es befindet sich nach dem schließenden </html>-Tag.

In diesem Container können Sie die Elemente im Stapel der obersten Schicht jederzeit beobachten. Der Container der obersten Ebene ist eine Liste von Links zu den Elementen der obersten Ebene und ihren Hintergründen. Der Darstellungsstapel der obersten Ebene ändert sich dynamisch, wenn Elemente der obersten Ebene hinzugefügt oder daraus entfernt werden.

Wenn Sie Elemente der obersten Ebene im Elementbaum oder im Container der obersten Ebene finden möchten, klicken Sie auf die Links von der Darstellung des Elements der obersten Ebene im Container der obersten Ebene zu demselben Element im Elementbaum und zurück.

Wenn Sie vom Containerelement der obersten Ebene zum Baumelement der obersten Ebene springen möchten, klicken Sie neben dem Element im Container der obersten Ebene auf die Schaltfläche Anzeigen.

Springen vom Containerlink der obersten Ebene zum Element.

Wenn Sie vom Baumelement der obersten Ebene zum Link im Container der obersten Ebene springen möchten, klicken Sie neben dem Element auf das Symbol Oberste Ebene.

Springen von einem Element zum Containerlink der obersten Ebene.

Sie können jedes Kennzeichen deaktivieren, auch das oberste. Wenn du die Badges deaktivieren möchtest, klicke mit der rechten Maustaste auf ein Badge, wähle Badge-Einstellungen aus und entferne die Häkchen bei den Badges, die du ausblenden möchtest.

Deaktivieren Sie das Symbol.

Reihenfolge der Elemente im Stapel der obersten Ebene

Der Container der obersten Ebene zeigt die Elemente so an, wie sie im Stapel erscheinen, aber in umgekehrter Reihenfolge. Das oberste Element des Stapels ist das letzte in der Elementliste des Containers der obersten Ebene. Das letzte Element in der Containerliste der obersten Ebene ist also das Element, mit dem Sie derzeit im Dokument interagieren können.

Die Symbole neben den Baumelementen geben an, ob die Elemente zur obersten Ebene gehören, und enthalten die Position eines Elements im Stapel.

In diesem Screenshot besteht der Stapel der obersten Schicht aus zwei Elementen, wobei sich das zweite Element oben im Stapel befindet. Wenn Sie das zweite Element entfernen, wird das erste an die Spitze verschoben.

Die Reihenfolge der Elemente im Stapel.

Hintergründe im Container der obersten Ebene

Wie bereits erwähnt, hat jedes Element der obersten Ebene ein CSS-Pseudoelement namens „backdrop“. Sie können dieses Element stylen. Daher ist es hilfreich, es zu prüfen und sich seine Darstellung anzusehen.

Im Elementbaum befindet sich ein Hintergrundelement vor dem schließenden Tag des Elements, zu dem es gehört. Im Container der obersten Ebene ist jedoch direkt über dem zugehörigen Element der obersten Ebene ein Hintergrundlink aufgeführt.

Stapelposition der Hintergründe.

Änderungen am DOM-Baum

ElementsTreeElement, die Klasse, die für das Erstellen und Verwalten einzelner DOM-Baumelemente in DevTools verantwortlich ist, war nicht ausreichend, um einen Container der obersten Schicht zu implementieren.

Um den Container der obersten Schicht als Knoten im Baum anzuzeigen, haben wir eine neue Klasse hinzugefügt, mit der DevTools-Baumelementknoten erstellt werden. Bisher hat die Klasse, die für das Erstellen des DevTools-Elementbaums verantwortlich ist, jede TreeElement mit einer DOMNode initialisiert. Dabei handelt es sich um eine Klasse mit einer backendNodeId und anderen backendbezogenen Eigenschaften. backendNodeId wird wiederum im Backend zugewiesen.

Der Containerknoten der obersten Ebene, der eine Liste von Links zu Elementen der obersten Ebene enthält, muss sich wie ein normaler Knoten des Baumelements verhalten. Dieser Knoten ist jedoch kein „echter“ DOM-Knoten und das Backend muss den Containerknoten der obersten Schicht nicht erstellen.

Um einen Frontend-Knoten zu erstellen, der die oberste Schicht darstellt, haben wir einen neuen Typ von Frontend-Knoten hinzugefügt, der ohne DOMNode erstellt wird. Dieses Containerelement der obersten Schicht ist der erste Frontend-Knoten ohne DOMNode. Das bedeutet, dass es nur im Frontend vorhanden ist und das Backend nichts davon weiß. Damit sich der Knoten genauso verhält wie andere Knoten, haben wir eine neue Klasse TopLayerContainer erstellt, die die Klasse UI.TreeOutline.TreeElement erweitert, die für das Verhalten von Frontend-Knoten verantwortlich ist.

Um die gewünschte Platzierung zu erreichen, wird TopLayerContainer von der Klasse, die ein Element rendert, als nächstes gleichgeordnetes Element des <html>-Tags angehängt.

Ein neues Symbol für die oberste Ebene gibt an, dass sich das Element in der obersten Ebene befindet, und dient als Link zum Verknüpfungselement dieses Elements im TopLayerContainer-Element.

Erster Entwurf

Ursprünglich war geplant, Elemente der obersten Ebene im Container der obersten Ebene zu duplizieren, anstatt eine Liste von Links zu den Elementen zu erstellen. Wir haben diese Lösung nicht implementiert, da die Abrufmethode der untergeordneten Elemente in DevTools nicht funktioniert. Jedes Element hat einen übergeordneten Verweis, der beim Abrufen von untergeordneten Elementen verwendet wird. Es ist nicht möglich, mehrere Verweise zu haben. Daher kann es keinen Knoten geben, der richtig maximiert wird und alle untergeordneten Elemente an mehreren Stellen im Baum enthält. Im Allgemeinen wurde das System nicht für doppelte Unterbäume entwickelt.

Wir haben uns entschieden, Links zu den DOM-Knoten des Front-Ends zu erstellen, anstatt diese Knoten zu duplizieren. Die Klasse, die für das Erstellen von Links zu Elementen in den Entwicklertools verantwortlich ist, ist ShortcutTreeElement, die die UI.TreeOutline.TreeElement erweitert. ShortcutTreeElement verhält sich wie andere DOM-Baumelemente in den DevTools, hat aber keinen entsprechenden Knoten im Backend und eine Schaltfläche, die zu einer ElementsTreeElement führt. Jeder ShortcutTreeElement-Knoten der obersten Ebene hat ein untergeordnetes ShortcutTreeElement-Element, das zur Darstellung eines ::backdrop-Pseudoelements im DOM-Baum der DevTools verlinkt ist.

Erster Entwurf:

Erster Entwurf.

Änderungen am Chrome-Entwicklertools-Protokoll (CDP)

Für die Implementierung der Unterstützung der obersten Schicht sind Änderungen am Chrome DevTools Protocol (CDP) erforderlich. CDP dient als Kommunikationsprotokoll zwischen DevTools und Chromium.

Wir müssen Folgendes hinzufügen:

  • Ein Befehl, der jederzeit über das Frontend aufgerufen werden kann.
  • Ein Ereignis, das vom Backend aus im Frontend ausgelöst wird.

CDP: DOM.getTopLayerElements-Befehl

Um die aktuellen Elemente der obersten Ebene anzuzeigen, benötigen wir einen neuen experimentellen CDP-Befehl, der eine Liste der Knoten-IDs der Elemente in der obersten Ebene zurückgibt. Dieser Befehl wird von den Entwicklertools aufgerufen, wenn die Entwicklertools geöffnet werden oder sich die Elemente der obersten Ebene ändern. Der Befehl sieht folgendermaßen aus:

  # 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: DOM.topLayerElementsUpdated-Ereignis

Damit wir eine aktuelle Liste der Elemente der obersten Ebene erhalten, muss jede Änderung der Elemente der obersten Ebene ein experimentelles CDP-Ereignis auslösen. Dieses Ereignis informiert das Frontend über die Änderung, das dann den Befehl DOM.getTopLayerElements aufruft und die neue Elementeliste empfängt.

Das Ereignis sieht so aus:

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

CDP-Hinweise

Es gab mehrere Möglichkeiten, wie die CDP-Unterstützung der obersten Schicht implementiert werden konnte. Eine weitere Option, die wir in Betracht gezogen haben, war die Erstellung eines Ereignisses, das die Liste der Elemente der obersten Ebene zurückgibt, anstatt das Frontend nur über das Hinzufügen oder Entfernen eines Elements der obersten Ebene zu informieren.

Alternativ könnten wir anstelle des Befehls zwei Ereignisse erstellen: topLayerElementAdded und topLayerElementRemoved. In diesem Fall würden wir ein Element empfangen und müssten das Array der Elemente der obersten Schicht im Frontend verwalten.

Derzeit ruft ein Frontend-Ereignis den Befehl getTopLayerElements auf, um eine Liste der aktualisierten Elemente abzurufen. Wenn wir jedes Mal, wenn ein Ereignis ausgelöst wird, eine Liste der Elemente oder ein bestimmtes Element senden, das die Änderung verursacht hat, können wir einen Schritt beim Aufrufen des Befehls vermeiden. In diesem Fall würde das Frontend jedoch die Kontrolle darüber verlieren, welche Elemente gepusht werden.

Wir haben es so implementiert, weil es unserer Meinung nach besser ist, wenn das Frontend entscheidet, wann Knoten der obersten Schicht angefordert werden. Wenn beispielsweise die oberste Schicht in der Benutzeroberfläche minimiert ist oder der Nutzer ein DevTools-Steuerfeld verwendet, das nicht den Elementbaum enthält, müssen die zusätzlichen Knoten, die sich weiter unten im Baum befinden könnten, nicht abgerufen werden.