--- title: CSS Comparisons description: Explore how CSS concepts map to Roblox UI styling concepts. --- 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: 1. In the [Explorer](../../studio/explorer.md), create the following: 1. `Class.StyleSheet` instance named `CoreSheet` inside `Class.ReplicatedStorage`. 2. Empty `Class.StyleRule` instance as a child of `CoreSheet`. 3. `Class.ScreenGui` container in `Class.StarterGui`. 4. `Class.LocalScript` instance inside the `Class.ScreenGui`. 5. `Class.StyleLink` object inside the `Class.ScreenGui` whose `Class.StyleLink.StyleSheet|StyleSheet` property is linked to `CoreSheet`. 2. In the `Class.LocalScript`, paste the following supporting code: ```lua title="LocalScript" local CollectionService = game:GetService("CollectionService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local coreSheet = ReplicatedStorage:FindFirstChild("CoreSheet") local rule = coreSheet:FindFirstChildWhichIsA("StyleRule") local screenGui = script.Parent ``` 3. For each example below, paste the **Luau** code lines following the supporting lines 1–6. ## Selectors The `Class.StyleRule.Selector|Selector` property of a `Class.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 `Class.GuiObject` class, for example `Class.Frame`, `Class.ImageLabel`, `Class.TextButton`, etc.
```text title="CSS" button { background-color: #335FFF; color: #E1E1E1; width: 15%; height: 40px; border: none; } ```
```text title="HTML" ```

