...">

How to use z-index in svg elements?

I use SVG circles in my project like this,

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120"> <g> <g id="one"> <circle fill="green" cx="100" cy="105" r="20" /> </g> <g id="two"> <circle fill="orange" cx="100" cy="95" r="20" /> </g> </g> </svg> 

And I use z-index in the g tag to show the elements first. In my project, I only need to use the z-index value, but I cannot use z-index for my svg elements. I googled a lot, but found nothing regarding. So please help me use z-index in my svg.

Here is a DEMO.

+127
javascript jquery svg z-index
Jul 22 '13 at 11:38
source share
13 answers

Specification

In the specification of SVG 1.1, the rendering order is based on the order of the documents:

 first element -> "painted" first 

Link to SVG 1.1. Specification

3.3 Rendering Procedure

Elements in an SVG document fragment have an implicit drawing order, with the first elements in the SVG document fragment first “colored” . Subsequent elements are painted over previously painted elements.




Solution (cleaner faster)

You should put the green circle as the last object to draw. So swap the two elements.

 <svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120"> <!-- First draw the orange circle --> <circle fill="orange" cx="100" cy="95" r="20"/> <!-- Then draw the green circle over the current canvas --> <circle fill="green" cx="100" cy="105" r="20"/> </svg> 

Here is the fork of your jsFiddle .

Solution (alternative)

xlink:href use with the xlink:href attribute and as the id value of the element. Keep in mind that this may not be the best solution, even if the result seems good. With a little time, here is a link to the SVG 1.1 "use" Element specification.

Goal:

In order not to require the authors to modify the referenced document to add an identifier to the root element.

 <svg xmlns="http://www.w3.org/2000/svg" viewBox="30 70 160 120"> <!-- First draw the green circle --> <circle id="one" fill="green" cx="100" cy="105" r="20" /> <!-- Then draw the orange circle over the current canvas --> <circle id="two" fill="orange" cx="100" cy="95" r="20" /> <!-- Finally draw again the green circle over the current canvas --> <use xlink:href="#one"/> </svg> 



SVG 2 Notes

SVG 2 Specification is the next major version and still supports the above features.

3.4. Order of registration

Elements in SVG are located in three dimensions. In addition to their position on the x and y axes of the SVG viewport, SVG elements are also located on the z axis. The position on the z axis determines the order in which they are drawn .

Along the z axis, elements are grouped into summation contexts.

3.4.1. Setting the stack context in SVG

...

Stack contexts are conceptual tools used to describe the order in which elements should be drawn one above the other when rendering a document, ...

+137
Aug 14 '14 at 7:23
source share

Try to invert #one and #two . Look at this fiddle: http://jsfiddle.net/hu2pk/3/

Update

In SVG, the z-index is determined by the order in which the element appears in the document . You can also take a look at this page if you want: https://stackoverflow.com/a/167458/

+28
Jul 22 '13 at 11:44
source share

As others have said, z-index is determined by the order in which an element appears in the DOM. If manually reordering html is not an option or would be difficult, you can use D3 to reorder SVG groups / objects.

Use D3 to Update DOM Order and Simulate Z-Index Functionality

Update SVG Element Z-Index with D3

At the most basic level (and if you are not using identifiers for anything else), you can use element identifiers as a replacement for z-index and reorder them. On top of that, you can pretty much let your imagination go crazy.

Code snippet examples

 var circles = d3.selectAll('circle') var label = d3.select('svg').append('text') .attr('transform', 'translate(' + [5,100] + ')') var zOrders = { IDs: circles[0].map(function(cv){ return cv.id; }), xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }), yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }), radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }), customOrder: [3, 4, 1, 2, 5] } var setOrderBy = 'IDs'; var setOrder = d3.descending; label.text(setOrderBy); circles.data(zOrders[setOrderBy]) circles.sort(setOrder); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 100"> <circle id="1" fill="green" cx="50" cy="40" r="20"/> <circle id="2" fill="orange" cx="60" cy="50" r="18"/> <circle id="3" fill="red" cx="40" cy="55" r="10"/> <circle id="4" fill="blue" cx="70" cy="20" r="30"/> <circle id="5" fill="pink" cx="35" cy="20" r="15"/> </svg> 

