D3.js .join() DOM ordering with key functions
0 reputation · 23 Jun 2025, 03:33 UTC
0 reputation · 23 Jun 2025, 03:33 UTC
In D3 v6 and v7, the .join() method streamlines the enter-update-exit pattern. When a key function is provided to the data join, D3 matches data points to existing DOM elements based on the returned key value rather than the array index.
A critical design consideration arises when the order of the input data array changes between updates. While new elements are appended to the selection, it is unclear if .join() automatically reorders existing DOM elements to mirror the new sequence of the data array when a key function is utilized.
This behavior impacts visualizations where the DOM order determines the z-index (layering) of SVG elements or the sequence of CSS transitions.
.join() preserve the original DOM position of matched elements?34775 reputation · 23 Jun 2025, 04:39 UTC
No. In D3 v6 and v7, .join() does not reorder existing DOM elements when the input data array changes order, even when a key function is supplied. The resulting DOM order is not guaranteed to match the data array.
.join() is a convenience wrapper around the standard enter-update-exit pattern. It uses the key function to bind data by identity, but the underlying selection operations do not move existing nodes. Reordering the DOM is a separate concern that D3 delegates to the caller.
SVG z-index layering and CSS transition sequences depend on document order. If you re-sort or shuffle the data array between updates without reordering the DOM, the visual stacking and animation timing will reflect insertion history rather than the current data sequence.
Call .sort() on the selection after .join() to reposition DOM nodes so they match the data array. Use .order() only if the selection is already sorted and you need to sync the DOM to it.
const rects = svg.selectAll("rect")
.data(data, d => d.id);
rects.join(
enter => enter.append("rect"),
update => update
)
.sort((a, b) => data.indexOf(a) - data.indexOf(b));
To confirm this in your own code:
.join()..sort() and verify the DOM nodes shift to match the new array sequence.If you skip .sort(), treat DOM order as a record of insertion history, not a reflection of the current data order.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.