UI Layout and Appearance

When you design a graphical user interface, you don't have to start from scratch. Roblox provides layouts, constraints, and appearance modifiers so you can create high-quality graphical user interfaces with minimal scripting.

Layouts allow you to organize GuiObjects quickly without having to manually set their size or position. They provide fast and intuitive behavior to structure and sort GuiObjects that frequently change.

Example inventory GUI menu made with a UIGridLayout

Constraints allow you to create minimum and maximum sizing limitations so your GuiObjects function properly within different screen sizes without overlapping or having large gaps between one another. You should typically use constraints for any GuiObject that you position and size with the scale value because scale causes the AbsoluteSize and AbsolutePosition of the object to responsively change to the size of a user's screen.

Label text constrained to a minimum and maximum size

Appearance modifiers give you further control over the appearance and aesthetics of your GuiObjects. For example, you can:


There are four types of layouts you can use within your experiences: UIListLayouts, UIGridLayouts, UITableLayouts, and UIPageLayouts.

To use a layout, you must insert it as a sibling to the applicable GuiObjects. If you use multiple layouts in the same parent GuiObject, only the first layout you added applies.


The UIListLayout positions sibling GuiObjects into a single vertical or horizontal row within their parent GuiObject while retaining each object's original size. Whenever you add or remove a sibling object, the UIListLayout repositions the list accordingly.

This layout is useful when you only want to order objects within a row or column, such as a dropdown menu.


The UIGridLayout positions sibling GuiObjects into a grid of uniform cells of the same size within their parent GuiObject. The UIGridLayout adds cells to a row one-by-one until the next cell doesn't fit, then it starts the next row. For further control, you can use the FillDirectionMaxCells property to set the maximum number of cells per row.

This layout is useful when you want to display objects within a fixed scale, such as a shop inventory.

By default, this layout positions GuiObjects from left-to-right and top-to-bottom in alphabetical order, but when you change the SortOrder property from Name to LayoutOrder, GuiObjects sort in ascending order where lower LayoutOrder values have more priority over higher values, and GuiObjects with equal values sort depending on the order in which you added them.


The UITableLayout positions sibling GuiObjects into rows, and any child GuiObjects of these sibling GuiObjects become columns. Each cell within a row has the same height while each cell within a column has the same width.

Unless you enable the FillEmptySpaceColumns or FillEmptySpaceRows property, the parent GuiObject determines the dimensions of the cells.

This layout is useful when you want further control over which items display where within a grid, such as a backpack inventory that separates items into categories like weapons and potions.


When you parent a UIPageLayout to a GuiObject, every sibling GuiObject of the UIPageLayout becomes a unique page that you can transition to through script. This layout is useful when you want to create menus with multiple pages, such as tutorials or character customization screens.

Switching Pages

After you create multiple pages within the UIPageLayout, you need to use scripting to transition from page to page. For example, the following code creates three separate pages, each with a different color frame that takes up the entire screen. Studio then transitions between the pages every two seconds, moving from page 1 to page 2 to page 3, then returning back from page 3 to page 2 to page 1:

1local screenGui = script.Parent
2local pageLayout = Instance.new("UIPageLayout")
3pageLayout.Parent = screenGui
5local page1 = Instance.new("Frame")
6page1.Size = UDim2.fromScale(1, 1)
7page1.BackgroundColor3 = Color3.fromRGB(25, 100, 100)
8page1.Parent = screenGui
10local page2 = Instance.new("Frame")
11page2.Size = UDim2.fromScale(1, 1)
12page2.BackgroundColor3 = Color3.fromRGB(100, 25, 100)
13page2.Parent = screenGui
15local page3 = Instance.new("Frame")
16page3.Size = UDim2.fromScale(1, 1)
17page3.BackgroundColor3 = Color3.fromRGB(100, 100, 25)
18page3.Parent = screenGui
20while true do
21 pageLayout:Next()
22 wait(2)
23 pageLayout:Next()
24 wait(2)
25 pageLayout:Previous()
26 wait(2)
27 pageLayout:Previous()
28 wait(2)

If you want to view pages while editing in Studio, you can use the Command Bar to navigate from one page to another. This allows you to review where you need to make changes without having to play your experience each time.

To navigate to another page while in Edit mode:

  1. In the Explorer window, select the UIPageLayout object.

  2. From the View tab, open the Command Bar.

    • To transition to the next page, input game:GetService("Selection"):Get()[1]:Next().

    • To transition to the previous page, input game:GetService("Selection"):Get()[1]:Previous().

  3. Press Enter.


There are three types of constraints you can use within your experiences: UIAspectRatioConstraint, UISizeConstraint, and UITextSizeConstraint.

To use a constraint, you must parent it to the GuiObject you want to constrain.


The UIAspectRatioConstraint specifies an aspect ratio for a GuiObject regardless of its actual size, so that it doesn't warp or distort within different screen sizes. This constraint ensures that the GuiObject maintains a specific aspect ratio even if its size is set as a percentage of its parent.


The UISizeConstraint specifies a minimum and maximum size for a GuiObject. This constraint ensures that the GuiObject doesn't become too small or large on different screen sizes.

For example, if you set the MaxSize property to {400, 400} and the MinSize to {200, 200}, the GuiObject cannot scale larger than 400 pixels wide and 400 pixels tall, or smaller than 200 pixels wide and 200 pixels tall.


