[Studio Beta] Introducing UI Styling!

Hi Creators!

Today, we’re excited to introduce UI Styling as a Studio beta! UI styling is a Roblox-native feature that lets you declare and globally apply overrides to UI instance properties. This has been a long awaited feature with lots of anticipation from the community – we can’t wait to hear what you think and see what you build :tada:

We’re launching:

  1. Multiple APIs to define and apply UI styles, including:

    • StyleRules define styled properties which override properties on the instances affected by the Selector property.
    • StyleSheets aggregate StyleRules and can be linked to DataModel trees to apply style properties to instances.
    • StyleLinks connect a StyleSheet to the instance tree whose root is the parent of the StyleLink.
    • StyleDerives reference another StyleSheet for a parent StyleSheet to inherit StyleRules and token definitions
  2. A no-code Style Editor built into Studio that allows you to globally manage UI styles & themes. These can be used to:

    • :arrows_counterclockwise: Create complex UI styles and apply them with one click
    • :pencil2: Quickly change the visual appearance of multiple styled instances at once
    • :art: Manage all of your UI colors and fonts in one location
    • :bulb: Create swappable UI themes, like a light and dark mode

2025-05-12 09.29.59

During this Studio beta period, you can opt into usage of the APIs and Studio tooling via the Beta features tab in Studio. At this time, you can’t publish any Styling instances (or references to Styling instances) into your live experiences. We are hoping to use this beta to get your feedback and stomp out any issues – please let us know if you have any in the comments below. You’ll be able to start publishing experiences with Styling when we move into the client beta phase within the next couple of months.

Keep reading for more details on how to start using the Styling Editor and API!


To enable this beta in Roblox Studio, follow these simple steps:

  1. Open Roblox Studio and navigate to the “File” menu.
  2. Click on “Beta Features”.
  3. Enable the “UI Styling” option by checking the corresponding checkbox (see screenshot below) and press Save.
  4. Restart Roblox Studio when prompted.

Improving Your UI Workflow With Styling

In the past, visually styling UI elements typically involved manually adjusting the properties of each individual UI instance. In an experience with numerous UI elements, this process could quickly become cumbersome – having to search through the Datamodel tree to locate the right instance, match its properties exactly to another, and repeat the process for each one.

Styling separates defining the structure of UI elements from their visual appearance. This is extremely powerful – teams can now iterate quickly across color palettes, fonts, and other themes without recreating instances. We’ve taken some inspiration from CSS, a common programming paradigm used to style web pages. This page provides an in-depth overview of Styling. If you’re familiar with CSS (or want to learn more), check out this guide comparing Roblox’s Styling with CSS.

What exactly can you style? We’ve added Styling support for UI-related classes! Note that not all properties within each class will be styleable – this page will have the most updated list of styleable properties. Additional support may be added over time!

How to Use the Style Editor

The built-in Style Editor is a comprehensive tool that allows you to create, manage, and apply UI styles for Roblox experiences through a combination of design sheets, style rules, tokens, and themes. You can find the Style Editor under the UI tab.

There are 3 types of StyleSheets you can create in the Style Editor:

  1. Design: UI Element style rules and tags

    • Class rules: A class selector targets all instances of a given UI class. Here’s an example that styles all Frames with a uniform background color and size.

    • Tag rules: Tag selectors target specific UI objects tagged through CollectionService. Here’s an example that shows a TextButton tagged as ButtonPrimary with a custom background color, font, and text size.

    • Modifier rules: Instance pseudo-instance selectors apply phantom UIComponents such as UICorner or UIStroke to an object. This achieves the same result as inserting a UIComponent under an object in the DataModel–without actually inserting anything! Here’s an example that styles a TextLabel and a TextButton with the same rounded corner

    • State rules: GuiObject state selectors correspond to one of the four GuiState enum values such as Hover, letting you automatically configure style changes for interactive states. Here’s an example that creates a hover state of -4 degrees rotation for all ImageButtons.

  2. Tokens: Global UI property variables that can be used across styles and components. For example, Frame.BackgroundColor3, TextLabel.TextColor3, and UIStroke.Color could all be set to a common color variable named Magenta. Here’s an example of what a Token StyleSheet could look like.

  3. Themes: A swappable defined set of property values. Here’s an example of what a Theme StyleSheet looks like – on the “General” folder, you can toggle between ThemeA and ThemeB to swap what values BackColor, ButtonFont, and ButtonTextSize are set to.

