moveBefore() を使用して DOM ミューテーション中に状態を保持する

このたび、新しい moveBefore() DOM API が Chrome バージョン 133 で利用可能になりました。この API を使用すると、状態を失うことなく DOM 内で要素を簡単に移動できます。プロジェクトで使用する方法については、以下をご覧ください。

DOM ミューテーション中に状態が失われる

appendChild() API を使用して DOM に新しい要素を挿入していますか?多くの人がそうしていますが、DOM にすでに存在する要素で、この API や insertBefore()、または他の挿入 API を呼び出したことはありますか?そのような場合、まず要素を古い親から削除し、新しい親に再挿入することで、この操作が静かに行われることに気付いていない可能性があります。これは、1998 年に最初の DOM 標準ドラフトが導入されて以来、Document Object Model に remove プリミティブと insert プリミティブしかなかったためです。DOM 内の要素をある場所から別の場所に「移動」していると思う場合でも、実際には削除と挿入が行われています。

「移動」が実際には「削除して挿入」であるという事実は、通常、ユーザー エクスペリエンスに影響しません。たとえば、DOM 内で <p> を「移動」する場合、これらの 2 つのオペレーションは中断的な副作用を引き起こしませんが、重要な状態を保持する複雑なノード(<iframe> 要素、全画面表示の要素、CSS アニメーションなど)を移動する場合、暗黙的な「削除」オペレーションにより、さまざまな状態がリセットされます。

これにより、予想外の副作用が生じる可能性があります。

DOM ツリー内の移動を試してみると、状態保持デモ ウェブサイトでリセットされる状態を確認できます。次の例は、要素を親コンテナから別の親コンテナに移動する際の CSS アニメーションと <iframe> 状態のリセットを示しています。

この制限により、動的ユーザー エクスペリエンスの構築が困難になるか、不可能になる可能性があります。アプリケーションの状態が不可解にリセットされると、ユーザーはイライラして混乱します。JavaScript フレームワークの作成者は、この問題に関連するフロントエンド コードの再設計に膨大な時間を費やしたり、MorphDOM などの複雑なライブラリを作成したり、修正できない問題をハイライトするバグレポートに対応したりすることで、この問題の重荷を負っています。

新しい moveBefore() API

この問題を解決するため、DOM に新しいプリミティブ オペレーションを追加しました。これは「移動」プリミティブと呼ばれ、新しい moveBefore() DOM API を介してデベロッパーに公開されます。

moveBefore()insertBefore() と同じ引数を取りますが、DOM にすでに接続されているノードを削除して再挿入するのではなく、この新しい API は、ほとんどの状態をリセットせずにターゲット ノードを新しい親にアトミックに移動します。これにより、JavaScript デベロッパーは、動かせるアニメーション、iframe、全画面要素などを使用して、動的エクスペリエンスを構築できるようになりました。chrome://flags/#atomic-move 試験運用版フラグを有効にしてデモサイトにアクセスするか、2025 年 2 月 4 日にリリースされる Chrome バージョン 133 を使用して、この機能をご自身でお試しいただけます。

この新しいプリミティブにより JavaScript 作成者が実現できる動作の例を以下に示します。

  • ユーザーがウェブサイトを操作する際に、動画の再生状態を保持します(動画が <video> 要素または <iframe> 要素から提供されるかどうかに関係なく)。
  • DOM 内で移動するユーザー入力フィールドのフォーカスを保持する。
  • DOM に新しいコンテンツが追加または削除されたときに、アニメーションがスムーズに終了できるようにします。
  • 既存の DOM と新しいコンテンツを調整するための高忠実度モルフィング アルゴリズム。
  • モーダル ダイアログ、ポップオーバー、全画面要素を開いたままにします。

Google は、他のブラウザとともにこの API をウェブ プラットフォームに導入できるよう取り組んでおり、デベロッパーからの長年の要望に応え、ウェブ プラットフォームの大きなギャップを埋める API をデベロッパーの皆様に提供できることを楽しみにしています。


いつものように、Twitter または下記のコメント欄からご意見をお寄せください。バグは crbug.com/new に送信してください。