SVG Reorder Elements
Taking manual control of the z-order
- svg
- meta
SVG Auto Reorder guesses the right draw order from area and proximity - and it's usually right. But "usually" isn't "always." When you have a composition where the stacking genuinely can't be inferred from shape size - a filled circle that must sit under linework, a highlight that has to be on top even though it's tiny - SVG Reorder is the manual override. You write the order, it obeys.
How it works
One required input: svg_string. Then order_rules_json (default []) is an array of {selector, order} pairs that assign each matching element a priority:
[
{"selector": "#background", "order": 0},
{"selector": ".shadow", "order": 1},
{"selector": ".main", "order": 2},
{"selector": "#highlights", "order": 3}
]
Elements matching .main render after (on top of) elements matching .shadow, which render on top of #background. Elements without a rule keep their relative position, sorted after the rule-matched ones - the tooltip sums it up: "Array of {selector, order} to specify drawing order." reverse_order (default false) flips the whole result, which is occasionally the exact fix you need and costs nothing to try.
The selector engine is the same one used across the pack's editing nodes - #id, .class, tag names, and [attr*=value] attribute-contains selectors (so [id*=bg] catches bg1, bg2, whatever). That means you can reorder by ID, by class, or by name fragment without knowing exact names.
Outputs: svg (reordered) and meta (JSON describing what was reordered and the new order - useful when you're scripting this across many SVGs).
When to reach for it
You reach for this when Auto Reorder almost works but a specific layer is wrong. Concretely: vectorize a cel, auto-reorder with renumbering, then run SVG Group Layout with labels to see the IDs. Now you know path5 is the background block and path2 is the foreground eyebrow. Write {"selector": "#path5", "order": 0} and it sinks to the bottom, done. It's also the node to use when you're building an SVG from scratch - every vector path is secretly a stack of layers, and this is how you specify that stack in plain text instead of by hand-editing XML.
Install
Part of the pack, install once:
cd ComfyUI/custom_nodes
git clone https://github.com/TJ16th/TJ_ComfyUI_Lineart2Vector.git
# restart ComfyUI
or ComfyUI Manager → search TJ_ComfyUI_Lineart2Vector. No models, no keys; dependencies are the standard ComfyUI stack (numpy, opencv, scipy, scikit-image) listed in requirements.txt. A bare clone-and-restart typically just works.
Where people get burned
The selector syntax is the main trap - a typo like # path0 (space) or a wrong class name matches nothing, and the node quietly leaves that element in its default position rather than erroring. Check the meta output; it tells you what matched. Second: order is relative priority, not an absolute file position - if you only assign orders to two of ten elements, the other eight keep their original relative order, and "where do they go?" is answered by "after the matched ones," which may surprise you. And remember, rules don't apply to descendants of a <g> unless the selector reaches them - if a path is nested in a group, target the group or use a selector that matches the path itself.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| svg_string | STRING | — | |
| order_rules_jsonopt | STRING | [] | Array of {selector, order} to specify drawing order |
| reverse_orderopt | BOOLEAN | false | Reverse entire order after applying rules |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| svg | STRING | — |
| meta | STRING | — |