Main idea:

  1. Use D3 to select SVG DOM elements.

     var circles = d3.selectAll('circle') 
  2. Create some array of z-indices with a 1: 1 ratio with your SVG elements (which you want to reorder). The Z-index arrays used in the examples below are identifiers, x & y position, radii, etc.

     var zOrders = { IDs: circles[0].map(function(cv){ return cv.id; }), xPos: circles[0].map(function(cv){ return cv.cx.baseVal.value; }), yPos: circles[0].map(function(cv){ return cv.cy.baseVal.value; }), radii: circles[0].map(function(cv){ return cv.r.baseVal.value; }), customOrder: [3, 4, 1, 2, 5] } 
  3. Then use D3 to bind your z-indices to this selection.

     circles.data(zOrders[setOrderBy]); 
  4. Finally, call D3.sort to reorder the items in the DOM based on the data.

     circles.sort(setOrder); 



Examples

enter image description here

  • You can add by ID



enter image description here

  • With leftmost SVG on top



enter image description here

  • The smallest radii on top



enter image description here

  • Or specify an array to use z-index for a specific order - in my code example, the array [3,4,1,2,5] moves / reorders the 3rd circle (in the original HTML order) to be 1st in the DOM, 4th will be 2nd, 1st will be 3rd, and so on



+22
Apr 20 '16 at 7:01
source share

You can use use .

 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 120"> <g> <g id="one"> <circle fill="green" cx="100" cy="105" r="20" /> </g> <g id="two"> <circle fill="orange" cx="100" cy="95" r="20" /> </g> </g> <use xlink:href="#one" /> </svg> 

A green circle appears on top.
jsFiddle

+20
Oct 09 '14 at 11:36
source share

There is no z index for svgs. But svg determines which of your items are topmost in their position in the DOM. Thus, you can delete the object and put it at the end of svg, making it the "last rendered" element. Then it is visualized "from above."




Using jQuery:

 function moveUp(thisObject){ thisObject.appendTo(thisObject.parents('svg>g')); } 

using:

 moveUp($('#myTopElement')); 



Using D3.js:

 d3.selection.prototype.moveUp = function() { return this.each(function() { this.parentNode.appendChild(this); }); }; 

using:

 myTopElement.moveUp(); 



+9
Oct 24 '16 at 10:22
source share

Using D3:

If you want to add an element in reverse to data usage:

 .insert('g', ":first-child") 

Instead of .append

Add an item to the beginning of a group item

+8
Apr 22 '16 at 11:29
source share

