Suporte à camada superior no Chrome DevTools

Alina Varkki
Alina Varkki

O Chrome DevTools está adicionando suporte para elementos da camada superior, facilitando a depuração do código que faz uso desses elementos pelos desenvolvedores.

Este artigo descreve o que são os elementos da camada superior, como o DevTools ajuda a visualizar o conteúdo da camada superior para entender e depurar a estrutura do DOM que contém elementos da camada superior e como o suporte à camada superior do DevTools é implementado.

Quais são os elementos da camada superior e da camada superior?

O que acontece internamente quando você abre um <dialog> como modal? 🤔

Ele é colocado em uma camada superior. O conteúdo da camada superior é renderizado sobre todos os outros conteúdos. Por exemplo, uma caixa de diálogo modal precisa aparecer sobre todos os outros conteúdos do DOM para que o navegador renderize automaticamente esse elemento em uma "camada superior" em vez de forçar os autores a lutar manualmente contra o Z-index. Um elemento da camada superior aparece sobre um elemento mesmo com o Z-index mais alto.

A camada de cima pode ser descrita como "a camada de empilhamento mais alto". Cada documento tem uma única janela de visualização associada e, portanto, também uma única camada superior. É possível haver vários elementos dentro da camada superior ao mesmo tempo. Quando isso acontece, elas se empilham umas sobre as outras, a última em cima. Em outras palavras, todos os elementos da camada superior são colocados em uma pilha último a chegar, primeiro a sair (LIFO, na sigla em inglês) na camada superior.

O elemento <dialog> não é o único elemento renderizado pelo navegador em uma camada superior. Atualmente, os elementos da camada superior são: popovers, caixas de diálogo modais e elementos em um modo de tela cheia.

Confira a seguinte implementação de caixa de diálogo:

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

Aqui está uma demonstração com algumas caixas de diálogo com estilos aplicados aos seus panos de fundo (panos de fundo descritos abaixo):

O que é um pano de fundo?

Felizmente, há uma maneira de personalizar o conteúdo abaixo do elemento da camada superior.

Cada elemento na camada superior tem um pseudoelemento CSS chamado pano de fundo.

O Pano de fundo é uma caixa do tamanho da janela de visualização que é renderizada imediatamente abaixo de qualquer elemento da camada superior. O pseudoelemento ::backdrop permite ocultar, aplicar estilo ou ocultar completamente tudo o que está abaixo do elemento quando ele é o mais alto na camada superior.

Quando você torna vários elementos modais, o navegador desenha o pano de fundo imediatamente abaixo do elemento mais frontal e por cima dos outros elementos de tela cheia.

Veja como definir o estilo de um pano de fundo:

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

Como mostrar apenas o primeiro pano de fundo?

Cada elemento da camada superior tem um pano de fundo que pertence a uma pilha de camada superior. Esses cenários foram criados para se sobrepor. Portanto, se a opacidade de um pano de fundo não for 100%, ele ficará visível.

Se apenas o primeiro pano de fundo na pilha da camada superior precisar ficar visível, é possível conseguir isso acompanhando os identificadores de itens na pilha da camada superior.

Se o elemento adicionado não for o primeiro na camada superior, a função chamada quando o elemento for colocado na camada superior aplicará uma classe hiddenBackdrop ao ::backdrop. Essa classe é removida quando o elemento é removido da camada superior.

Confira o código neste exemplo de demonstração:

Design de suporte de camada superior no DevTools

O suporte do DevTools para a camada superior ajuda os desenvolvedores a entender o conceito de camada superior e visualizar como o conteúdo da camada superior muda. Esses recursos ajudam os desenvolvedores a identificar o seguinte:

  • Os elementos na camada superior a qualquer momento e a ordem deles.
  • O elemento no topo da pilha em qualquer ponto.

Além disso, o suporte à camada superior do DevTools ajuda a visualizar a posição do pseudoelemento do pano de fundo na pilha da camada superior. Mesmo que não seja um elemento de árvore, ele desempenha um papel importante no funcionamento da camada superior e pode ser útil para desenvolvedores.

