VisualElements won't grow to fill space for some reason

(First of all, yes, I’ve read all the documentation and flex-box reference multiple times.)

I have two empty, plain VisualElement objects. Their parent is a simple container VisualElement with display:flex and flex-direction:column. In other words, I just want to stack two VisualElements on top of each other and have them fill all available space.

I’ve set the flex-grow of the child VisualElements each to 1 and the flex-shrink of each to 0. These elements are contained within a custom EditorWindow which contains no other elements, i.e. it’s:

parentFlexContainer (VisualElement, flex-direction:column)
flexItem1 (VisualElement, flex-grow:1, flex-shrink:0, width/height:auto)
flexItem2 (VisualElement, flex-grow:1, flex-shrink:0, width/height:auto)```

The width and height of flexItem1 and 2 are 'auto'.

Everything I understand about flex layout tells me that, given this hierarchy, flexItem1 and flexItem2 should fill the EditorWindow in such a way that they each take up half the vertical space of the window, i.e. the bounds should look like:

![5059865--497027--visualelementlayouts.png|427x749](upload://9EapDBoe8DJl6Wdo1afLNLF0OIP.png)

But they don't. Instead, they don't take up any space whatsoever, despite their flex-grow properties and width/height set to auto.

Is this a bug, or am I fundamentally misunderstanding flex layout?

It may be an issue with the parent not having any height. So on your parent style use this:

.stretch {
    position-type: absolute;
    position-left: 0;
    position-top: 0;
    position-right: 0;
    position-bottom: 0;
}

<VisualElement class="parent-container stretch">
    <VisualElement class="child1"></VisualElement>
    <VisualElement class="child2"></VisualElement>
</VisualElement>

Or just add the stretch styles into the parent css.

I always use that to make the equivalent of the HTML ‘body’ tag.

‘display: flex’, ‘flex-direction: column’ on the parent and ‘flex-grow: 1’ on both children should be enough. Remove all other settings such as width/height/shrink.

If it doesn’t work, try adding ‘align-items: stretch’ and ‘align-content: stretch’ on the parent too.

Somehow that worked, thank you. Unfortunately I was using this to try to resolve a more specific issue, which doesn’t seem to be remedied by it. Specifically, all I am trying to do is get an Image to align to the top of the EditorWindow. This image scales uniformly as the window is resized, which is ideal, but for some reason I can’t get the actual Image to be placed at the top of the window. Further, the bounds of the Image’s VisualElement don’t seem to be the same as the bounds of the image and that seems to be what causes the problem.

My original thinking was that I could place the Image as the top VisualElement in a flex container and put some spacer VisualElement below it, which, when setting flexGrow to 1 on the bottom element, should push the Image up to the top if the Image had a flexGrow of 0 and a flexShrink of 1. No luck, though.

Anyway, this sounds like a sufficiently different issue that I may make a new question for it. I really appreciate your help as this is another issue I have faced in many forms.

Are you using an Image tag or using background-image CSS? Using background-image should keep it inside.

I’m doing this all in code, and the image URL will regularly change so I couldn’t hard-code it in CSS (er, USS).

Your parentFlexContainer should also have flex-grow: 1. The children are trying to take up all available space, but the parent will have 0 height. This is because of the default align styles of the rootVisualElement.

Not sure If I should make a seperate post, but I am getting inconsistent behaviour between UIBuilder and my actual Editor Windows, which seems to be a bug related to the above question.

UIBuilder shows my correct flexbox setup, of a two column layout.

Parent is set to grow, both nested columns are set to grow.
Left coolumn has a list, also set to grow.

In UIBuilder it shows correctly.
In the editor window however nothing grows vertically to fit the window.

What it looks like in UIBuilder:

What it actually looks like:

Now when I look inside UIElementsDebugger, unity creates an unnamed “TemplateContainer” between my elements and the actual root container from my loaded UXML, which does not have grow on it, but we cannot set any properties on our actual root node (aka the “Heirarchy” is the root node in UIBuilder).

This template container shrinks on it’s own, and my elements inside it are trying to grow to it.
How do we work around it? How do we grow the template container?

Ok found a workaround.

TemplateElement comes from VisualElement uxml = visualTree.CloneTree();

So instead of doing root.add(uxml); which includes that TemplateConatiner, I had to iterate the children inside them and add only the children, as such:

VisualElement uxml = visualTree.CloneTree();
for(var i = 0; i < uxml.childCount; i++)
{
      root.Add(uxml.ElementAt(i));
}

Which bypasses the TemplateContainer root, and thus Flex-Grow now works.

1 Like

Erm. I discovered now that root.add also removes elements from the TemplateContainer (why? Bug or nonstandard behaviour?),

so the actual workaround had to be implemented like this:

VisualElement uxml = visualTree.CloneTree();
while(uxml.childCount > 0)
{
    root.Add(uxml.ElementAt(0));
}

I had the same issue a while ago. I asked why they couldn’t just remove it - https://discussions.unity.com/t/728653/7

They just need an option to not create one, or a better system to make cloned root elements instantiate in the correct place (like your solution, if I understand the reason for TemplateContainer existing correctly), or at least make it auto-expand its height.

I ended up making my entire app without using UXML at all because of this stuff. Just made everything in C# using MVC pattern, but you obviously want to use the new editor.

You can pass the element container to visualTree.CloneTree(root). This will create elements and add them without the creation of a TemplateContainer

9 Likes

This is not really clear reading the documentation. Especially since the example showed uses the setup creating the templatecontainer : https://docs.unity3d.com/2020.1/Documentation/Manual/UIE-LoadingUXMLcsharp.html (the example also doesn’t compile, btw)

I had a very similar issue to what everyone here is discussing.
In my case, the root element in UXMl/UI Builder was set to flex and grow to take up the whole editor window, however it didn’t work in the actual editor window.
Turned out that when the UXML is loaded into the editor using root.Add(UXML) or UXML.CloneTree(root) (or similar methods), all it’s children are actually populated into a new VisualElement sometimes called “TemplateConatiner”.
This “TemplateConatiner” is not set to grow (flexGrow). Just changing flexGrow style property for this element to the desired value is enough to replicate the behavior seen in the UI Builder editor window.

1 Like

If your instantiation code is like this:

root.Add(uxml.ElementAt(i));

Just add style to USS:

:root {
    flex-grow: 1;
    height: 100%;
    width: 100%;
}
2 Likes

It’s crazy that this is not a default logic, and that it is not documented anywhere that example showed in Unity documentation creates additional element under the hood

Still happens, by the way, took me several hours to figure why my layout is different in editor and in window

4 Likes

this comment was more useful than all the unity documentation xd

1 Like