Question: Is it possible for visual element to match size of it's children? (wrap content)

Dear Unity Community,

I’ve been trying the UI Toolkit and it’s all fine but I’ve been unable to make elements match width of their children.

If I set the parent’s width and height to auto, only the height is correct, but the width is always stretched to all available space instead of matching it’s children’s width.

I am able to achieve what I want here Playground | Yoga by just setting the parent element’s width to auto instead of a fixed amount.

Do you know if the same thing is possible in Unity’s UI toolkit?


Kind regards,

Adam

Hmm, seems to work by setting the parent’s position absolute, so I guess the question is answered.

Setting the parent’s position to absolute, means it get removed from the parent’s parent flex layouting. To control how flex handles the size of children along the cross-axis (width for a column direction, height for flex-direction: row), you can use 2 different properties:
align-items: set on a parent, it defaults to stretch, so children will take all the available space of the parent’s container. setting align-items to flex-start, center, or anything else than stretch will give you want you want.
align-self: set on a child, it will override how the parent assign size along the cross axis.

Remember that your root element of your uxml eventually gets added to an already existing hierarchy so itself gets driven by its parent’s layout parameters.

Hope that helps

Sorry, but I think you misunderstood the question. The op wanted to give dynamic size to the parent based on the size of its children, not the other way around. So removing the element from the influence of its parent is the valid answer.

2 Likes

Re-reading my answer, you’re right, it was a bit obtuse.

Sometimes you still need want your overall to be layout done by the parent and setting position: absolute is not the way to go. In these cases, setting align-self to center or anything else than stretch on this uxml root would give the desired result, as your width would be driven by the children sizes and not by the parent’s own width.
Setting align-items on the element that will end up being this uxml root parent would do the trick as well.

2 Likes

Thank you for responding @uMathieu and apologies for a necro-bump. I’ve plastered this entire code sample with align-self: flex-start;, but no luck - the orange (well, orange-ish) container is wider than its children. Did I miss something?

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <ui:VisualElement name="FixedWidthParent" style="background-color: rgba(0, 0, 0, 0); width: 470px; align-self: flex-start; align-items: flex-start;">
        <ui:VisualElement name="Root" style="background-color: rgb(180, 135, 16); flex-direction: row; flex-wrap: wrap; align-self: flex-start; align-items: flex-start;">
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
            <ui:VisualElement name="Entry" style="background-color: rgb(197, 55, 55); width: 64px; height: 64px; border-left-color: rgb(32, 136, 231); border-right-color: rgb(32, 136, 231); border-top-color: rgb(32, 136, 231); border-bottom-color: rgb(32, 136, 231); border-right-width: 2px; border-left-width: 2px; border-top-width: 2px; border-bottom-width: 2px; align-self: flex-start;" />
        </ui:VisualElement>
    </ui:VisualElement>
</ui:UXML>

I feel like I’m going to have to use GeometryChangedEvent, but I’m hoping I just misunderstood something.

ChatGPT suggested I use width: fit-content;. Little did it know that it is not a thing in USS - got a Trying to read value of type Dimension while reading a value of type Enum error when manually specifying in UXML.

Late June bump… I see that @JuliaP_Unity is quite active in this subforum, maybe they have got an idea?

August bump. Let’s see if pinging @uDamian will land me in trouble.

You’ve defined its width to be 470px, you get 470px, what else did you expect?

You have 8 items of 64px width, that makes 512px width, but it’s limited by this 470px container. So, root cannot be larger than 470px. If you set FixedWidthParent to >= 512px for example1024 then root will get the proper 512px width.

I don’t understand anything I just told you what I see.

Yes, that is precisely the problem, so please, can you stop spamming the thread if you don’t understand the matter?

I’ll clean up my desperate attempts at guiding you as they don’t add value other than making it harder to reach the actual question.

flex-wrap: no-wrap