Com os recursos de suporte da camada superior, é possível:

  1. Observe quais elementos estão na pilha da camada superior a qualquer momento. A pilha de representação da camada superior muda dinamicamente à medida que elementos são adicionados ou removidos da camada superior.
  2. Veja a posição do elemento na pilha da camada superior.
  3. Ir dos elementos da camada superior pseudoelemento do pano de fundo na árvore até o elemento ou pseudoelemento do pano de fundo no contêiner de representação da camada superior e na parte de trás.

Vamos conferir como usar esses recursos.

Contêiner da camada superior

Para ajudar a visualizar os elementos da camada superior, o DevTools adiciona um contêiner de camada superior à árvore de elementos. Ele fica depois da tag de fechamento </html>.

Esse contêiner permite observar os elementos na pilha da camada superior a qualquer momento. O contêiner da camada superior é uma lista de links para os elementos da camada superior e seus panos de fundo. A pilha de representação da camada superior muda dinamicamente à medida que elementos são adicionados ou removidos da camada superior.

Para encontrar elementos da camada superior na árvore de elementos ou o contêiner da camada superior, clique nos links da representação do elemento da camada superior no contêiner da camada superior para o mesmo elemento na árvore de elementos e vice-versa.

Para pular do elemento do contêiner da camada superior para o elemento da árvore de camadas superior, clique no botão revelar ao lado do elemento no contêiner da camada superior.

Pulando do link do contêiner da camada superior para o elemento.

Para navegar do elemento da árvore de camadas superior até o link no contêiner da camada superior, clique no selo da camada superior ao lado do elemento.

Pulando de um elemento para o link do contêiner da camada superior.

Você pode desativar qualquer selo, incluindo o de camada superior. Para desativar os selos, clique com o botão direito do mouse em qualquer um deles, escolha Configurações dos selos e desmarque as marcas ao lado daqueles que você quer ocultar.

Desativando o selo.

Ordem dos elementos na pilha da camada superior

O contêiner da camada superior mostra os elementos como eles aparecem na pilha, mas na ordem inversa. O topo do elemento da pilha é a última na lista de elementos do contêiner da camada superior. Isso significa que o último elemento na lista de contêineres da camada superior é aquele com que você pode interagir no documento no momento.

Os selos ao lado dos elementos da árvore indicam se os elementos pertencem à camada superior e contêm o número da posição de um elemento na pilha.

Nesta captura de tela, a pilha da camada superior consiste em dois elementos, com o segundo elemento no topo da pilha. Se você remover o segundo elemento, o primeiro moverá para o topo.

A ordem dos elementos na pilha.

Panos de fundo no contêiner da camada superior

Como mencionado acima, cada elemento da camada superior tem um pseudoelemento CSS chamado pano de fundo. É possível definir o estilo do elemento. Portanto, é útil inspecioná-lo e ver sua representação.

Na árvore de elementos, um elemento de pano de fundo fica antes da tag de fechamento do elemento a que ele pertence. No entanto, no contêiner da camada superior, um link do pano de fundo é listado logo acima do elemento da camada superior ao qual pertence.

Posição da pilha de panos de fundo.

Alterações na árvore do DOM

A ElementsTreeElement, a classe responsável por criar e gerenciar elementos individuais da árvore do DOM no DevTools, não foi suficiente para implementar um contêiner da camada superior.

Para exibir o contêiner da camada superior como um nó da árvore, adicionamos uma nova classe que cria nós do elemento da árvore do DevTools. Anteriormente, a classe responsável por criar a árvore de elementos do DevTools inicializava cada TreeElement com um DOMNode, que é uma classe com backendNodeId e outras propriedades relacionadas ao back-end. backendNodeId, por sua vez, é atribuído no back-end.

O nó de contêiner da camada superior, que tem uma lista de links para elementos da camada superior, precisa se comportar como um nó de elemento de árvore regular. No entanto, esse nó não é um nó "real" o nó DOM e o back-end não precisam criar o nó de contêiner da camada superior.

