How can I control the order of elements from CSS?
VisualElement.BringToFront gets overwritten in certain circumstances, like when a new child is added.
How can I control the order of elements from CSS?
VisualElement.BringToFront gets overwritten in certain circumstances, like when a new child is added.
Hi @Stardog !
Unfortunately, Z-index is not supported in USS. However, you can control the ordering of the elements via the hierarchy. The parents are drawn before the children.
As I understand it … the main reason for z-index to exist is for the many cases where parents CANNOT be drawn before the children.
A year later … z-index still not supported?
I agree z-index will be useful to have but I’m curious to understand your specific case where it is not an option to use the hierarchy for ordering. It’s not always fun or elegant but I’ve yet to hit a use case where I could not use the hierarchy in place of z-index but maybe I’ve just not hit hard enough problems yet. ![]()
I don’t know if this is a use case because I cannot switch to UIToolkit yet for this menu (as I need shader support), but I am certain it will.
When you click on one of the levels in this menu, the black background element will rotate on the Y axis, hide the level number, then flip back and grow until it covers the entire screen. I think if I had to put that element in front of the hierarchy, it will make everything else adjust around it (already had issue with another menu and reordering elements).
I would need to use z-index in this instance to make sure the black level background can cover all other UI.
I don’t know about the “rotate on the Y axis”, that won’t be possible yet with UI Toolkit in screen space. But having one of the level shapes expand to take up the entire screen shouldn’t be too bad. What you can do is spawn a new element that sits on top of the entire menu using Absolute position and have it grow, starting with the active item, to take up the full screen. It would be after the menu container in the hierarchy and so would take up the screen. You would actually still need to do this even with z-index, because growing your active item in relative position would displace the other level items and never actually go on top of them.
That’s true. Thanks for pointing that out.
I’m very surprised that you haven’t seen this. Maybe there’s another way of hacking around it that works (if so, I’d love to know it - I couldn’t google anything for it, I guess because z-index is so easy to use that no-one would need a hack?) It’s happened on most non-trivial CSS layouts I’ve made, especially any that are responsive, that work on multiple screen resolutions, that have user-supplied content, etc. How big is your set of test cases?
In my experience of CSS this is a feature that is frequently used in two classes of situation:
Classic example of 2 is the “two images that both overlap each other” trick (e.g. an image inside a border, where parts of the image overlap the border and other parts underlap it).
Classic example of 1 is fine-grained control of overflow - e.g. text that you need to be inside one element but overflow a different element. Or underflow one element and overflow another. USUALLY: because margins / padding are insufficient to allow the text to show through - which is USUALLY because text is labelling something, and labels conceptually need to float above graphics. (*)
My immediate case:
Root rect has a label at top
Child rect has a background color
when root object padding is small / child margins are small: the text gets cut off by the child rect
In CSS, this kind of thing isn’t common but happens sooner or later (at least once) on almost every project, but it’s trivial to solve: you z-index it and then move on, so quickly you probably forget you even needed it :).
(*) if z-index didn’t exist, we would have to stop using flexbox for text in most of the UI’s we wrote: all text would have to be manually positioned simply so that we could place the text in a separate layer above the graphics layer.
This is what I’m currently doing as a workaround. It so far requires almost 4x as much code to achieve in UIToolkit what would be needed if z-index were supported. It’s essentially the same as writing an IMGUI example: we have to manually position everything.
Screenshots are worth a million words.
All three cases you give above, from what I can get from just the description, I can easily implement them without z-index or absolute positioning. My point is that I feel like I’m missing the “edge” part of your edge-cases.
I don’t see how this is possible with z-index. You have to split either the border element or the image in two. Z-index doesn’t let you say “make half of this element go on top of something and the other half under that same something”. I’m going to assume you are, in fact, implying some sort of splitting, where the image element is split into two elements with one behind the border and the other above the border element. This is quite easy to do without z-index. You have your container element that has 3 children (image-background, border, image-foreground), where all children use Absolute position with left/top/bottom/right set to 0 (or some other offset). This makes them overlap each other like layers, producing what I think is your desired result?
This really requires a screenshot or a lot more specifics. If the “graphics” part that text attaches to are just elements, then, as I said in another post, you can always anchor a Label to an element. You can either use GCE on your target graphic element to “manually” position your Label or you can have your Label be a child of your graphic element but outside of its actual rect (overflow is visible by default) and then you get the “anchoring” for free. Neither approach requires z-index. “On top” just means “be the last child in the list of children”.
I don’t fully understand the problem here. Why would small padding/margin cause anything to be cut off?
I created something like what you describe, with zero parent padding and zero child margin. What am I missing?

