La mayoría de los conceptos de CSS se mapean a los conceptos de estilo de Roblox. Los siguientes ejemplos muestran cómo CSS y HTML se alinean con Luau y las clases/propiedades de Roblox.
Para probar cada uno de los siguientes ejemplos de script de Luau:
En el Explorer, crea lo siguiente:

- Instancia StyleSheet dentro de ReplicatedStorage.
- Contenedor ScreenGui en StarterGui.
- Instancia LocalScript dentro de ScreenGui.
En el LocalScript, pega el siguiente código de soporte:
LocalScriptlocal CollectionService = game:GetService("CollectionService")local ReplicatedStorage = game:GetService("ReplicatedStorage")local coreSheet = ReplicatedStorage:FindFirstChildWhichIsA("StyleSheet")local screenGui = script.Parentlocal styleLink = screenGui:FindFirstChildWhichIsA("StyleLink")styleLink.StyleSheet = coreSheetPara cada ejemplo a continuación, pega las líneas de código Luau siguiendo las líneas de soporte 1–7.
Selectores
La propiedad Selector de una StyleRule especifica qué instancias debe afectar la regla. Los siguientes tipos de selectores se mapean de CSS a Luau y se pueden usar con combinadores.
Elemento
Equivalente a los selectores de elementos de CSS son los selectores de clase de Roblox que seleccionan todas las instancias de una clase dada de GuiObject, por ejemplo Frame, ImageLabel, TextButton, etc.
button {
background-color: #335FFF;
color: #E1E1E1;
width: 15%;
height: 40px;
border: none;
}<button>Menú Principal</button>local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = "TextButton" -- Selector de clase de Roblox
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 = "Menú Principal"
button.Parent = screenGuiClase
El equivalente de Roblox a los selectores de clase de CSS son los selectores de etiqueta que utilizan etiquetas aplicadas a través de CollectionService.
.button-primary {
background-color: #335FFF;
color: #E1E1E1;
}<button class="button-primary">Menú Principal</button>local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = ".ButtonPrimary" -- Selector de etiqueta de Roblox
rule:SetProperties({
BackgroundColor3 = Color3.fromHex("335FFF"),
TextColor3 = Color3.fromHex("E1E1E1"),
AutomaticSize = Enum.AutomaticSize.XY
})
local button = Instance.new("TextButton")
button.Text = "Menú Principal"
button.Parent = screenGui
-- Aplicar etiqueta al botón
CollectionService:AddTag(button, "ButtonPrimary")Identificador
La comparación más cercana de Roblox al id de CSS es el selector #[name] que selecciona según el valor de Instance.Name. A diferencia de la especificación W3C del atributo id, no se espera que los nombres sean únicos.
#modal-frame {
background-color: #000022;
opacity: 0.5;
width: 50%;
min-height: 100px;
}<div id="modal-frame"></div>local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = "#ModalFrame" -- Selector de nombre de instancia
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
-- Renombrar el marco para que coincida con el selector
frame.Name = "ModalFrame"Combinadores
Los combinadores te permiten mezclar selectores básicos selectores para coincidir con relaciones jerárquicas más profundas.
Hijo
El selector hijo de > es idéntico entre CSS y Roblox.
.menu-container {
width: 25%;
}
.menu-container > button {
background-color: #335FFF;
color: #E1E1E1;
width: 80%;
height: 40px;
border: none;
}<div class="menu-container">
<button>Opciones</button>
</div>local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = ".MenuContainer > TextButton" -- Selector hijo
rule:SetProperties({
BackgroundColor3 = Color3.fromHex("335FFF"),
TextColor3 = Color3.fromHex("E1E1E1"),
Size = UDim2.new(0.8, 0, 0, 40),
BorderSizePixel = 0
})
-- Crear contenedor de menú
local menuContainer = Instance.new("Frame")
menuContainer.Size = UDim2.new(0.25, 0, 0, 0)
menuContainer.AutomaticSize = Enum.AutomaticSize.Y
menuContainer.Parent = screenGui
-- Aplicar etiqueta
CollectionService:AddTag(menuContainer, "MenuContainer")
-- Crear botón
local button = Instance.new("TextButton")
button.Text = "Opciones"
-- Establecer el contenedor de menú como padre del botón
button.Parent = menuContainerDescendiente
A diferencia de la sintaxis de espacio en blanco de CSS, por ejemplo .menu-container button vista aquí, Roblox utiliza el combinador >> para indicar una relación de descendencia.
.menu-container {
width: 25%;
}
.sub-container {
width: 75%;
}
.menu-container button {
background-color: #335FFF;
color: #E1E1E1;
width: 80%;
height: 40px;
border: none;
}<div class="menu-container">
<div class="sub-container">
<button>Opciones</button>
</div>
</div>local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = ".MenuContainer >> TextButton" -- Selector de descendiente
rule:SetProperties({
BackgroundColor3 = Color3.fromHex("335FFF"),
TextColor3 = Color3.fromHex("E1E1E1"),
Size = UDim2.new(0.8, 0, 0, 40),
BorderSizePixel = 0
})
-- Crear contenedor de menú
local menuContainer = Instance.new("Frame")
menuContainer.Size = UDim2.new(0.25, 0, 0, 0)
menuContainer.AutomaticSize = Enum.AutomaticSize.Y
menuContainer.Parent = screenGui
-- Aplicar etiqueta
CollectionService:AddTag(menuContainer, "MenuContainer")
-- Crear sub-contenedor
local subContainer = Instance.new("Frame")
subContainer.Size = UDim2.new(0.75, 0, 0, 0)
subContainer.AutomaticSize = Enum.AutomaticSize.Y
-- Establecer el contenedor de menú como padre del sub-contenedor
subContainer.Parent = menuContainer
-- Crear botón
local button = Instance.new("TextButton")
button.Text = "Opciones"
-- Establecer el sub-contenedor como padre del botón
button.Parent = subContainerLista de selectores
Múltiples selectores (incluidos los selectores con combinadores) se pueden declarar con el mismo bloque de propiedades, separados por comas, para reducir la redundancia.
img, p {
background-color: #FF0033;
}<img src="gear.png" width="100" height="100">
<p>Menú Principal</p>local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = "ImageLabel, TextLabel" -- Selector para etiquetas de imagen Y etiquetas de texto
rule:SetProperty("BackgroundColor3", Color3.fromHex("ff0033"))
-- Crear etiqueta de imagen
local imageLabel = Instance.new("ImageLabel")
imageLabel.Image = "rbxassetid://104919049969988"
imageLabel.Size = UDim2.new(0, 100, 0, 100)
imageLabel.Parent = screenGui
-- Crear etiqueta de texto
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 = "Menú Principal"
textLabel.Parent = screenGuiPseudo-clases
El equivalente de Roblox a los selectores de pseudo-clase de CSS son los selectores de estado que corresponden a uno de los cuatro valores de Enum.GuiState, como Hover o Press.
img:hover {
opacity: 0.5;
}<img src="gear.png" width="100" height="100">local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = "ImageLabel:Hover" -- Selector de estado
rule:SetProperty("ImageTransparency", 0.5)
-- Crear etiqueta de imagen
local imageLabel = Instance.new("ImageLabel")
imageLabel.Image = "rbxassetid://104919049969988"
imageLabel.Size = UDim2.new(0, 100, 0, 100)
imageLabel.BackgroundTransparency = 1
imageLabel.Parent = screenGuiPseudo-instancias
De manera similar a cómo los pseudo-elementos de CSS pueden modificar partes específicas de un elemento, Roblox puede crear UIComponents fantasma a través de la propiedad Selector de una regla de estilo. Por ejemplo, la siguiente regla crea efectivamente un modificador UICorner bajo cada Frame etiquetado con RoundedCorner20 y establece el CornerRadius de cada modificador a 20 píxeles.
local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
rule.Selector = "Frame.RoundedCorner20::UICorner" -- Selector de componente de UI
rule:SetProperty("CornerRadius", UDim.new(0, 20))
-- Crear marco
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.4, 0, 0.2, 0)
frame.Parent = screenGui
-- Aplicar etiqueta al marco
CollectionService:AddTag(frame, "RoundedCorner20")Consultas
Las consultas de estilo de Roblox cierran la brecha entre las consultas de medios de CSS y las consultas de contenedor. Usando el prefijo @, puedes alternar estilos basados en las dimensiones del padre, tipos de dispositivos de entrada o configuraciones de accesibilidad del usuario.
En CSS, @container aplica estilos basados en el tamaño de un elemento padre. En Roblox, defines una consulta de pseudo‑instancia usando ::StyleQuery seguido de un identificador para la propiedad Selector de la condición, por ejemplo "::StyleQuery #WideContainer", junto con un nombre de condición de StyleQuery como "MinSize" para evaluar el GuiObject.AbsoluteSize del padre. Luego, para aplicar estilos a la instancia o sus hijos cuando la consulta está activa, crea una StyleRule con el prefijo @[identifier] como su Selector, por ejemplo @WideContainer.
.container {
container-type: inline-size;
background-color: rgba(0, 0, 34, 0.5);
}
button {
background-color: #335FFF;
color: #E1E1E1;
width: 75%;
height: 40px;
border: none;
}
@container (min-width: 400px) {
button {
background-color: #cc0033;
}
}<div class="container" style="width: 80%; height: 200px;">
<button>Menú Principal</button>
</div>-- Regla de contenedor
local containerRule = Instance.new("StyleRule")
containerRule.Selector = "Frame" -- Selector de clase de Roblox
containerRule:SetProperties({
BackgroundColor3 = Color3.fromRGB(0, 0, 34),
BackgroundTransparency = 0.5,
BorderSizePixel = 0
})
containerRule.Parent = coreSheet
-- Regla de botón
local buttonRule = Instance.new("StyleRule")
buttonRule.Selector = "TextButton" -- Selector de clase de Roblox
buttonRule:SetProperties({
BackgroundColor3 = Color3.fromHex("335FFF"),
TextColor3 = Color3.fromHex("E1E1E1"),
Size = UDim2.new(0.75, 0, 0, 40),
BorderSizePixel = 0
})
buttonRule.Parent = containerRule -- Hijo de la regla de contenedor
-- Condición de consulta (#WideContainer)
local queryCondition = Instance.new("StyleRule")
queryCondition.Selector = "::StyleQuery #WideContainer"
queryCondition:SetProperty("MinSize", Vector2.new(400, 0))
queryCondition.Parent = containerRule -- Hijo de la regla de contenedor
-- Regla que se aplica cuando la condición está activa (@WideContainer)
local queryStyle = Instance.new("StyleRule")
queryStyle.Selector = "@WideContainer Frame > TextButton" -- Selector hijo
queryStyle:SetProperty("BackgroundColor3", Color3.fromHex("CC0033"))
queryStyle.Parent = containerRule -- Hijo de la regla de contenedor
-- Crear instancias
local container = Instance.new("Frame")
container.Size = UDim2.new(0.8, 0, 0, 200)
container.Parent = screenGui
local button = Instance.new("TextButton")
button.Text = "Menú Principal"
button.Parent = containerRoblox también proporciona consultas integradas que se mapean directamente a estados globales del entorno, como ViewportDisplaySize o ReducedMotionEnabled. Estas no requieren una definición de ::StyleQuery y se pueden usar directamente con un prefijo @.
| Característica de medios CSS | Selector de consulta de estilo de Roblox |
|---|---|
| (max-width: 600px) | @ViewportDisplaySizeSmall |
| (min-width: 601px) and (max-width: 1200px) | @ViewportDisplaySizeMedium |
| (min-width: 1201px) | @ViewportDisplaySizeLarge |
| (pointer: fine) | @PreferredInputKeyboardAndMouse |
| (pointer: coarse) | @PreferredInputTouch |
| (any-pointer: coarse) | @PreferredInputGamepad |
| (prefers-reduced-motion: reduce) | @ReducedMotionEnabledTrue |
| (prefers-reduced-motion: no-preference) | @ReducedMotionEnabledFalse |
.container {
container-type: inline-size;
background-color: rgba(0, 0, 34, 0.5);
}
@media (prefers-reduced-motion: reduce) {
.container {
background-color: rgba(0, 0, 34, 1);
}
}<div class="container" style="width: 80%; height: 200px;">
</div>-- Regla de contenedor
local containerRule = Instance.new("StyleRule")
containerRule.Selector = "Frame" -- Selector de clase de Roblox
containerRule:SetProperties({
BackgroundColor3 = Color3.fromRGB(0, 0, 34),
BackgroundTransparency = 0.5,
BorderSizePixel = 0
})
containerRule.Parent = coreSheet
-- Consulta integrada
local motionRule = Instance.new("StyleRule")
motionRule.Selector = "@ReducedMotionEnabledTrue Frame"
motionRule:SetProperty("BackgroundTransparency", 0)
motionRule.Parent = containerRule -- Hijo de la regla de contenedor
-- Crear instancias
local container = Instance.new("Frame")
container.Size = UDim2.new(0.8, 0, 0, 200)
container.Parent = screenGuiVariables
CSS te permite declarar y referenciar variables a lo largo de un sistema de estilo. Roblox logra esto a través de tokens y el sistema de atributos de instancia. Usando $ como prefijo, puedes referenciar atributos declarados en una cadena de herencia de StyleRule o StyleSheet al establecer propiedades de estilo.
:root {
--button-bg-color: #335FFF;
--button-text-color: #E1E1E1;
}
button {
background-color: var(--button-bg-color);
color: var(--button-text-color);
}<button>Menú Principal</button>local rule = Instance.new("StyleRule")
rule.Parent = coreSheet
-- Establecer tokens de hoja de estilo usando atributos
coreSheet:SetAttribute("ButtonBgColor", Color3.fromHex("335FFF"))
coreSheet:SetAttribute("ButtonTextColor", Color3.fromHex("E1E1E1"))
rule.Selector = "TextButton" -- Selector de clase
rule:SetProperties({
BackgroundColor3 = "$ButtonBgColor",
TextColor3 = "$ButtonTextColor"
})
-- Crear botón
local button = Instance.new("TextButton")
button.AutomaticSize = Enum.AutomaticSize.XY
button.Text = "Menú Principal"
button.Parent = screenGuiTransiciones
Las transiciones de CSS te permiten animar valores de propiedades durante una duración establecida. Puedes lograr esto en Roblox estableciendo transiciones de propiedades en una StyleRule a través de SetPropertyTransition() (individual) o SetPropertyTransitions() (múltiples).
button {
background-color: #335FFF;
color: #E1E1E1;
width: 15%;
height: 40px;
border: none;
transition:
background-color 1s ease-out,
transform 1.25s ease-out
}
button:hover {
background-color: #33AAFF;
transform: rotate(-5deg);
}<button>Menú Principal</button>-- Regla de botón
local buttonRule = Instance.new("StyleRule")
buttonRule.Selector = "TextButton" -- Selector de clase de Roblox
buttonRule:SetProperties({
BackgroundColor3 = Color3.fromHex("335FFF"),
TextColor3 = Color3.fromHex("E1E1E1"),
Size = UDim2.new(0.15, 0, 0, 40),
BorderSizePixel = 0
})
-- Establecer comportamientos de transición de propiedades
buttonRule:SetPropertyTransitions({
BackgroundColor3 = TweenInfo.new(1, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out),
Rotation = TweenInfo.new(1.25, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out)
})
buttonRule.Parent = coreSheet
-- Regla de hover de botón
local hoverRule = Instance.new("StyleRule")
hoverRule.Selector = "TextButton:Hover" -- Selector de estado
hoverRule:SetProperties({
AutoButtonColor = false,
BackgroundColor3 = Color3.fromHex("33AAFF"),
Rotation = -5
})
hoverRule.Parent = coreSheet
-- Crear botón de texto
local button = Instance.new("TextButton")
button.Text = "Menú Principal"
button.Parent = screenGuiAnidación y fusión
Tomando un concepto de SCSS, StyleRules se pueden anidar juntos y sus selectores se fusionarán.
#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;
}
}
}<div id="menu-frame">
<button>Encantos</button>
<button>Mana</button>
<button>Rollos</button>
</div>-- Regla de marco de menú
local menuFrameRule = Instance.new("StyleRule")
menuFrameRule.Selector = "#MenuFrame"
menuFrameRule:SetProperties({
BackgroundColor3 = Color3.fromHex("000022"),
Size = UDim2.new(0.25, 0, 0, 200),
AutomaticSize = Enum.AutomaticSize.Y
})
menuFrameRule.Parent = coreSheet
-- Regla de diseño de menú
local menuLayoutRule = Instance.new("StyleRule")
menuLayoutRule.Selector = "::UIListLayout"
menuLayoutRule:SetProperties({
FillDirection = Enum.FillDirection.Vertical,
VerticalFlex = Enum.UIFlexAlignment.SpaceEvenly,
HorizontalAlignment = Enum.HorizontalAlignment.Center
})
menuLayoutRule.Parent = menuFrameRule -- Establecer la regla de marco de menú como padre
-- Regla de botón
local buttonRule = Instance.new("StyleRule")
buttonRule.Selector = "> TextButton"
buttonRule:SetProperties({
BackgroundColor3 = Color3.fromHex("335FFF"),
TextColor3 = Color3.fromHex("E1E1E1"),
Size = UDim2.new(0.8, 0, 0, 40),
BorderSizePixel = 0
})
buttonRule.Parent = menuFrameRule -- Establecer la regla de marco de menú como padre
-- Regla de hover de botón
local buttonHoverRule = Instance.new("StyleRule")
buttonHoverRule.Selector = ":Hover"
buttonHoverRule:SetProperties({
AutoButtonColor = false,
BackgroundTransparency = 0.5,
TextTransparency = 0.5
})
buttonHoverRule.Parent = buttonRule -- Establecer la regla de botón como padre
-- Crear marco padre
local menuFrame = Instance.new("Frame")
menuFrame.Name = "MenuFrame"
menuFrame.Parent = screenGui
-- Crear botones dentro del marco
local button1 = Instance.new("TextButton")
button1.Text = "Encantos"
button1.Parent = menuFrame
local button2 = Instance.new("TextButton")
button2.Text = "Mana"
button2.Parent = menuFrame
local button3 = Instance.new("TextButton")
button3.Text = "Rollos"
button3.Parent = menuFrame