As already mentioned, svgs is rendered in order and does not take into account z-index (for now). Maybe just send a specific item at the bottom of its parent so that it displays last.

 function bringToTop(targetElement){ // put the element at the bottom of its parent let parent = targetElement.parentNode; parent.appendChild(targetElement); } // then just pass through the element you wish to bring to the top bringToTop(document.getElementById("one")); 

Worked for me.

Refresh

If you have a nested SVG containing groups, you need to infer the element from its parentNode.

 function bringToTopofSVG(targetElement){ let parent = targetElement.ownerSVGElement; parent.appendChild(targetElement); } 

A nice feature of SVG is that each element contains its location, regardless of which group it is nested in: +1:

+8
Nov 15 '17 at 3:25
source share

Using D3:

If you want to reinsert each selected item, in order, as the last child of its parent.

 selection.raise() 
+7
Nov 14 '17 at 12:47 on
source share

Another solution would be to use divs that use zIndex to place SVG elements. Like here: https://stackoverflow.com/a/4646263

+5
Mar 06 '15 at 18:15
source share

We have 2019 already , and z-index is still not supported in SVG.

On the SVG2 support site in Mozilla, you can see that the state for z-index is not implemented.

You can also see error 360148 "Support for the z-index property for SVG elements" on the website (reported: 12 years ago).

But you have 3 possibilities in SVG:

  1. With element.appendChild(aChild);
  2. With parentNode.insertBefore(newNode, referenceNode);
  3. With targetElement.insertAdjacentElement(positionStr, newElement); (No support in IE for SVG)

Interactive demo

With all this 3 functions.

 var state = 0, index = 100; document.onclick = function(e) { if(e.target.getAttribute('class') == 'clickable') { var parent = e.target.parentNode; if(state == 0) parent.appendChild(e.target); else if(state == 1) parent.insertBefore(e.target, null); //null - adds it on the end else if(state == 2) parent.insertAdjacentElement('beforeend', e.target); else e.target.style.zIndex = index++; } }; if(!document.querySelector('svg').insertAdjacentElement) { var label = document.querySelectorAll('label')[2]; label.setAttribute('disabled','disabled'); label.style.color = '#aaa'; label.style.background = '#eee'; label.style.cursor = 'not-allowed'; label.title = 'This function is not supported in SVG for your browser.'; } 
 label{background:#cef;padding:5px;cursor:pointer} .clickable{cursor:pointer} 
 With: <label><input type="radio" name="check" onclick="state=0" checked/>appendChild()</label> <label><input type="radio" name="check" onclick="state=1"/>insertBefore()</label><br><br> <label><input type="radio" name="check" onclick="state=2"/>insertAdjacentElement()</label> <label><input type="radio" name="check" onclick="state=3"/>Try it with z-index</label> <br> <svg width="150" height="150" viewBox="0 0 150 150"> <g stroke="none"> <rect id="i1" class="clickable" x="10" y="10" width="50" height="50" fill="#80f"/> <rect id="i2" class="clickable" x="40" y="40" width="50" height="50" fill="#8f0"/> <rect id="i3" class="clickable" x="70" y="70" width="50" height="50" fill="#08f"/> </g> </svg> 
+4
Jan 28 '19 at 18:27
source share

Clean, quick, and easy solutions published as of the date of this answer are unsatisfactory. They are based on the erroneous assertion that the zG order is missing the z order. Libraries are not needed either. A single line of code can perform most operations to control the order of z objects or groups of objects that may be required when developing an application that moves 2D objects in XYZ space.

Order Z definitely exists in SVG document fragments

What is called an SVG document fragment is a tree of elements derived from a base node of type SVGElement. The root node of the SVG document fragment is SVGSVGElement, which corresponds to the HTML5 <svg> tag . SVGGElement matches the <g> tag and allows aggregation of child elements.

Having the z-index attribute in SVGElement, as in CSS, would have defeated the SVG rendering model. Sections 3.3 and 3.4 of the W3C Recommendation SVG v1.1, 2nd Edition, state that fragments of an SVG document (descendant trees from SVGSVGElement) are rendered using the so-called deep tree search. This scheme is in any sense of the word.

Z-order is essentially a shortcut to computer vision, avoiding the need for real 3D rendering with the complexities and computational requirements of ray tracing. A 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 the square above it, you simply insert a square in front of the circle. This can be easily done in JavaScript.

Support 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 mess up

Because SVGGElement ( <g> tag ) can be removed and pasted as easily as SVGCircleElement or any other shape, image layers typical of Adobe products and other graphical tools can be easily implemented using SVGGElement. This JavaScript is essentially a Move Below command.

 parent.insertBefore(parent.removeChild(gRobot), gDoorway) 

If the robot layer drawn as children of SVGGElement gRobot was before the doorway was drawn as children of SVGGElement gDoorway, the robot is now behind the doorway, because now the z-order of the doorway is one plus the z-order of the robot.

The Move Above team is almost as simple.

 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 

Leave the DOM in a view compatible state

The reason that this answer is correct is because it is minimal and complete, and, like the internal components of Adobe products or other well-designed graphic editors, it leaves the internal representation in a state that matches the representation created during rendering.

Alternative but limited approach

Another commonly used approach is to use CSS z-index in combination with several fragments of SVG documents (SVG tags) with an almost transparent background in all but the bottom. Again, this negates the elegance of the SVG rendering model, making it difficult to move objects up or down in z-order.




NOTES:

  1. ( https://www.w3.org/TR/SVG/render.html v 1.1, 2nd edition, August 16, 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 being “painted over” first. Subsequent elements are painted over previously painted elements.

    3.4 How groups are rendered Grouping elements such as the 'g element (see Container Elements) create a temporary separate canvas initialized with transparent black on which children are painted. After the group completes, all the filter effects specified for the group are used to create the modified temporary canvas. A modified temporary canvas is superimposed on the background, taking into account any masking parameters at the group level and opacity parameters in the group.

+3
Jun 12 '18 at 12:52
source share

Push the SVG element all the way so that its z-index is on top. SVG does not have a property called z-index. try below javascript to bring the element up.

 var Target = document.getElementById(event.currentTarget.id); var svg = document.getElementById("SVGEditor"); svg.insertBefore(Target, svg.lastChild.nextSibling); 

Purpose: element for which we need to bring it to the top svg: element container

+2
Jul 29 '18 at 9:12
source share

this is easy to do:

  1. clone your items
  2. sort cloned items
  3. replace items with cloned

 function rebuildElementsOrder( selector, orderAttr, sortFnCallback ) { let $items = $(selector); let $cloned = $items.clone(); $cloned.sort(sortFnCallback != null ? sortFnCallback : function(a,b) { let i0 = a.getAttribute(orderAttr)?parseInt(a.getAttribute(orderAttr)):0, i1 = b.getAttribute(orderAttr)?parseInt(b.getAttribute(orderAttr)):0; return i0 > i1?1:-1; }); $items.each(function(i, e){ e.replaceWith($cloned[i]); }) } $('use[order]').click(function() { rebuildElementsOrder('use[order]', 'order'); /* you can use z-index property for inline css declaration ** getComputedStyle always return "auto" in both Internal and External CSS decl [tested in chrome] rebuildElementsOrder( 'use[order]', null, function(a, b) { let i0 = a.style.zIndex?parseInt(a.style.zIndex):0, i1 = b.style.zIndex?parseInt(b.style.zIndex):0; return i0 > i1?1:-1; }); */ }); 
 use[order] { cursor: pointer; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="keybContainer" viewBox="0 0 150 150" xml:space="preserve"> <defs> <symbol id="sym-cr" preserveAspectRatio="xMidYMid meet" viewBox="0 0 60 60"> <circle cx="30" cy="30" r="30" /> <text x="30" y="30" text-anchor="middle" font-size="0.45em" fill="white"> <tspan dy="0.2em">Click to reorder</tspan> </text> </symbol> </defs> <use order="1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="0" y="0" width="60" height="60" style="fill: #ff9700; z-index: 1;"></use> <use order="4" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="50" y="20" width="50" height="50" style="fill: #0D47A1; z-index: 4;"></use> <use order="5" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="15" y="30" width="50" height="40" style="fill: #9E9E9E; z-index: 5;"></use> <use order="3" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="25" y="30" width="80" height="80" style="fill: #D1E163; z-index: 3;"></use> <use order="2" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="30" y="0" width="50" height="70" style="fill: #00BCD4; z-index: 2;"></use> <use order="0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sym-cr" x="5" y="5" width="100" height="100" style="fill: #E91E63; z-index: 0;"></use> </svg> 
0
Apr 05 '19 at 0:54
source share



All Articles