I’d encourage you try the UI Builder for a bit. It’s all done with UI Toolkit without using z-index and only using Absolute position “layers” where that’s exactly what they are, layers. For example, the selection highlight blue border in the Canvas that can’t be part of the actual user document hierarchy and needs to float on top.
But again, I feel like I’m missing the finer details of your cases. Screenshots would help a lot.
As I understand there is still no way to set z-index yet.
The workaround proposed here, to change the hierarchy, is out of question if you are using flex layout. For example, you want your element to be in the middle when calculating layout, but visually be in front of other elements.
Use cases like this are countless. Overlays (tooltip, dropdown menu etc.), drag-drop, sticky header…
Even if you are using absolute positioning, you need to watch out for elements added after you changed the hierarchy, and manually put your element at the end of hierarchy again. I think the code loses declarative-ness like this.
For what it’s worth: implementing this correctly in Unity outside of UIToolkit (i.e. implementing it in UnityUI) took me something like 20 minutes (won’t work for UIToolkit - this was my own Flexbox re-implementation). But my point is: I don’t think there’s a technical reason why UIToolkit violates the specification here, it’s not hard to do correctly.
(when the UIToolkit team made posts about: following the official specification isn’t important because they (Unity) don’t understand the purpose of those features and never use them themselves … and they argue about my app design and say that it’s me who’s wrong for trying to use the features that are guarnteed, that are required, by the spec … I lost interest)
Don’t get us wrong. We understand the handiness of z-index, and would like to implement it eventually. It’s also been requested internally. In most cases, we managed to work around it otherwise, by relying on the hierarchy and absolute positioning. It is indeed cumbersome in some instances, but gets the job done. It’s just that we can’t tackle everything at the same time, and have to establish priorities. Some highly requested features don’t have a workaround and end up being prioritized over this one. Runtime support was one of those, for example.
If z-index was easy to implement, it would likely be implemented already. But it’s not. It requires significant changes in the way we create, update and remove the rendering commands. In order to achieve scalable updates when the UI changes, we need to track and maintain a lot of state. This tracking is very complex and contains many assumptions that were designed with a depth-first rendering order in mind. Some hierarchical state propagation would be broken if elements could suddenly be drawn in a different order. We may have to implement a kind of ghost hierarchy that the renderer would consume in a depth-first manner, we’ll see.
Btw, I pinged our product manager to make sure he gets your input about the priority of z-index.
If there is no way to make z-index work without sacrificing performance to the garbage rendering levels of UnityUI then it is better to make sure it comes with a warning you cant disable.
z-index, amongst other desired UI Toolkit updates, would increase my productivity for sure. I find it a bit off that it wasn’t planned for from the beginning.
Thanks for the explanation. I understand that there are difficulties implementing performant UI and apparently the architectural basis was developed not considering the z-index feature. But I want to ping that this is a crucial feature.
UIToolkit seems to fix layouting of controls compared to the UGUI by using flexbox - that’s great and it is a vast improvement. But the absence of the ability to sort controls on the screen the way you want is like a huge flaw in the design of UIToolkit. Like you are not even UI for mobile apps it is UI for games that presume UIs can be twisted and bent as hell.
You asked for the use case. I don’t know this is such a basic feature I struggle to make a concrete use case…
Suppose you want to create FTUE (first-time user experience). You need to blacken all UI except for one button or other visual element and on top of it draw a finger and a tooltip.
In UGUI we were doing this with Canvas and override sorting.
What I would do (if z-index existed): added a transparent black overlay, change the z-index of a said button, add a finger and a tooltip on top of it. How would you do that without a z-index? The only way I could think of (which is hacky as hell) is: hide the button using visibility: hidden, get the position of a button, clone the button, set absolute position, and set position same as hidden button. Z-index is such a straightforward thing and you need to have it.
It’s been some time since this thread was started. In the meantime we also internally identified other valid use cases. So I don’t think that the practicality of this feature needs to be debated anymore. The question is more about prioritization. Our new roadmap contains this card which covers z-index. Make sure to have a look at it and and report your interest: https://portal.productboard.com/xvo8kmgtx7tkv7desh8cyaj7/c/520-depth-ordering
Btw, z-index requires what we internally refer to as “out-of-order rendering”, which is closely related to the notion of stacking context in the CSS world. Rendering-wise, this is required to implement many other cool features, like subtree post-processing, subtree caching (variable rate subtree rendering), etc. So it’s definitely something that we keep on our radar.
Sounds great!
I’m surprised no one mentioned the most obvious use case: tabs!
Tabs have to ordered a certain way, but if they overlap, then we want the selected one to be rendered in front of the others, but we them to stay in the same position (changing the hierarchy would push them to the end of the layout).
See an example:

(The FORMS tab should remain the third, but be rendered in front of the OTHER tab)
I guess we can do some trickery with absolute positioning, a ghost element and some scripting, but having z-index available would make things way simpler… ![]()
Any news about z-index in USS?
At least give us the order layout property