The clean, fast, and easy solutions posted as of the date of this answer are unsatisfactory. They are constructed over the flawed statement that SVG documents lack z order. Libraries are not necessary either. One line of code can perform most operations to manipulate the z order of objects or groups of objects that might be required in the development of an app that moves 2D objects around in an x-y-z space.
Z Order Definitely Exists in SVG Document Fragments
What is called an SVG document fragment is a tree of elements derived from the base node type SVGElement. The root node of an SVG document fragment is an SVGSVGElement, which corresponds to an HTML5 <svg> tag. The SVGGElement corresponds to the <g> tag and permits aggregating children.
Having a z-index attribute on the SVGElement as in CSS would defeat the SVG rendering model. Sections 3.3 and 3.4 of W3C SVG Recommendation v1.1 2nd Edition state that SVG document fragments (trees of offspring from an SVGSVGElement) are rendered using what is called a depth first search of the tree. That scheme is a z order in every sense of the term.
Z order is actually a computer vision shortcut to avoid the need for true 3D rendering with the complexities and computing demands of ray tracing. The linear equation for the implicit z-index of elements in an SVG document fragment.
z-index = z-index_of_svg_tag + depth_first_tree_index / tree_node_qty
This is important because if you want to move a circle that was below a square to above it, you simply insert the square before the circle. This can be done easily in JavaScript.
Supporting Methods
SVGElement instances have two methods that support simple and easy z order manipulation.
- parent.removeChild(child)
- parent.insertBefore(child, childRef)
The Correct Answer That Doesn't Create a Mess
Because the SVGGElement (<g> tag) can be removed and inserted just as easily as a SVGCircleElement or any other shape, image layers typical of Adobe products and other graphics tools can be implemented with ease using the SVGGElement. This JavaScript is essentially a Move Below command.
parent.insertBefore(parent.removeChild(gRobot), gDoorway)
If the layer of a robot drawn as children of SVGGElement gRobot was before the doorway drawn as children of SVGGElement gDoorway, the robot is now behind the doorway because the z order of the doorway is now one plus the z order of the robot.
A Move Above command is almost as easy.
parent.insertBefore(parent.removeChild(gRobot), gDoorway.nextSibling())
Just think a=a and b=b to remember this.
insert after = move above
insert before = move below
Leaving the DOM in a State Consistent With the View
The reason this answer is correct is because it is minimal and complete and, like the internals of Adobe products or other well designed graphics editors, leaves the internal representation in a state that is consistent with the view created by rendering.
Alternative But Limited Approach
Another approach commonly used is to use CSS z-index in conjunction with multiple SVG document fragments (SVG tags) with mostly transparent backgrounds in all but the bottom one. Again, this defeats the elegance of the SVG rendering model, making it difficult to move objects up or down in the z order.
NOTES:
- (https://www.w3.org/TR/SVG/render.html v 1.1, 2nd Edition, 16 August 2011)
3.3 Rendering Order Elements in an SVG document fragment have an implicit drawing order, with the first elements in the SVG document
fragment getting "painted" first. Subsequent elements are painted on
top of previously painted elements.
3.4 How groups are rendered Grouping elements such as the ‘g’ element (see container elements) have the effect of producing a temporary
separate canvas initialized to transparent black onto which child
elements are painted. Upon the completion of the group, any filter
effects specified for the group are applied to create a modified
temporary canvas. The modified temporary canvas is composited into the
background, taking into account any group-level masking and opacity
settings on the group.