Para criar um nó de front-end que represente a camada superior, adicionamos um novo tipo de nó de front-end que é criado sem um DOMNode. Esse elemento de contêiner da camada superior é o primeiro nó de front-end que não tem um DOMNode, o que significa que ele existe apenas no front-end e o back-end não "sabe". sobre isso. Para ter o mesmo comportamento que outros nós, criamos uma nova classe TopLayerContainer que estende a classe UI.TreeOutline.TreeElement, responsável pelo comportamento dos nós de front-end.

Para conseguir a posição desejada, a classe que renderiza um elemento anexa TopLayerContainer como o próximo irmão da tag <html>.

Um novo selo de camada superior indica que o elemento está na camada superior e serve como um link para o atalho no elemento TopLayerContainer.

Design inicial

Inicialmente, o plano era duplicar elementos da camada superior no contêiner da camada superior em vez de criar uma lista de links para os elementos. Não implementamos essa solução devido à forma como a busca dos filhos do elemento funciona no DevTools. Cada elemento tem um ponteiro pai usado para buscar filhos, e é impossível ter vários ponteiros. Portanto, não é possível ter um nó que se expanda e contenha todos os filhos corretamente em vários lugares da árvore. Em geral, o sistema não foi construído tendo em mente subárvores duplicadas.

O acordo que chegamos foi a criação de links para os nós DOM de front-end em vez de duplicar esses nós. A classe responsável por criar links para elementos no DevTools é ShortcutTreeElement, que estende o UI.TreeOutline.TreeElement. O ShortcutTreeElement tem o mesmo comportamento que outros elementos da árvore do DOM do DevTools, mas não tem um nó correspondente no back-end e tem um botão que direciona para uma ElementsTreeElement. Cada ShortcutTreeElement no nó da camada superior tem um ShortcutTreeElement filho que se vincula à representação de um pseudoelemento ::backdrop na árvore do DOM do DevTools.

Design inicial:

Design inicial.

Mudanças no protocolo do Chrome DevTools (CDP)

Para implementar o suporte à camada superior, é necessário fazer mudanças no protocolo do Chrome DevTools (CDP). O CDP atua como um protocolo de comunicação entre o DevTools e o Chromium.

Precisamos adicionar o seguinte:

  • Um comando para chamar do front-end a qualquer momento.
  • Um evento a ser acionado no front-end no lado do back-end.

CDP: comando DOM.getTopLayerElements

Para mostrar os elementos atuais da camada superior, precisamos de um novo comando experimental do CDP que retorne uma lista de IDs de nó dos elementos que estão na camada superior. O DevTools chama esse comando sempre que é aberto ou quando os elementos da camada superior mudam. O comando se parece com isto:

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

Para ter a lista atualizada dos elementos da camada superior, precisamos de cada alteração desses elementos para acionar um evento experimental de CDP. Esse evento informa o front-end sobre a mudança, que chama o comando DOM.getTopLayerElements e recebe a nova lista de elementos.

O evento é semelhante ao seguinte:

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

Considerações sobre o CDP

Havia várias opções de como implementar o suporte ao CDP da camada superior. Outra opção que consideramos foi criar um evento que retornasse a lista dos elementos da camada superior, em vez de apenas informar o front-end sobre a adição ou remoção de um elemento da camada superior.

Como alternativa, podemos criar dois eventos em vez do comando: topLayerElementAdded e topLayerElementRemoved. Nesse caso, receberíamos um elemento e precisaríamos gerenciar a matriz dos elementos da camada superior no front-end.

No momento, um evento de front-end chama o comando getTopLayerElements para receber uma lista de elementos atualizados. Se enviarmos uma lista de elementos ou um elemento específico que causou a mudança sempre que um evento for acionado, poderíamos evitar uma etapa de chamar o comando. No entanto, nesse caso, o front-end perderia o controle sobre quais elementos são enviados.

Implementamos isso dessa forma porque, em nossa opinião, é melhor que o front-end decida quando solicitar nós da camada superior. Por exemplo, se a camada superior estiver recolhida na IU ou o usuário estiver usando um painel do DevTools que não tem a árvore de elementos, não haverá necessidade de obter os nós extras que poderiam estar mais profundos na árvore.