Every time someone asks how to make a Roblox GUI work on mobile, the answer is the same. Switch everything from Offset to Scale, add a UIAspectRatioConstraint, maybe grab a plugin that converts it for you.
I did that for a while. My buttons fit on a phone, sure, but the carved corners on my 9-slice panels got squashed and the outlines stayed thick while the buttons around them shrank. It looked broken in a way that's hard to explain until you see it.
The first time I tried my own UI on a phone, it was huge. A 200 pixel button that looked fine on my monitor took half the screen. And I think that's what happens to most of us without noticing, you size everything for your own screen, and every other device gets whatever is left.
So I went the other way. I lay out everything in plain pixels at 1280x720, and I put one UIScale on the root frame that follows the window size:
local DESIGN = Vector2.new(1280, 720)
local function apply(root: GuiObject)
local scale = Instance.new("UIScale")
scale.Parent = root
local camera = workspace.CurrentCamera
local function update()
local v = camera and camera.ViewportSize
if not v or v.X == 0 or v.Y == 0 then return end
-- smaller of the two ratios, otherwise it spills off wide or tall screens
scale.Scale = math.min(v.X / DESIGN.X, v.Y / DESIGN.Y)
end
update()
camera:GetPropertyChangedSignal("ViewportSize"):Connect(update)
return scale
end
A button that takes a fifth of your monitor takes a fifth of the phone. Nothing gets stretched because the whole screen shrinks as one piece. And I was surprised by this one: UIStroke thickness and 9-slice borders scale along with it. I checked in game, I didn't have to touch them.
It's not quite that simple though. Here's what broke along the way.
Stuff that bit me
You can't put a UIScale on a ScreenGui. Roblox just doesn't allow it. It has to go on the Frame that holds everything.
If your buttons already use a UIScale for hover (mine do, because animating Size shoves the neighbours around), the two multiply. A 1.04 hover inside a 0.5 screen scale ends up at 0.52. That's fine once you know. I just don't add a third one on top.
workspace.CurrentCamera can get swapped for a new camera. When that happens your ViewportSize connection is listening to a camera nobody uses anymore, and the UI stops following the window. You have to reconnect:
workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
camera = workspace.CurrentCamera
update()
if camera then
camera:GetPropertyChangedSignal("ViewportSize"):Connect(update)
end
end)
The last one took me the longest. For panels that need the real usable height, I first measured ScreenGui.AbsoluteSize and listened to its changes. When I shrank the play area, the signal fired zero times, and when it did fire later it gave me the old size. The camera's viewport does fire, but it counts space the ScreenGui can't use. What finally worked was listening to the camera, reading the ScreenGui, and waiting a frame so the layout settles:
camera:GetPropertyChangedSignal("ViewportSize"):Connect(function()
task.defer(update) -- update reads gui.AbsoluteSize here
end)
Should you clamp it?
I don't. The whole point is that a size you pick on one screen holds on every other one, and a max value breaks that on big monitors. If you have a weird case, clamp that one screen.
One real limit this makes your layout smaller on a phone, it doesn't rearrange it. For a shop or an inventory that's what I want. If your mobile version needs a different layout, you'll need a second one anyway.
The kit I built on top of this
All of this is baked into UI Pack Plus, a free UI kit I made for Roblox. It has 8 finished screens (main menu, shop, inventory, character sheet, options, trade, a confirm popup and a HUD) plus the parts to build your own, with hover and click animations already working.
The scaling rides on a tag instead of a script, so when you drag a screen into StarterGui it keeps working. Nothing to install on top.
Setup is quick. Drag UIPackPlus.rbxm into Studio, then move ShardUI into ReplicatedStorage and ShardUIPack into StarterGui. People miss that second part a lot, and nothing shows up until both are in the right place. After that, open ShardUIPack > Kits and copy whichever screen you want.
It's free, and you can use it in games that make Robux: https://zerodev.tools/assets/ui-pack-plus
There's a setup video too if you'd rather watch: https://youtu.be/efZowS5hAPc
Anyone here still doing everything in Scale? I'd honestly like to know if there's a case where it beats this.


Top comments (0)