~
moveBefore
?
New in Chrome 133 (which goes stable on Feb 4) is a new method to move an element around the DOM: Node.prototype.moveBefore
. While small in size, this method is a very big deal because it preserves the element’s state when moving them around! For example:
- Iframes remain loaded
- Active element remains focus
- Popovers, fullscreen, modal dialogs remain open
- CSS transitions and animations carry on
- …
~
Old vs new
The classic way of moving things around is to use Node.prototype.insertBefore
. When doing so the node that was “moved” reloads with its initial state.
document.querySelector('#classic').addEventListener('click', () => {
const $newSibling = getRandomElementInBody();
const $iframe = document.querySelector('iframe');
document.body.removeChild($iframe);
document.body.insertBefore($iframe, $newSibling);
});
Even if you leave out the call to removeChild
, the insertBefore
will still do that all by itself – even if the target is still connected to a parent. I’ve left it in to make what is going on behind the scenes more explicit.
The new way of moving elements around is to use moveBefore
. Syntax-wise the method is modeled after insertBefore
so that you can swap things out easily.
document.querySelector('#classic').addEventListener('click', () => {
const $newSibling = getRandomElementInBody();
const $iframe = document.querySelector('iframe');
document.body.moveBefore($iframe, $newSibling);
});
With moveBefore
the state of the moved element is preserved.
~
Demo
Here’s a demo that includes both approaches.
See the Pen DOM State-Preserving Move (Node.prototype.moveBefore) by Bramus (@bramus) on CodePen.
If your browser does not support moveBefore
, check out this video to see it in action. The YouTube embed – which is an iframe – keeps playing as the iframe gets moved around.
~
The effect on MutationObserver
and Web Components
If you have a MutationObserver
, using moveBefore
will – just like insertBefore
– generate two mutations: one for the removal and one for adding the element onto its new parent. This choise was made for compatibility reasons.
When using Web Components the connectedMoveCallback
method will fire if you have specified it. If you do not have specified a connectedMoveCallback
method, the regular disconnectedCallback
and connectedCallback
will fire (again for backwards compat reasons) with isConnected
being true
.
~
Browser Support
Browser support is limited to Chrome 133+ at the time of writing. Both Safari and Firefox have expressed (1, 2) their support for this new API.
You can feature detect availability of moveBefore
as follows:
if (!("moveBefore" in Element.prototype)) {
// Not supported
}
~
Spread the word
Feel free to reshare one of the following posts on social media to help spread the word:
~
🔥 Like what you see? Want to stay in the loop? Here's how:
however: https://caniuse.com/?search=moveBefore