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:

  1. Right-click StarterPlayer โ†’ StarterPlayerScripts and insert a LocalScript.
  2. 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:

LocalScript in StarterPlayer
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 = menuFrame

This 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:

Expanded Script with Title and Buttons
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.

๐Ÿ’ก Tip โ€” Use the same gradient on related UI elements to tie your menu together visually. A consistent color scheme makes the menu feel polished.

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:

Three-Color Gradient Example
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 = myFrame

The 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:

Animated Gradient Script
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
end

This 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.

๐Ÿ’ก Tip โ€” Keep animations subtle on menus. A slow rotation (0.02โ€“0.05 second intervals) is more professional than fast spinning.

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 = 1 instead.
  • 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:

Complete Production Menu Script
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.