The UITextSizeConstraint specifies a minimum and maximum font size for a GuiObject with text, such as a TextLabel, TextButton, or TextBox. This constraint ensures that the text within a GuiObject doesn't become illegible or too large.

If you enable the TextScaled property of the parent GuiObject, the text size scales with the container's size and respects constraints even if the object becomes smaller or larger than the MinTextSize and MaxTextSize values.

For example, the following TextLabel object has a UITextSizeConstraint with a MinTextSize value of 50 and a MaxTextSize value of 80. Even when the TextLabel becomes smaller, the font never becomes smaller than 50 pixels, and when the object becomes large, the font next exceeds 80 pixels.

Appearance Modifiers

By utilizing appearance modifiers, you can further customize the appearance of your GuiObjects.


The UIGradient object applies a color and transparency gradient to its parent GuiObject.

You can configure the gradient by:

Color Sequence

To set a gradient's color sequence:

  1. In the Explorer window, select the UIGradient.

  2. In the Properties window, click inside the Color property field, then click the button to the right of the input box. A color sequence pop-up displays.

    Each triangle on the bottom axis of the color sequence is a keypoint that determines the color value at that point.

  3. Click a keypoint in the color sequence, then click the small square next to Color to open the Colors pop-up window.

  4. Select the desired color for the keypoint.

  5. If needed, you can:

    • Add another keypoint by clicking anywhere on the graph.
    • Drag an existing keypoint to a new position, or select a keypoint and enter a specific time value through the Time input.
    • Delete a keypoint by selecting it and clicking the Delete button.
    • Reset the sequence by clicking the Reset button.


To adjust a gradient's transparency across its range:

  1. In the Explorer window, select the UIGradient.

  2. In the Properties window, click inside the Transparency property field, then click the button to the right of the input box. A number sequence pop-up displays.

    Each square across the number sequence graph is a keypoint that determines the transparency value at that point.

  3. Click and drag any keypoint around, or select a keypoint and enter a specific time/value combination through the Time and Value inputs.

  4. If needed, you can:

    • Add another keypoint by clicking anywhere on the graph.
    • Delete a keypoint by selecting it and clicking the Delete button.
    • Reset the sequence by clicking the Reset button.

Offset and Rotation

The Offset and Rotation properties let you adjust the gradient's control points and its angle. As illustrated in the following diagrams, Offset is based on a percentage of the parent's width or height, and both positive or negative values are valid.

Offset (X) = 0

Offset (X) = 0.25

Offset (X) = -0.25

Similarly, when you rotate the gradient, the control points also rotate.

Rotation = 0

Rotation = 45

Rotation = -90


The UIStroke instance applies an outline to text or a border. Key features include:

Text Outline / Border

Depending on its parent, UIStroke operates as either a text outline or as a border. When you parent UIStroke to a text object, it applies to the text's outline; when you parent UIStroke to other GuiObjects, it applies to the border.

TextLabel with UIStroke child
Frame with UIStroke and UICorner children

When applied to a text object, you can override the default stroke behavior by the ApplyStrokeMode property, letting you apply the stroke to the object's bounds instead of the text itself. You can even control the text outline and border independently by parenting two UIStroke instances to a text object, one set to Contextual and the other to Border.

UIStroke.ApplyStrokeMode = Contextual
UIStroke.ApplyStrokeMode = Border


You can set the stroke width through the Thickness property which is measured in pixels from the parent's outer edges.

UIStroke.Thickness = 4
UIStroke.Thickness = 12

Color / Gradient

You can set the stroke color through the Color property, as well as insert a child UIGradient instance to create gradient strokes.

UIStroke.Color = (0, 95, 225)
UIStroke with UIGradient child


The Transparency property sets the stroke transparency independently of the parent object's BackgroundTransparency or TextTransparency. This allows you to render text and borders that are "hollow" (consisting of only an outline).

TextLabel.TextTransparency = 0  /  UIStroke.Transparency = 0.5
TextLabel.TextTransparency = 1  /  UIStroke.Transparency = 0

Corner Style

The LineJoinMode property lets you control how corners are interpreted. It accepts a value of either Round, Bevel, or Miter.

UIStroke.LineJoinMode = Round

UIStroke.LineJoinMode = Bevel

UIStroke.LineJoinMode = Miter


The UICorner instance applies deformation to all four corners of its parent GuiObject. You can control the applied radius through the CornerRadius property using either Scale or Offset.

Scale rounds the corners to a percentage based on the total length of the shortest edge of the parent, meaning that a scale of 0.5 or higher deforms the parent into a "pill" shape, regardless of its width or height.

Scale = 0.25  /  Offset = 0
Scale = 0.5  /  Offset = 0

Offset rounds the corners to a specific number of pixels, regardless of the width/height of the parent.

Scale = 0  /  Offset = 25
Scale = 0  /  Offset = 50


A UIPadding object applies top, bottom, left, and/or right padding to the contents of the parent GuiObject.

For example, you can move the text inside a text button downward or upward by applying an offset to the bottom of the button.


A UIScale object stores a numerical value that multiplies the AbsoluteSize property of the parent GuiObject. For example, if you want an object to be twice as large as it currently is, you can insert a UIScale object with a Scale property of 2.

This object is useful when you want to resize GuiObjects proportionally for different screen sizes without having to manually change the size and position properties for each individual GuiObject. It is also useful to test a range of different sizes without committing to the changes.