Most CSS concepts map to Roblox styling concepts. The following examples show how CSS and HTML align with Luau and Roblox classes/properties.
To test each of the following Luau script examples:
In the Explorer, create the following:
- Empty StyleRule instance as a child of CoreSheet.
- ScreenGui container in StarterGui.
- LocalScript instance inside the ScreenGui.
In the LocalScript, paste the following supporting code:
LocalScriptlocal CollectionService = game:GetService("CollectionService")local ReplicatedStorage = game:GetService("ReplicatedStorage")local coreSheet = ReplicatedStorage:FindFirstChild("CoreSheet")local rule = coreSheet:FindFirstChildWhichIsA("StyleRule")local screenGui = script.ParentFor each example below, paste the Luau code lines following the supporting lines 1–6.
Selectors
The Selector property of a StyleRule specifies which instances the rule should affect. The following selector types map from CSS to Luau and can be used with combinators.
Element
Equivalent to CSS element selectors are Roblox class selectors which select all instances of a given GuiObject class, for example Frame, ImageLabel, TextButton, etc.
CSS
button {background-color: #335FFF;color: #E1E1E1;width: 15%;height: 40px;border: none;}
HTML
<button>Main Menu</button>
Luau
-- Class selectorrule.Selector = "TextButton"-- Set rule propertiesrule:SetProperties({["BackgroundColor3"] = Color3.fromHex("335FFF"),["TextColor3"] = Color3.fromHex("E1E1E1"),["Size"] = UDim2.new(0.15, 0, 0, 40),["BorderSizePixel"] = 0})local button = Instance.new("TextButton")button.Text = "Main Menu"button.Parent = screenGui
Class
The Roblox equivalent to CSS class selectors are tag selectors which utilize tags applied through CollectionService.
CSS
.button-primary {background-color: #335FFF;color: #E1E1E1;}
HTML
<button class="button-primary">Main Menu</button>
Luau
-- Tag selectorrule.Selector = ".ButtonPrimary"-- Set rule propertiesrule:SetProperties({["BackgroundColor3"] = Color3.fromHex("335FFF"),["TextColor3"] = Color3.fromHex("E1E1E1"),["AutomaticSize"] = Enum.AutomaticSize.XY})local button = Instance.new("TextButton")button.Text = "Main Menu"button.Parent = screenGui-- Apply tag to buttonCollectionService:AddTag(button, "ButtonPrimary")
Identifier
The closest Roblox comparison to CSS id is the #[name] selector which selects according to the value of Instance.Name. Unlike the W3C specification of the id attribute, names are not expected to be unique.
CSS
#modal-frame {background-color: #000022;opacity: 0.5;width: 50%;min-height: 100px;}
HTML
<div id="modal-frame"></div>
Luau
-- Instance name selectorrule.Selector = "#ModalFrame"-- Set rule propertiesrule:SetProperties({["BackgroundColor3"] = Color3.fromHex("000022"),["BackgroundTransparency"] = 0.5,["Size"] = UDim2.new(0.5, 0, 0, 100),["AutomaticSize"] = Enum.AutomaticSize.Y})local frame = Instance.new("Frame")frame.Parent = screenGui-- Rename frame to match selectorframe.Name = "ModalFrame"
Combinators
Combinators let you mix basic selectors to match deeper hierarchy relationships.
Child
The child selector of > is identical between CSS and Roblox.
CSS
.menu-container {width: 25%;}.menu-container > button {background-color: #335FFF;color: #E1E1E1;width: 80%;height: 40px;border: none;}
HTML
<div class="menu-container"><button>Options</button></div>
Luau
-- Child selectorrule.Selector = ".MenuContainer > TextButton"-- Set rule properties for childrule:SetProperties({["BackgroundColor3"] = Color3.fromHex("335FFF"),["TextColor3"] = Color3.fromHex("E1E1E1"),["Size"] = UDim2.new(0.8, 0, 0, 40),["BorderSizePixel"] = 0})-- Create menu containerlocal menuContainer = Instance.new("Frame")menuContainer.Size = UDim2.new(0.25, 0, 0, 0)menuContainer.AutomaticSize = Enum.AutomaticSize.YmenuContainer.Parent = screenGui-- Apply tagCollectionService:AddTag(menuContainer, "MenuContainer")-- Create buttonlocal button = Instance.new("TextButton")button.Text = "Options"-- Set menu container as parent of buttonbutton.Parent = menuContainer
Descendant
Unlike the CSS whitespace syntax, for example .menu-container button seen here, Roblox uses the >> combinator to indicate a descendant relationship.
CSS
.menu-container {width: 25%;}.sub-container {width: 75%;}.menu-container button {background-color: #335FFF;color: #E1E1E1;width: 80%;height: 40px;border: none;}
HTML
<div class="menu-container"><div class="sub-container"><button>Options</button></div></div>
Luau
-- Descendant selectorrule.Selector = ".MenuContainer >> TextButton"-- Set rule properties for descendantrule:SetProperties({["BackgroundColor3"] = Color3.fromHex("335FFF"),["TextColor3"] = Color3.fromHex("E1E1E1"),["Size"] = UDim2.new(0.8, 0, 0, 40),["BorderSizePixel"] = 0})-- Create menu containerlocal menuContainer = Instance.new("Frame")menuContainer.Size = UDim2.new(0.25, 0, 0, 0)menuContainer.AutomaticSize = Enum.AutomaticSize.YmenuContainer.Parent = screenGui-- Apply tagCollectionService:AddTag(menuContainer, "MenuContainer")-- Create sub-containerlocal subContainer = Instance.new("Frame")subContainer.Size = UDim2.new(0.75, 0, 0, 0)subContainer.AutomaticSize = Enum.AutomaticSize.Y-- Set menu container as parent of sub-containersubContainer.Parent = menuContainer-- Create buttonlocal button = Instance.new("TextButton")button.Text = "Options"-- Set sub-container as parent of buttonbutton.Parent = subContainer
Selector list
Multiple selectors (including selectors with combinators) can be declared with the same property block, separated by commas, to reduce redundancy.
CSS
img, p {background-color: #FF0033;}
HTML
<img src="gear.png" width="100" height="100"><p>Main Menu</p>
Luau
-- Selector for image labels AND text labelsrule.Selector = "ImageLabel, TextLabel"-- Set common property for classesrule:SetProperty("BackgroundColor3", Color3.fromHex("ff0033"))-- Create image labellocal imageLabel = Instance.new("ImageLabel")imageLabel.Image = "rbxassetid://104919049969988"imageLabel.Size = UDim2.new(0, 100, 0, 100)imageLabel.Parent = screenGui-- Create text labellocal textLabel = Instance.new("TextLabel")textLabel.Size = UDim2.new(1, 0, 0, 0)textLabel.AutomaticSize = Enum.AutomaticSize.YtextLabel.TextXAlignment = Enum.TextXAlignment.LefttextLabel.TextYAlignment = Enum.TextYAlignment.ToptextLabel.Text = "Main Menu"textLabel.Parent = screenGui
Pseudo-classes
The Roblox equivalent to CSS pseudo-class selectors are state selectors which correspond to one of the four Enum.GuiState values such as Hover or Press.
CSS
img:hover {opacity: 0.5;}
HTML
<img src="gear.png" width="100" height="100">
Luau
-- State selectorrule.Selector = "ImageLabel:Hover"-- Set rule propertyrule:SetProperty("ImageTransparency", 0.5)-- Create image labellocal label = Instance.new("ImageLabel")label.Image = "rbxassetid://104919049969988"label.Size = UDim2.new(0, 100, 0, 100)label.BackgroundTransparency = 1label.Parent = screenGui
Pseudo-instances
Similar to how CSS pseudo-elements can modify specific parts of an element, Roblox can create phantom UIComponents through a style rule's Selector property. For example, the following rule effectively creates a UICorner modifier under every Frame tagged with RoundedCorner20 and sets each modifier's CornerRadius to 20 pixels.
Luau
-- UI component selectorrule.Selector = "Frame.RoundedCorner20::UICorner"-- Set rule propertyrule:SetProperty("CornerRadius", UDim.new(0, 20))-- Create framelocal frame = Instance.new("Frame")frame.Size = UDim2.new(0.4, 0, 0.2, 0)frame.Parent = screenGui-- Apply tag to frameCollectionService:AddTag(frame, "RoundedCorner20")
Variables
CSS lets you declare and reference variables throughout a style system. Roblox achieves this through tokens and the instance attributes system. Using $ as a prefix, you can reference attributes declared in a StyleRule or StyleSheet inheritance chain when setting style properties.
CSS
:root {--button-bg-color: #335FFF;--button-text-color: #E1E1E1;}button {background-color: var(--button-bg-color);color: var(--button-text-color);}
HTML
<button>Main Menu</button>
Luau
-- Set style sheet tokens using attributescoreSheet:SetAttribute("ButtonBgColor", Color3.fromHex("335FFF"))coreSheet:SetAttribute("ButtonTextColor", Color3.fromHex("E1E1E1"))-- Class selectorrule.Selector = "TextButton"-- Set rule propertiesrule:SetProperties({["BackgroundColor3"] = "$ButtonBgColor",["TextColor3"] = "$ButtonTextColor"})-- Create buttonlocal button = Instance.new("TextButton")button.AutomaticSize = Enum.AutomaticSize.XYbutton.Text = "Main Menu"button.Parent = screenGui
Nesting and merging
Borrowing a concept from SCSS, StyleRules can be nested together and their selectors will merge.
SCSS
#menu-frame {background-color: #000022;width: 25%;min-height: 200px;display: flex;flex-direction: column;justify-content: space-evenly;align-items: center;> button {background-color: #335FFF;color: #E1E1E1;width: 80%;height: 40px;border: none;&:hover {opacity: 0.5;}}}
HTML
<div id="menu-frame"><button>Charms</button><button>Mana</button><button>Scrolls</button></div>
Luau
-- Menu frame rulelocal menuFrameRule = Instance.new("StyleRule")menuFrameRule.Parent = coreSheetmenuFrameRule.Selector = "#MenuFrame"menuFrameRule:SetProperties({["BackgroundColor3"] = Color3.fromHex("000022"),["Size"] = UDim2.new(0.25, 0, 0, 200),["AutomaticSize"] = Enum.AutomaticSize.Y})-- Menu layout rulelocal menuLayoutRule = Instance.new("StyleRule")menuLayoutRule.Parent = menuFrameRule -- Set menu frame rule as parentmenuLayoutRule.Selector = "::UIListLayout"menuLayoutRule:SetProperties({["FillDirection"] = Enum.FillDirection.Vertical,["VerticalFlex"] = Enum.UIFlexAlignment.SpaceEvenly,["HorizontalAlignment"] = Enum.HorizontalAlignment.Center})-- Button rulelocal buttonRule = Instance.new("StyleRule")buttonRule.Parent = menuFrameRule -- Set menu frame rule as parentbuttonRule.Selector = "> TextButton"buttonRule:SetProperties({["BackgroundColor3"] = Color3.fromHex("335FFF"),["TextColor3"] = Color3.fromHex("E1E1E1"),["Size"] = UDim2.new(0.8, 0, 0, 40),["BorderSizePixel"] = 0})-- Button hover rulelocal buttonHoverRule = Instance.new("StyleRule")buttonHoverRule.Parent = buttonRule -- Set button rule as parentbuttonHoverRule.Selector = ":hover"buttonHoverRule:SetProperty("BackgroundTransparency", 0.5)-- Create parent framelocal menuFrame = Instance.new("Frame")menuFrame.Parent = screenGuimenuFrame.Name = "MenuFrame"-- Create buttons inside framelocal button1 = Instance.new("TextButton")button1.Text = "Charms"button1.Parent = menuFramelocal button2 = Instance.new("TextButton")button2.Text = "Mana"button2.Parent = menuFramelocal button3 = Instance.new("TextButton")button3.Text = "Scrolls"button3.Parent = menuFrame