Chrome 133 Supports DOM State-Preserving Move with moveBefore()
chromestatus.com
chromestatus.com
https://github.com/facebook/react/pull/32036
I'm not exactly sure what the developer experience of this would be, but I expect it would make Portals significantly more powerful and able to be hot-swapped into different containers without disrupting either their internal state or even things like loaded iFrames. I expect others will be experimenting heavily with this now that there's platform support.
https://github.com/facebook/react/issues/12247 (2018-2020) describes some of the use cases, with one partial solution being https://github.com/httptoolkit/react-reverse-portal - the conversation around caveats of these approaches would be entirely different now!
Iframes particularly have always been a pain point, as people often want to reparent them to move things around the DOM, but they always reload completely when you do so which causes all sorts of issues. This new API says it explicitly _doesn't_ reload iframes, so we'll be able to drop that caveat immediately (for supporting browsers, but hopefully Safari/FF will follow suit soon). Looks great!
This was brought up multiple times to the html spec authors, but no changes were made.
https://github.com/bigskysoftware/htmx/blob/master/CHANGELOG...
https://htmx.org/examples/move-before/
We initially asked for this new feature about two years ago and have worked with the Chrome team as they have implemented it. It is going to be a huge step forward for the web!
Next up — DOM parts and standardized signals, unified.
Then there's a direct line to built-in declarative reactive templating: https://github.com/WICG/webcomponents/issues/1069
You can do a lot better just checking if the template that/s rendering to a spot in the DOM is the same or different from the previous template. If it's the same, just update the bindings from the template, if it's different re-render the whole thing.
That's simpler and faster, but the one thing it leaves out is stateful reordering of lists. So you can have a specific re-ordering code path, which is simpler than a full VDOM, but if you want to preserve state like moveBefore() does, even that reordering gets pretty complicated because you can only preserve state for one contiguous range of nodes that you don't actually move - instead you move all the other nodes around them. moveBefore() just eliminates all that extra complexity.
There's also a couple of standards issues open for native reordering of siblings, like reorderChildren(). That would eliminate the re-ordering code completely.
vdom is necessary in react to abstract the view from the platform so it can be represented by react-dom and react-native[-x] bridges.
Again, fine, but I personally prefer a vibrant web platform that evolves to meet the needs of web developers.
My only intent was to point out another function of the vdom being discussed.
For WASM+WebGPU, I doubt it will ever be up to the same accessibility and feel that react-native-web gives. Just look at Flutter.
You'll be able to reorder items in a list while preserving focus, without reloading iframes, and keeping audio and video playing.
We have a draft PR for support in Lit, and will try to ship that as soon as possible.
[1] https://github.com/mozilla/standards-positions/issues/1053
No movement since its creation on October 10, 2024
> [stage 3] basically means "finished, pending editorial nit review---but since multiple implementations haven't happened yet, there's a reasonable chance that we'll discover something is broken, and need to fix the normative content
https://github.com/whatwg/meta/issues/336#issuecomment-24874...
The editor of the playground shows you the live DOM in its editor.
Would you mind sharing some if you are experienced with it?
Sure, this would theoretically be a backwards incompatible change. But if no one is using insertBefore without really meaning moveBefore, it's not a concern in practice.
I don't understand the need for this awkward API.
Ok, `otherParent.append(existingIframe)` reloads the iframe, but that's just a legacy behavior. Why not toggle the new behavior by calling `existingIframe.holdMyBeer()`? This way I could just continue using .prepend/.append/.before/.after et — which by the way support multiple elements at once, unlike moveBefore.
Ridiculous choice, but I'm not even surprised anymore.
Well, it's clear you didn't take the time to try. There are multiple threads on this and related topics, with inputs from all browser vendors.
This has been a high-priority standards request from framework and rendering library maintainers for many, many years. Chrome is not at all being ridiculous.
Parent - Moved Node
disconnect - connected
connected (Doc A) - connected (Doc B)
connected - disconnected
The last one is the most concerning one. Most of the top performing frameworks do child node reconciliation something like this https://github.com/WebReflection/udomdiff/blob/e58db3ad28b72.... Each node could be unmoved (no-op), new (disconnected), or moved from within the parent (connected). Now if one wants to leverage moveBefore each of these nodes needs to be checked for it's connection state.I know what it's for, I don't agree with the API itself. Read my third paragraph.
> [stage 3] basically means "finished, pending editorial nit review---but since multiple implementations haven't happened yet, there's a reasonable chance that we'll discover something is broken, and need to fix the normative content
https://github.com/whatwg/meta/issues/336#issuecomment-24874...
This is not one of them.
I'm also thinking about situations where passing accessibility audits is nearly impossible and at odds with business and marketing insisting on complex designs that need to handle a lot of use cases on one page without making the user navigate to another page. Inevitably you find that there's a lot of display state in the DOM you can't serialize, and on the other end of the spectrum simple pages shouldn't need bloated JS web app frameworks just to maintain the state of a form.
For new projects I can see this significantly reducing the JS and CSS needed. Layout change isn't triggered just by screen width but user input state. Right now I see a lot of web projects with ugly CSS (relative positioning or sometimes mind bending stuff with grid/flex) and ugly JS doing error prone element attribute accounting that ultimately wouldn't be necessary if you could just restructure the DOM on the fly.
If you want an example for accessibility, since I think that's usually a big showstopper, many UI designs want z-indexy things such as context menus, tooltips, popups, notifications, modal forms, etc. that would not pass an audit because they're not properly contained within the structure of the page and technically live somewhere rattling around loosely in the <body> with a ton of CSS applied to complete the illusion.
If, instead, you force the user to do things he doesn't want to do in order to get access to the things he wants to do, it's inevitable that the UI becomes frustrating, no matter how much care you put into it.
If your requirements are entirely minimum viable product functional and you don't mind your UI looking incredibly ugly, I agree it is easy.
- move embedded iframe to lightbox for “full screen” and back
- drag and drop of elements without resetting their state
- I’m very curious if it works with contenteditable and/or input method editors. The specifics here are complex so I’m guessing it won’t work, but if it does it will unlock a new bag of tricks for dealing with various problems one encounters when building a rich editor like Notion
Presumably this would also preserve the state of animations, such as GIFs and objects with embedded animated documents (like SVG). With current methods these get reset (along with the already mentioned video state) which break the illusion of an element being transported elsewhere when the original can't be just literally moved.
Could recreate that famous old Mac OS X demo where a video keeps playing while minimized
https://fingswotidun.com/tests/appendNode/
It's interesting that they added new functions to support the new (essentially correct) behaviour. I guess there are people out there that have used moving nodes as a way to delete hidden state.
Much is being made of how it will impact client libraries in other threads, but it's actually driving changes from the server which is most helped by this seemingly simple feature.
To make this real, imagine that you are connected to a collaborative (realtime multi-user) app and someone else drags to reorder an item in a list. Let's say that item has a text box that you're typing into. In today's browsers, all but the most clever implementations will clobber your changes. When this drops, the item you're typing into should be able to be programmatically moved to a different location in the DOM and you won't even lose focus.
That's a big freaking deal that makes server-rendered systems like StimulusReflex, LiveView, Hotwire and HTMX even more desirable options compared to SPAs.
I expect this and the View Transition API to have massive implications for the way libraries are written. And hopefully positive ones. Allowing libraries to "use the platform" more closely