```lua title="Luau" -- Class selector rule.Selector = "TextButton" -- Set rule properties rule: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](../../studio/properties.md#instance-tags) applied through `Class.CollectionService`.
```text title="CSS" .button-primary { background-color: #335FFF; color: #E1E1E1; } ```
```text title="HTML" ```

```lua title="Luau" -- Tag selector rule.Selector = ".ButtonPrimary" -- Set rule properties rule: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 button CollectionService:AddTag(button, "ButtonPrimary") ``` ### Identifier The closest Roblox comparison to CSS `id` is the `#[name]` selector which selects according to the value of `Class.Instance.Name`. Unlike the W3C specification of the `id` attribute, names are not expected to be unique.
```text title="CSS" #modal-frame { background-color: #000022; opacity: 0.5; width: 50%; min-height: 100px; } ```
```text title="HTML" ```

```lua title="Luau" -- Instance name selector rule.Selector = "#ModalFrame" -- Set rule properties rule: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 selector frame.Name = "ModalFrame" ``` ## Combinators Combinators let you mix basic [selectors](#selectors) to match deeper hierarchy relationships. ### Child The child selector of `>` is identical between CSS and Roblox.
```text title="CSS" .menu-container { width: 25%; } .menu-container > button { background-color: #335FFF; color: #E1E1E1; width: 80%; height: 40px; border: none; } ```
```text title="HTML" ```

```lua title="Luau" -- Child selector rule.Selector = ".MenuContainer > TextButton" -- Set rule properties for child rule:SetProperties({ ["BackgroundColor3"] = Color3.fromHex("335FFF"), ["TextColor3"] = Color3.fromHex("E1E1E1"), ["Size"] = UDim2.new(0.8, 0, 0, 40), ["BorderSizePixel"] = 0 }) -- Create menu container local menuContainer = Instance.new("Frame") menuContainer.Size = UDim2.new(0.25, 0, 0, 0) menuContainer.AutomaticSize = Enum.AutomaticSize.Y menuContainer.Parent = screenGui -- Apply tag CollectionService:AddTag(menuContainer, "MenuContainer") -- Create button local button = Instance.new("TextButton") button.Text = "Options" -- Set menu container as parent of button button.Parent = menuContainer ``` ### Descendant Unlike the CSS whitespace syntax, for example `.menu-container button` seen here, Roblox uses the `>>` combinator to indicate a descendant relationship.
```text title="CSS" .menu-container { width: 25%; } .sub-container { width: 75%; } .menu-container button { background-color: #335FFF; color: #E1E1E1; width: 80%; height: 40px; border: none; } ```
```text title="HTML" ```

```lua title="Luau" -- Descendant selector rule.Selector = ".MenuContainer >> TextButton" -- Set rule properties for descendant rule:SetProperties({ ["BackgroundColor3"] = Color3.fromHex("335FFF"), ["TextColor3"] = Color3.fromHex("E1E1E1"), ["Size"] = UDim2.new(0.8, 0, 0, 40), ["BorderSizePixel"] = 0 }) -- Create menu container local menuContainer = Instance.new("Frame") menuContainer.Size = UDim2.new(0.25, 0, 0, 0) menuContainer.AutomaticSize = Enum.AutomaticSize.Y menuContainer.Parent = screenGui -- Apply tag CollectionService:AddTag(menuContainer, "MenuContainer") -- Create sub-container local 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-container subContainer.Parent = menuContainer -- Create button local button = Instance.new("TextButton") button.Text = "Options" -- Set sub-container as parent of button button.Parent = subContainer ``` ### Selector list Multiple selectors (including selectors with combinators) can be declared with the same property block, separated by commas, to reduce redundancy.
```text title="CSS" img, p { background-color: #FF0033; } ```
```text title="HTML"

Main Menu

```

```lua title="Luau" -- Selector for image labels AND text labels rule.Selector = "ImageLabel, TextLabel" -- Set common property for classes rule:SetProperty("BackgroundColor3", Color3.fromHex("ff0033")) -- Create image label local imageLabel = Instance.new("ImageLabel") imageLabel.Image = "rbxassetid://104919049969988" imageLabel.Size = UDim2.new(0, 100, 0, 100) imageLabel.Parent = screenGui -- Create text label local textLabel = Instance.new("TextLabel") textLabel.Size = UDim2.new(1, 0, 0, 0) textLabel.AutomaticSize = Enum.AutomaticSize.Y textLabel.TextXAlignment = Enum.TextXAlignment.Left textLabel.TextYAlignment = Enum.TextYAlignment.Top textLabel.Text = "Main Menu" textLabel.Parent = screenGui ``` ## Pseudo-classes The Roblox equivalent to CSS [pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) selectors are **state selectors** which correspond to one of the four `Enum.GuiState` values such as `Enum.GuiState|Hover` or `Enum.GuiState|Press`.
```text title="CSS" img:hover { opacity: 0.5; } ```
```text title="HTML" ```

```lua title="Luau" -- State selector rule.Selector = "ImageLabel:Hover" -- Set rule property rule:SetProperty("ImageTransparency", 0.5) -- Create image label local label = Instance.new("ImageLabel") label.Image = "rbxassetid://104919049969988" label.Size = UDim2.new(0, 100, 0, 100) label.BackgroundTransparency = 1 label.Parent = screenGui ``` ## Pseudo-instances Similar to how CSS [pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements) can modify specific parts of an element, Roblox can create phantom `Class.UIComponent|UIComponents` through a style rule's `Class.StyleRule.Selector|Selector` property. For example, the following rule effectively creates a `Class.UICorner` modifier under every `Class.Frame` tagged with `RoundedCorner20` and sets each modifier's `Class.UICorner.CornerRadius|CornerRadius` to `20` pixels. ```lua title="Luau" -- UI component selector rule.Selector = "Frame.RoundedCorner20::UICorner" -- Set rule property rule:SetProperty("CornerRadius", UDim.new(0, 20)) -- Create frame local frame = Instance.new("Frame") frame.Size = UDim2.new(0.4, 0, 0.2, 0) frame.Parent = screenGui -- Apply tag to frame CollectionService:AddTag(frame, "RoundedCorner20") ``` ## Variables CSS lets you declare and reference [variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) throughout a style system. Roblox achieves this through tokens and the [instance attributes](../../studio/properties.md#instance-attributes) system. Using `$` as a prefix, you can reference attributes declared in a `Class.StyleRule` or `Class.StyleSheet` inheritance chain when setting style properties.
```text title="CSS" :root { --button-bg-color: #335FFF; --button-text-color: #E1E1E1; } button { background-color: var(--button-bg-color); color: var(--button-text-color); } ```
```text title="HTML" ```

```lua title="Luau" -- Set style sheet tokens using attributes coreSheet:SetAttribute("ButtonBgColor", Color3.fromHex("335FFF")) coreSheet:SetAttribute("ButtonTextColor", Color3.fromHex("E1E1E1")) -- Class selector rule.Selector = "TextButton" -- Set rule properties rule:SetProperties({ ["BackgroundColor3"] = "$ButtonBgColor", ["TextColor3"] = "$ButtonTextColor" }) -- Create button local button = Instance.new("TextButton") button.AutomaticSize = Enum.AutomaticSize.XY button.Text = "Main Menu" button.Parent = screenGui ``` ## Nesting and merging Borrowing a concept from [SCSS](https://sass-lang.com/guide/#nesting), `Class.StyleRule|StyleRules` can be nested together and their selectors will **merge**.
```text title="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; } } } ```
```text title="HTML" ```

```lua title="Luau" -- Menu frame rule local menuFrameRule = Instance.new("StyleRule") menuFrameRule.Parent = coreSheet menuFrameRule.Selector = "#MenuFrame" menuFrameRule:SetProperties({ ["BackgroundColor3"] = Color3.fromHex("000022"), ["Size"] = UDim2.new(0.25, 0, 0, 200), ["AutomaticSize"] = Enum.AutomaticSize.Y }) -- Menu layout rule local menuLayoutRule = Instance.new("StyleRule") menuLayoutRule.Parent = menuFrameRule -- Set menu frame rule as parent menuLayoutRule.Selector = "::UIListLayout" menuLayoutRule:SetProperties({ ["FillDirection"] = Enum.FillDirection.Vertical, ["VerticalFlex"] = Enum.UIFlexAlignment.SpaceEvenly, ["HorizontalAlignment"] = Enum.HorizontalAlignment.Center }) -- Button rule local buttonRule = Instance.new("StyleRule") buttonRule.Parent = menuFrameRule -- Set menu frame rule as parent buttonRule.Selector = "> TextButton" buttonRule:SetProperties({ ["BackgroundColor3"] = Color3.fromHex("335FFF"), ["TextColor3"] = Color3.fromHex("E1E1E1"), ["Size"] = UDim2.new(0.8, 0, 0, 40), ["BorderSizePixel"] = 0 }) -- Button hover rule local buttonHoverRule = Instance.new("StyleRule") buttonHoverRule.Parent = buttonRule -- Set button rule as parent buttonHoverRule.Selector = ":hover" buttonHoverRule:SetProperty("BackgroundTransparency", 0.5) -- Create parent frame local menuFrame = Instance.new("Frame") menuFrame.Parent = screenGui menuFrame.Name = "MenuFrame" -- Create buttons inside frame local button1 = Instance.new("TextButton") button1.Text = "Charms" button1.Parent = menuFrame local button2 = Instance.new("TextButton") button2.Text = "Mana" button2.Parent = menuFrame local button3 = Instance.new("TextButton") button3.Text = "Scrolls" button3.Parent = menuFrame ```