StyleSheets are stored in ReplicatedStorage. When you use the Style Editor, you may notice a BaseStyleSheet there – this is automatically generated by the Style Editor when you create your first Design StyleSheet. :warning: It is highly recommended that you do not delete or attempt to modify the BaseStyleSheet, since this will reset all your default properties to Engine defaults.

Try It Out

The building blocks of Styling above can be combined to achieve some powerful new workflows. Check out our video tutorial or see this document for a step-by-step walkthrough of how to use our Style Editor, best practices, and some ideas of what it can achieve! If you want to follow along at home, you can find a sample placefile here: Styling Advanced Example.rbxl (76.2 KB)

How to Use Styling APIs in Script

While you can author UI Styles completely using the no-code Style Editor, you can also use scripting to create styles with additional run-time functionality!

  • Define StyleSheets and apply them to UI instance hierarchies
Click here to see a working script example
-- Parent this script to a ScreenGui under StarterGui.

local CollectionService = game:GetService("CollectionService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local screenGui = script.Parent

-- DesignSheet

local sheet = Instance.new("StyleSheet")

sheet.Parent = ReplicatedStorage

-- Configure rule

local rule = Instance.new("StyleRule")

rule.Selector = "TextButton" -- Class selector

rule.Parent = sheet

-- Set rule properties

rule:SetProperties({

["BackgroundColor3"] = Color3.fromHex("335fff"),

["TextColor3"] = Color3.fromHex("e1e1e1"),

["Size"] = UDim2.new(0.15, 0, 0, 40),

["BorderSizePixel"] = 0

})

-- Create a UI

local button = Instance.new("TextButton")

button.Text = "Main Menu"

button.Parent = screenGui

-- Apply styling to UI

local link = Instance.new("StyleLink")

link.Parent = screenGui

link.StyleSheet = sheet
  • Create tokens, themes, and dynamically swap themes at run-time based on game state or player data
Click here to see a working script example
-- Parent this script to a ScreenGui under StarterGui.

local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local screenGui = script.Parent

-- Tokens
local tokens = Instance.new("StyleSheet")
tokens.Name = "Tokens"
tokens.Parent = ReplicatedStorage
tokens:SetAttribute("SquareS", UDim2.fromOffset(50, 50))
tokens:SetAttribute("SquareM", UDim2.fromOffset(100, 100))
tokens:SetAttribute("SquareL", UDim2.fromOffset(200, 200))
tokens:SetAttribute("Fit", UDim2.fromScale(1, 1))
tokens:SetAttribute("Magenta", Color3.fromHex("FF0099"))
tokens:SetAttribute("Gold", Color3.fromHex("FFCC00"))
tokens:SetAttribute("Aqua", Color3.fromHex("0093F0"))

-- ThemeA
local themeA = Instance.new("StyleSheet")
themeA.Name = "ThemeA"
themeA.Parent = ReplicatedStorage
local tokensDerive = Instance.new("StyleDerive")
tokensDerive.StyleSheet = tokens  -- Derive global tokens
tokensDerive.Parent = themeA
themeA:SetAttribute("TextButtonSize", "$SquareM")
themeA:SetAttribute("TextButtonColor", "$Aqua")

-- ThemeB
local themeB = Instance.new("StyleSheet")
themeB.Name = "ThemeB"
themeB.Parent = ReplicatedStorage
local tokensDerive = Instance.new("StyleDerive")
tokensDerive.StyleSheet = tokens  -- Derive global tokens
tokensDerive.Parent = themeB
themeB:SetAttribute("TextButtonSize", "$SquareL")
themeB:SetAttribute("TextButtonColor", "$Magenta")

-- DesignSheet
local designSheet = Instance.new("StyleSheet")
designSheet.Name = "DesignSheet"
designSheet.Parent = ReplicatedStorage
local themeDerive = Instance.new("StyleDerive")
themeDerive.StyleSheet = themeB  -- Derive from ThemeB
themeDerive.Parent = designSheet

-- Link DesignSheet to ScreenGui
local styleLink = Instance.new("StyleLink")
styleLink.StyleSheet = designSheet
styleLink.Parent = screenGui

-- Configure rule
local rule = Instance.new("StyleRule")
rule.Selector = "TextButton"  -- Class selector
rule.Parent = designSheet

-- Set rule properties
rule:SetProperties({
	["BackgroundColor3"] = "$TextButtonColor",
	["Size"] = "$TextButtonSize",
	["BorderSizePixel"] = 0
})

-- Create and style UI
local textButton = Instance.new("TextButton")
textButton.Text = "Press me to change my theme!"
textButton.TextWrapped = true
textButton.Parent = screenGui
textButton.Activated:Connect(function(inputObject: InputObject, clickCount: number) 
	if themeDerive.StyleSheet == themeA then
		themeDerive.StyleSheet = themeB
	else
		themeDerive.StyleSheet = themeA
	end	
end)


Tips

Click here to read more
  • StyleRule property overrides only apply if the instance property is set to its default value. To reset the property to its default value, right click the property in the properties panel and select Reset Property to Default.
  • You can only apply one pseudoinstance of each type per instance. This means for a Frame, you can have a ::UICorner, ::UIStroke, ::UIGradient, etc. pseudoinstances, but if you have two UICorners, only one phantom instance is created.
  • You can only apply one StyleLink per instance in the Datamodel. If there are two StyleLinks parented to the same instance, only one will take effect.
  • A BaseStyleSheet will only be auto-generated and derived from if you are using the Style Editor.
  • Deriving or linking to a StyleSheet that is not in the DataModel will have undefined behavior. Using a StyleSheet outside the DataModel is not supported.

:blue_heart: Made with love

UI Styling was made possible thanks to @Tiffblocks, @nomnomhungy, @ThunderBolt5140, @TangyTrout, @stadium_parkour, @uiuxartist, @DrRanchDressing, @hughtesting, @hijabiIntern, @rbx_dert, @KarRic22, @slamborgen, @butterthebig, @IgnisRBX, and @darthskrill. We also want to give a huge thank you to our early testers who gave us feedback along the way!

We can’t wait to hear your thoughts on UI Styling and see all the amazing things you create! Let us know about your experience and if you encounter any issues! :smile:

514 Likes

This topic was automatically opened after 10 minutes.

WOAH… THIS IS HUGE… UI Styling is EXACTLY what we’ve needed for so long. No more manually updating every single frame just to change one color or font so happy its now it’s all linked and clean!!

This is gonna make UI updates SO much faster and way more organized. Massive W for devs, especially for teams and big projects. Love seeing features like this roll out!!

101 Likes

this looks brilliant, will be really useful for light/dark toggles and user color preferences.
the no code editor reminds me of figma’s variable system

also from the looks of the screenshot, will you be able to edit any property of a ui element? could this be used to dynamically change component contents?

31 Likes

I’m so excited for stylesheets. I’ve been working on a text based language as an alternative to the plugin to interface with them.

The language is currently very unstable but i’d thought i’d share it anyways: https://rsml.style.

57 Likes

FINALLY!!! LOVELY FEATURE
the placefile on google drive isn’t public though :weary:

15 Likes

Thank you so much for finally bringing us this. Honestly, it’s been annoying having to do styling individually for each element.

11 Likes

Just opened the topic, saw the preview, euphoria took over.

This is INCREDIBLE! Finally, I can get something of easier for my plugin without having to do clunky shenanigans like I do right now to get custom themes. Off with the era of having 7 frames for each theme. This is future, and it is bright (as always).

I will try to do some things with it soon and will edit this message to give you some news. Anyway, thanks to:

…for making this!

19 Likes

When are you introducing UI masks? It’s 2025, Photoshop had them on 1994

44 Likes

Thanks for raising this! Can you try accessing the place file again?

4 Likes

The font folder, are we getting custom fonts ??!

6 Likes

Praying that we get some form of UI blur soon. Seems like a perfect time now that this has released.

20 Likes

Will we get the ability to have an event get triggered? E.g we define a style then have we can connect a .Activated function to it which is triggered by any button with that style being pressed. This would make button designing and such, much more simplified (in my opinion) than using tag editor

5 Likes

Will there be a way to make it text based kind of like in CSS (Cascading Style Sheets)?

8 Likes

thank you, it works now!! :smiley:
30 bytes

7 Likes

Okay, I can finally say - THAT is what we needed. Thank you so much, Roblox.

8 Likes

I think it’s already possible, on the StyleBase documentation, it mentions this:

Is it what you meant or not?

4 Likes

Yeah I think you can put fonts like gg sans on Roblox if that becomes a thing.

4 Likes

gg sans is not an open-source font, that would technically not be allowed. the license on the font doesn’t allow it either

6 Likes

There is a lot more to this than I originally thought.

I felt like the whole idea of pseudoinstances would get confusing, but I see that they appear in properties:
image
(Along with some other property changes, which are really nice to see!)

I don’t know how to feel about having to make 2 gazillion tags to use stylesheets, but I guess it’s better than using 2 gazillion StyleLinks instead.

Overall this is super awesome and very in-depth. I can see why this took so long to release.

11 Likes