永続的な最上位レイヤの UI

ウェブ機能: moveBefore()

appendChild() や insertBefore() などの従来の方法を使用して、DOM 内で開いている <dialog>、popover、または全画面表示要素を移動すると、ブラウザは暗黙的に要素を DOM から削除して再挿入します。この削除により状態がリセットされ、開いているモーダル、ポップオーバー、全画面表示の要素が突然閉じられます。

ユーザー エクスペリエンスを中断したり、最上位要素を閉じたりせずに最上位要素を再親化するには、代わりにアトミック moveBefore() API を使用します。

開いている最上位レイヤ要素の親を再設定する

moveBefore() は、移動するノードと、その前に挿入する参照ノード(または新しい親の末尾に追加する null)の 2 つの引数を取ります。

const newParent = document.getElementById('new-container');
const dialogElement = document.getElementById('my-dialog');

// MANDATORY: Use moveBefore to ensure the <dialog> or popover stays open.
// Passing null appends it to the end of newParent.
newParent.moveBefore(dialogElement, null);

代替戦略

moveBefore() はプログレッシブ エンハンスメントであるため、呼び出す前に機能検出を使用する必要があります。古いブラウザの場合は、従来の再親化にフォールバックする必要があります。

必須: サポートされていないブラウザの <dialog> 要素の場合、従来の移動ではダイアログが閉じます。移動後も開いたままにする必要がある場合は、移動後に手動で再度開く必要があります。

const targetParent = document.getElementById('target-container');
const popoverOrDialog = document.getElementById('my-top-layer-element');

// Check if moveBefore is supported
if ('moveBefore' in Element.prototype) {
  targetParent.moveBefore(popoverOrDialog, null);
} else {
  // Fallback: traditional move.
  // Note: This WILL close <dialog>, popover, and fullscreen elements.
  const wasOpen = popoverOrDialog.hasAttribute('open') || popoverOrDialog.matches(':popover-open');
  targetParent.insertBefore(popoverOrDialog, null);
  
  // Manually restore state if possible
  if (wasOpen && typeof popoverOrDialog.showModal === 'function') {
    popoverOrDialog.showModal();
  } else if (wasOpen && typeof popoverOrDialog.showPopover === 'function') {
    popoverOrDialog.showPopover();
  }
}