Hi Creators!
We are excited to announce new flex features for UIListLayout, available now in a Studio Beta!
Flex allows your UI content to effortlessly fill a dynamically-sized UI container using these new features:
- Multiline wrapping
- Growing items to fill empty space / shrinking items if they don’t fit
- Distributing empty space between elements
- Custom per-item line alignment options
Our goal is to make authoring UI across platforms, screen resolutions and aspect ratios much more seamless. Ideally, you should only need to create a single UI that looks amazing everywhere.
Flex allows you to accomplish this goal by allowing your content to grow (on desktop screens ) or shrink (on mobile ) to best fit on the user’s display.
Enabling the Beta
To enable this beta in Roblox Studio, follow these simple steps:
-
Open Roblox Studio and navigate to the “File” menu
-
Click on “Beta Features”
-
Enable the “UIListLayout Flex Features” option by checking the corresponding checkbox (see screenshot below) and press Save
-
Restart Roblox Studio when prompted
How to Use
Let’s look at a simple example of making a “spacer” element that fills empty space in a container.
To accomplish this, let’s create a UIListLayout containing two TextLabel
s and the “spacer” element, a Frame
. Set the TextLabel
s to a known size, such as 100 x 100px. Then, add a UIFlexItem component to the spacer Frame
.
So we have this setup:
Now, set the UIFlexItem.FlexMode = Fill
so that the spacer fills the remaining space. If you now resize the parent container, notice that the spacer fills up the extra horizontal space between the two TextLabel
s:
Shop Example
Here’s an example of a shop layout that uses the new flex features:
Notice that the user can access all the shop items for both small and large screens (with scrolling). On small screens, it’s also important to make sure the text isn’t shrunk too small to read, and buttons aren’t too small to tap on.
Here’s how this UI would look on some different mobile and desktop screens:
Here is the instance tree for this example, with the Flex instances highlighted:
And here are some highlights of the new Flex features we used:
- The ScrollingFrame has a
UIListLayout
component withHorizontalFlex
=Fill
andVerticalFlex
=Fill
. This tells each item in the list to grow horizontally and vertically to fit the container, if there is room. - The
UIListLayout
hasWraps
=true
which allows the items to take up multiple lines. - The icons have a
UIFlexItem
component withFlexMode
=Custom
andGrowFactor
=0.5
, so they grow half as much as the text (which hasGrowFactor=1
by default). - Each item has a
UISizeConstraint
withMinSize
of 120px in the Y direction, preventing the height of each item from being squished too much. - The shop is wrapped in a
ScrollingFrame
so that overflowing items can be scrolled to on small screens. - The
ScrollingFrame
hasAutomaticCanvasSize=Y
so that the canvas is sized to fit the content.
Here’s the placefile if you want to check it out in Studio!
Flex Terminology
- A flex container is a
GuiObject
with aUIListLayout
child. - The flex direction = fill direction is the direction specified by
UIListLayout.FillDirection
. - The cross direction is the direction perpendicular to the fill direction.
- A flex item is a
GuiObject
child in a flex container. - The basis size is the size of a flex item before stretching/growing is applied.
- The flex size is the size of a flex item after stretching/growing is applied.
- A flex line is a rectangle within a container containing multiple flex items. The line’s flex size is the width or height of the container, depending on
UIListLayout.FillDirection
. - The line’s cross size is determined by the largest item cross size in the line. The line’s rectangle always completely contains every item in the line.
Flex API
New UIListLayout
Properties
Property | Value Options | Description |
---|---|---|
UIListLayout.FillDirection: Enum.FillDirection |
Horizontal, Vertical (default) | The main axis aka flex direction of the layout. |
UIListLayout.Wraps: boolean |
False (default), True | If true, allows multiple content lines to be created perpendicular to the FillDirection. |
UIListLayout.HorizontalFlex: Enum.UIFlexAlignment |
None (default), Fill, SpaceAround, SpaceBetween, SpaceEvenly | If not None, distribute extra horizontal space using this strategy. |
UIListLayout.VerticalFlex: Enum.UIFlexAlignment |
None (default), Fill, SpaceAround, SpaceBetween, SpaceEvenly | If not None, distribute extra vertical space using this strategy. |
UIListLayout.ItemLineAlignment: Enum.ItemLineAlignment |
Automatic (default),Start, Center, End, Stretch | Cross-axis alignment of items within each line. |
New UIFlexItem
Instance
Property | Value Options | Description |
---|---|---|
UIFlexItem.FlexMode: Enum.UIFlexMode |
None (default), Grow, Shrink, Fill, Custom | How the parent GuiObject should grow or shrink with available space in the parent UIListLayout. |
UIFlexItem.ItemLineAlignment: Enum.ItemLineAlignment |
Automatic (default),Start, Center, End, Stretch | Cross-axis alignment of this specific item within the line. |
GrowRatio: float |
Positive number | If FlexMode=Custom, and there is empty space in the line, this is the weighting factor for distributing the empty space to this specific item in order to fill the line.This property is only shown in Studio if FlexMode=Custom. |
ShrinkRatio: float |
Positive number | If FlexMode=Custom, and there is overflow in the line, this is the weighting factor for shrinking this specific item in order to fit all items in 1 line. This property is only shown in Studio if FlexMode=Custom. |
New Enums
UIFlexAlignment
Enum. UIFlexAlignment Value | Description |
---|---|
None (default) | If set in the flex direction, set each item flex size to have GrowRatio=ShrinkRatio=0. This means that each item will not grow or shrink based on the container size. If set in the cross direction, set each line cross size to have GrowRatio=ShrinkRatio=0. So each line will not grow/shrink based on the container size. This is the default for backwards-compatibility with existing UIListLayout s. |
Fill | If set in the flex direction, set each item flex size to have an effective GrowRatio=ShrinkRatio=1: If set in the cross direction, stretch each line cross size to fill the container: |
SpaceAround | If set in the flex direction, distribute empty space between each item as padding. The start and end padding is half the between-element padding. If set in the cross direction, distribute empty space between each line using the same strategy. |
SpaceBetween | If set in the flex direction, distribute space between each item in the flex direction. The start and end padding is zero. If set in the cross direction, distribute empty space between each line using the same strategy. |
SpaceEvenly | If set in the flex direction, distribute space evenly between each item in the flex direction. The start and end padding is equal to the between-element padding. If set in the cross direction, distribute empty space between each line using the same strategy. |
ItemLineAlignment
Enum.ItemLineAlignment Value | Description |
---|---|
Automatic (default) | Follow the UIListLayout.HorizontalAlignment or UIListLayout.VerticalAlignment, depending on the flex direction. If HorizontalFlex/VerticalFlex=Fill for in the flex direction, choose “Stretch” line alignment. This is the default value for backwards-compatibility. |
Start | Align items within each line to the top for FillDirection.Horizontal or left for FillDirection.Vertical. |
Center | Align items in each line to the center of the line. |
End | Align items in each line to the bottom for FillDirection.Horizontal, or right for FillDirection.Vertical. |
Stretch | Fill entire line cross direction, overriding the original item cross size. |
UIFlexMode
Enum.UIFlexMode Value | Effective GrowRatio | Effective ShrinkRatio |
---|---|---|
None (default) | 0 | 0 |
Grow | 1 | 0 |
Shrink | 0 | 1 |
Fill | 1 | 1 |
Custom | UIFlexItem.GrowRatio |
UIFlexItem.ShrinkRatio |
Interaction with AutomaticSize
- If AutomaticSize is enabled for a UIListLayout child in the flex direction, this is interpreted as “automatic flex basis”. This is implemented by first calculating the minimum size of this item needed to contain its content, and setting this as the “flex basis” size. Then, we allow the item to further grow/shrink based on available space.
- If AutomaticSize is enabled for a UIListLayout child in the cross direction, this is interpreted as “automatic cross size”. The automatic cross size is calculated as the minimum size needed to contain all the child’s content in the cross direction after the flex size is determined.
Known Issues
-
Automatic Size isn’t supported for nested[Fixed]UIListLayout
s with flex features enabled. -
Flex-enabled[Fixed]UIListLayout
s may take multiple frames to update, depending on layout complexity.
Please note that the new Flex features are currently only available in Roblox Studio during the beta period, so these features aren’t active on the Roblox Client yet.
Thanks to @EGOTISMS @uiuxartist @Slim_Fandango for their contributions to this feature!
As always, please share any questions or feedback below — we’re eager to know what you think! Thank you.