A main menu is the first thing players see. UIGradient makes it look polished by blending colors instead of using flat blocks. Let's build a complete menu from scratch with working code.
What Is UIGradient?
UIGradient is an object that smoothly transitions between two or more colors across a UI element. You add it to any Frame or Button, point it in a direction, and it handles the blending. It works in one of four directions: horizontal, vertical, or diagonal angles.
The key property is Rotation, which controls the angle (0โ360 degrees). Offset lets you shift where the gradient starts and ends. Color sequence controls which colors appear and where along the gradient.
Creating the Base Menu Frame
First, create the main Frame that holds everything. In Roblox Studio:
- Right-click StarterPlayer โ StarterPlayerScripts and insert a LocalScript.
- In that script, create the UI structure with a LocalScript. This is better than manually building it because you control every detail and can reuse the code.
Here's the script to build a simple menu background with gradient:
local PlayerGui = game:GetService("Players").LocalPlayer:WaitForChild("PlayerGui")
-- Create main menu frame
local menuFrame = Instance.new("Frame")
menuFrame.Name = "MainMenu"
menuFrame.Size = UDim2.new(1, 0, 1, 0)
menuFrame.Position = UDim2.new(0, 0, 0, 0)
menuFrame.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
menuFrame.Parent = PlayerGui
-- Add UIGradient to the frame
local gradient = Instance.new("UIGradient")
gradient.Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.fromRGB(30, 60, 120)), -- Dark blue
ColorSequenceKeypoint.new(1, Color3.fromRGB(100, 150, 200)) -- Light blue
})
gradient.Rotation = 45 -- Diagonal gradient
gradient.Parent = menuFrameThis creates a full-screen frame with a diagonal blue gradient. The ColorSequence lets you define multiple color stops. Keypoint.new(0, ...) is the start color, and Keypoint.new(1, ...) is the end color. You can add more keypoints in between for three-color gradients.
The Rotation property is in degrees. 0 = left-to-right, 90 = bottom-to-top, 45 = diagonal bottom-left to top-right.
Adding a Title and Buttons
Let's add a title and two buttons (Play and Settings) to the menu:
local PlayerGui = game:GetService("Players").LocalPlayer:WaitForChild("PlayerGui")
-- Main menu frame with gradient background
local menuFrame = Instance.new("Frame")
menuFrame.Name = "MainMenu"
menuFrame.Size = UDim2.new(1, 0, 1, 0)
menuFrame.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
menuFrame.Parent = PlayerGui
local gradient = Instance.new("UIGradient")
gradient.Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.fromRGB(30, 60, 120)),
ColorSequenceKeypoint.new(1, Color3.fromRGB(100, 150, 200))
})
gradient.Rotation = 45
gradient.Parent = menuFrame
-- Add UIAspectRatioConstraint to keep things centered
local aspect = Instance.new("UIAspectRatioConstraint")
aspect.Parent = menuFrame
-- Title text
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Size = UDim2.new(0, 400, 0, 80)
titleLabel.Position = UDim2.new(0.5, -200, 0.2, 0)
titleLabel.BackgroundTransparency = 1
titleLabel.Text = "MAIN MENU"
titleLabel.TextSize = 48
titleLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
titleLabel.Font = Enum.Font.GothamBold
titleLabel.Parent = menuFrame
-- Play button
local playButton = Instance.new("TextButton")
playButton.Name = "PlayButton"
playButton.Size = UDim2.new(0, 200, 0, 50)
playButton.Position = UDim2.new(0.5, -100, 0.45, 0)
playButton.BackgroundColor3 = Color3.fromRGB(50, 150, 80)
playButton.Text = "PLAY"
playButton.TextColor3 = Color3.fromRGB(255, 255, 255)
playButton.TextSize = 24
playButton.Font = Enum.Font.GothamBold
playButton.Parent = menuFrame
-- Add gradient to play button
local playGradient = Instance.new("UIGradient")
playGradient.Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.fromRGB(40, 120, 60)),
ColorSequenceKeypoint.new(1, Color3.fromRGB(80, 180, 120))
})
playGradient.Rotation = 90
playGradient.Parent = playButton
-- Settings button
local settingsButton = Instance.new("TextButton")
settingsButton.Name = "SettingsButton"
settingsButton.Size = UDim2.new(0, 200, 0, 50)
settingsButton.Position = UDim2.new(0.5, -100, 0.60, 0)
settingsButton.BackgroundColor3 = Color3.fromRGB(100, 100, 100)
settingsButton.Text = "SETTINGS"
settingsButton.TextColor3 = Color3.fromRGB(255, 255, 255)
settingsButton.TextSize = 24
settingsButton.Font = Enum.Font.GothamBold
settingsButton.Parent = menuFrame
local settingsGradient = Instance.new("UIGradient")
settingsGradient.Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.fromRGB(80, 80, 80)),
ColorSequenceKeypoint.new(1, Color3.fromRGB(140, 140, 140))
})
settingsGradient.Rotation = 90
settingsGradient.Parent = settingsButton
-- Button click handlers
playButton.MouseButton1Click:Connect(function()
print("Play button clicked!")
-- Load your game here
end)
settingsButton.MouseButton1Click:Connect(function()
print("Settings button clicked!")
-- Open settings menu
end)Now you have a menu with a title, two buttons, and gradients on everything. Each button has its own gradient to make them stand out. Notice how each gradient uses Rotation = 90 for a vertical blend, which works well for buttons.
Customizing the Gradient
UIGradient has a few key properties you'll adjust:
- Color: A ColorSequence that defines the colors and their positions. Use ColorSequenceKeypoint to add stops.
- Rotation: The angle in degrees (0โ360). 0 = horizontal left-to-right, 90 = vertical bottom-to-top.
- Offset: Moves the gradient position (X and Y offset). Useful for creating subtle animated effects.
- Transparency: Makes the entire gradient see-through. Use TransparencySequence if you need parts more transparent than others.
Here's how to create a three-color gradient:
local gradient = Instance.new("UIGradient")
gradient.Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.fromRGB(255, 0, 0)), -- Red
ColorSequenceKeypoint.new(0.5, Color3.fromRGB(255, 255, 0)), -- Yellow
ColorSequenceKeypoint.new(1, Color3.fromRGB(0, 255, 0)) -- Green
})
gradient.Rotation = 0 -- Horizontal
gradient.Parent = myFrameThe keypoint values (0 to 1) represent positions along the gradient. 0 is the start, 0.5 is the middle, and 1 is the end. This gives you precise control over where colors appear.
Animating Gradients
You can animate the gradient's offset or rotation to create movement. Here's a simple animation loop:
local gradient = -- your UIGradient object
-- Smoothly rotate the gradient
while true do
for i = 0, 360, 1 do
gradient.Rotation = i
wait(0.01) -- Update every 10ms
end
endThis spins the gradient in a full circle over a few seconds. For offset-based animation, do the same with the Offset property, which is a UDim2 value.
Performance Tips
UIGradient is lightweight, but here's how to keep your menu running smoothly:
- Avoid too many gradients: Each UIGradient is calculated by the GPU. 10โ15 gradients on screen at once is fine. 100+ can cause lag.
- Use solid backgrounds for invisible frames: If a frame doesn't need a gradient, don't add one. Set
BackgroundTransparency = 1instead. - Animate with care: If you animate rotation or offset, do it every 0.02 seconds or slower. Updating every frame is overkill.
- Test on mobile: Mobile devices have weaker GPUs. A menu that looks smooth on desktop might lag on phone. Always test.
Making It Production-Ready
Here's a complete menu script with error handling and better structure:
local PlayerGui = game:GetService("Players").LocalPlayer:WaitForChild("PlayerGui")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Function to create a button with gradient
local function createButton(parent, name, position, text, gradientColor1, gradientColor2)
local button = Instance.new("TextButton")
button.Name = name
button.Size = UDim2.new(0, 200, 0, 50)
button.Position = position
button.BackgroundColor3 = gradientColor1
button.Text = text
button.TextColor3 = Color3.fromRGB(255, 255, 255)
button.TextSize = 24
button.Font = Enum.Font.GothamBold
button.Parent = parent
local gradient = Instance.new("UIGradient")
gradient.Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, gradientColor1),
ColorSequenceKeypoint.new(1, gradientColor2)
})
gradient.Rotation = 90
gradient.Parent = button
return button
end
-- Create main menu
local menuFrame = Instance.new("Frame")
menuFrame.Name = "MainMenu"
menuFrame.Size = UDim2.new(1, 0, 1, 0)
menuFrame.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
menuFrame.Parent = PlayerGui
-- Background gradient
local bgGradient = Instance.new("UIGradient")
bgGradient.Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.fromRGB(30, 60, 120)),
ColorSequenceKeypoint.new(1, Color3.fromRGB(100, 150, 200))
})
bgGradient.Rotation = 45
bgGradient.Parent = menuFrame
-- Title
local title = Instance.new("TextLabel")
title.Name = "Title"
title.Size = UDim2.new(0, 400, 0, 80)
title.Position = UDim2.new(0.5, -200, 0.15, 0)
title.BackgroundTransparency = 1
title.Text = "ADVENTURE GAME"
title.TextSize = 54
title.TextColor3 = Color3.fromRGB(255, 255, 255)
title.Font = Enum.Font.GothamBold
title.Parent = menuFrame
-- Buttons
local playBtn = createButton(menuFrame, "PlayButton", UDim2.new(0.5, -100, 0.45, 0), "PLAY",
Color3.fromRGB(40, 120, 60), Color3.fromRGB(80, 180, 120))
local settingsBtn = createButton(menuFrame, "SettingsButton", UDim2.new(0.5, -100, 0.60, 0), "SETTINGS",
Color3.fromRGB(80, 80, 80), Color3.fromRGB(140, 140, 140))
local quitBtn = createButton(menuFrame, "QuitButton", UDim2.new(0.5, -100, 0.75, 0), "QUIT",
Color3.fromRGB(150, 50, 50), Color3.fromRGB(200, 100, 100))
-- Button handlers
playBtn.MouseButton1Click:Connect(function()
print("Starting game...")
menuFrame:Destroy()
-- Load game level
end)
settingsBtn.MouseButton1Click:Connect(function()
print("Opening settings...")
-- Show settings menu (create another frame)
end)
quitBtn.MouseButton1Click:Connect(function()
print("Quitting...")
game:Shutdown()
end)This script is modular and reusable. The createButton function saves you from repeating code. Each button does something when clicked. You can expand this by creating a settings panel, loading levels, or adding sound effects.
Remember: put this script in StarterPlayer โ StarterPlayerScripts as a LocalScript so it runs when each player joins. The UI will be local to their client and won't sync across other players.