How to 'offset' a UI from corner evenly using scale?

It’s easier if I first show you what I mean:

Screenshot 2023-01-12 165330

Lets say I want to position that ImageButton (AnchorPoint: 1, 1) at 0.95 on Y, and I want the space between it and the right side of the screen to be the same amount of space (in pixels) that’s between it and the bottom of the screen, but without using offset, just scale, obviously there’s no issue when using offset.

This has been on my mind for a long time, but the only solution I ever came up with is what you see in the screenshot above - putting another UI element in the corner, setting it’s height in scale, using AspectRatio, then adding the actual element of interest inside of the first element.

While this works, it’s kind of hacky and ugly to work with, both on the scripting and UI side. Scale becomes the scale of the Parent (who’s size is probably very small), and not the Viewport, and so on.

I’m wondering if any of you have a better approach?

Why do you want to avoid using offset?

Inconsistent pixel densities on different screens, but more importantly, I recently realized that anything set in pixels will double on mobile. Let’s say you have a phone with 1080p on Y, you make an element 540p tall, and you’d expect it to take up half the screen, but it will take up the whole screen.

I don’t think this is just a Roblox thing though: if you go to your phone’s settings and check the resolution (or just Google it), and then on the phone go to a website like whatismyscreenresolution.net you’ll get half of what it actually is.

I’ve verified this on 2 different phones, I don’t know if it’s the case with all of them, or why it happens, but it makes using offset really really messy in my mind, like differing pixel densities weren’t enough. So it’s much safer to stick to scale entirely. This is my personal take on the situation though, some people might not mind it.

1 Like

I see.

I run into the same problem when creating my UIs. Currently, I create the interface and use UIScale to scale down or up the UI depending on the resolution.

As for your issue, I don’t think there is a way to do that apart from the current method or using some code.

1 Like

pretty sure it’s because roblox does not support full resolution on phones. if you go into the device emulator in studio, the phone resolutions given are lower than the actual screen size for that device.

1 Like

Hi, what you’re looking for is the UI element called UIPadding. It can offset your UI frame from the edge of the screen, by scale or offset.

The old method was creating a ParentFrame with the size 0.9,0,0.9,0 with anchorpoint being 0.5,0.5 and position being 0.5,0,0.5,0.

You can use the method below, to make sure that the UI object you’re trying to manipulate, is the same distance away from the screen, no matter the size of the device. Below is the sample for scaling UIStrokes, but you can use it for any property. This will not do so you get the EXACT same distance vertical & horizontal. But you can setup your UI so it is exactly like you want it, and then use the code below to scale it to all screen sizes.

local Studio_Viewport_Size = Vector2.new(1920,1080) -- Make sure this is your own monitor size, since this is the scale you see when editing UIs.
local Camera_Viewport_Size = workspace.CurrentCamera.ViewportSize -- Device screen size. This is used to determine the players device size.
local Studio_Viewport_Average = (Studio_Viewport_Size.X + Studio_Viewport_Size.Y)/2
local Camera_Viewport_Average = (Camera_Viewport_Size.X + Camera_Viewport_Size.Y)/2
local function AdjustUIStroke(UIStroke)
	local Ratio = UIStroke.Thickness / Studio_Viewport_Average
	UIStroke.Thickness = Camera_Viewport_Average * Ratio
end

Edit: Well, the code above wont work, since not all devices has 16:9 ratio. I am uncertain of the result you would get by trying it out.

2 Likes

Offset is not your enemy.

The most widespread misconception I’ve seen on this forum is that “offset is bad because it doesn’t scale well on mobile” or “buttons will be too small on 4k monitors,” but this is not true.

Offset represents “device-independent pixels,” which are not the same as pixels. Device-independent pixels (DP) represent a specific pixel size based on your device’s scale setting. The website you used returned an inaccurate result because it read the number of DPs that your device displays.


(Image source)

Take the Windows taskbar (or similar), for example. The taskbar appears identical in size for both 1080p and 4k monitors, independent of the device’s pixels. This is done for UX and accessibility reasons, as interfacing with a small or obnoxiously big taskbar would be a pain. Similarly, if you abandon offset entirely and start misusing scale, your UI becomes displeasing and causes many accessibility issues that DPs are meant to fix.

Unfortunately, due to Roblox’s lack of clarity about offset, many games (popular ones are no exception) suffer from scale-only UI made with AutoScale or similar plugins that produce UX issues. For example, buttons would appear abnormally large on large displays (Xbox, for example). On tiny displays (older iPhone models), buttons would be too small to press on the first try. Worst of all is the accessibility ignorance that comes out of this. People who have their scale set large suffer significantly from this popular malpractice.

In your case, offset will work perfectly for what you’re trying to accomplish. You are correct in that your method is hacky and ugly. It will also cause performance issues, as AspectRatio updating is used for every anchored element, not to mention you are using an unnecessary additional element that could be used elsewhere.

You should only use scale when you need a size/position percentage of a container you know the size of (not the viewport, except when you want to position elements in a corner or the center). For example, anchoring (what you’re trying to do) and expressing progress (progress bars, scroll bars) are good use cases for scale. You should never use scale for the size of menus, grids, buttons, or text.

Using a UI library like Fusion or Roact makes UI development, especially with offset, much more manageable. With Fusion (I’ve never used Roact), I’m able to react dynamically to different screen sizes. If I want a different layout for smaller devices, I can design one and apply it only if the viewport size decreases to a certain amount. This is how developing with offset can prove decisive if you use the right tools.

5 Likes

Offset represents “device-independent pixels,” which are not the same as pixels.

Well that clears up a lot, wish I knew that earlier. Now that I think about it, when I was using 125% scale on my PC and measured things in pixels (zooming in on a screenshot or using one of the Windows PowerToys) it didn’t match up with offset. When I went back to 100% scale it matched, but I didn’t look into the ‘why’ of it.

Thank you for the effort you put into the reply, things make sense now.

However, me being a long time developer (granted, not a UI designer) and not knowing about this, and even now not having the slightest idea how to adjust this on my phone (if possible at all) says a lot. I could not expect the average player to be aware of this/adjust it on their device either.

Now if I was primarily a UI designer and it was something I enjoyed spending my time on, then I would definitely look into Fusion or Roact like you suggested. But since I don’t enjoy making UI that much, having to make multiple layouts sounds like a nightmare.

So it’s unreasonable to ask/expect users to adjust their DPI settings, and too much work (for me personally) to make and maintain multiple layouts. I don’t see a third way out other than sticking to scale.

For mitigating the too small/large issue you mentioned, UISizeConstraint works nicely. Most of the time there’s no need to reach for hacky methods with scale, this was just an oddball that I was wondering about. But just using offset (without Fusion/Roact) and wondering things like ‘hmm, is this gonna take up 10% of the screen or 20% for someone’, ‘is this gonna stay close to the edge or be half way up the screen’, ‘are these things going to overlap for someone with low DPI’ is a no-go for me.

I get what you’re saying about accessibility too, it’s a fair point, but what you’re suggesting is asking too much from someone who treats UI as ‘okay, let’s get this over with’ most of the time. I don’t mean to sound insensitive to people’s needs, and I’m not, but as someone who’s trying to make a living I’m primarily trying to cater to the majority of players, I can’t afford to put in 50% more hours to appease 1-2% of the player base. I can’t say the percentage for sure, but I assume it’s low. Exactly like I don’t cater to console users, there’s just 3% of them, and it takes a lot of effort to take console into consideration with both UI and scripting, so I simply never do it, I don’t tick the console checkbox.

But, that’s why it’s great having a community, folks like you, other UI/UX folks who are passionate about what they do and will go the extra mile, make those multiple layouts, at least for those who can afford to pay. Like I’d go the extra mile in scripting, make sure things run smoothly, expect the unexpected circumstances… just not for console :stuck_out_tongue:

I think I have something in mind (requires localscript + renderstepped)

--put references to the UI element up here
--put this below into a RenderStepped repeat loop
UI.Size = UDim2.new(1, -workspace.Camera.ViewportSize/X, 1, -workspace.Camera.ViewportSize/X)--decide what X is

I think you slightly misunderstood what @CriticalDucky said.


The purpose of a user’s DPI settings is itself for accessibility, so that you don’t have to manually adjust UI for different screen sizes.

For example, imagine the following scenario: Person A has a 1080p monitor, while Person B has a 4k monitor, but both monitors have the same physical size; the 4k monitor simply has twice the pixel density.

On both monitors, you would want UI to appear exactly the same; you wouldn’t want to have UI on the 4k monitor to be smaller simply because the pixels are smaller.

To mitigate this, both monitors will have different UI scales, determined by a setting built into the operating system. The 1080p monitor may have a 100% scale, in which case one unit of measurement (or a single unit of “offset”) is a single pixel, while the 4k monitor has 200%, in which case a single unit of measurement (or a single unit of “offset”) is two pixels.

Here’s another scenario: you have a normal monitor and a TV connected to your computer, and they are both displaying your screen. They both have the same pixel density; however, your TV is larger and further away. As a result, if UI (say, a button) was the exact same physical size on both screens, the button would look much smaller on your TV since it’s further; so on the TV, you would have a larger UI scale (a single unit of “offset” is more pixels than a single unit of “offset” on your monitor) to make the button bigger and therefore equally easy to see as on your monitor.


Because of this system, a UI designer like you does not have to worry about changing the size of UI based on screen size, since the operating system will do it for you. Take the Windows taskbar, for example. Its width will always take up the entire screen; however, it has a constant height. If you magically doubled the physical height of your monitor, the windows taskbar’s height would NOT change because that would look weird. However, if you doubled the width of your monitor, the taskbar would adjust to take up the whole width of your screen.

However, if you doubled the scale of your monitor (e.g. change it from 100% to 200%), the taskbar will double in height because the monitor will now assume it’s smaller or further away, and adjust to make it easier to see by increasing how many pixels are a single unit of measurement. But the number of units in the height of the taskbar does not change.

You can think of the taskbar’s width as using scale while its height uses offset. The width changes by screen size, while the height doesn’t. However, to make UI look nice on screens that have high DPI or are distant, the number of pixels per unit will increase with higher scales. The “offset” used in the taskbar does not change when the UI’s scale changes; it is simply that each unit of “offset” changes in size automatically. (This also illustrates how Roblox “scale” and “offset” should be used together, not one or the other.)

This is intentional and ensures UI is easily displayed. You should not try to change offset based on screen size to make a width a set amount of pixels, because then it will look smaller on high-resolution screens (like 4k monitors or phones) or on distant ones (like TVs). You should keep the offset values in your UI the same, and the device’s UI scale will automatically ensure that the offset looks good no matter the resolution or distance.

So when you say…

…you’re right. Users will have their DPI at a setting where UI looks reasonable at the distance and pixel density of their screen, as it should be. As a UI designer, you should not change offset by screen size; you should keep it constant so that the user’s device can automatically make the size of offset look good. (For example, text size is ALWAYS measured in offset, and a device’s scale setting will make sure the text is legible but not too big, whether it be a phone or a TV.)

This is perfectly okay. Though some developers like to make separate layouts for different screen sizes, in most cases you don’t need to. To ensure that layouts look good for all screen sizes, the general rule of thumb is to design your UI for mobile (since it’s the smallest screen size), and if it’s designed correctly it should upscale perfectly to any screen size. Offset will automatically be adjusted to be the right size on all devices, whether it be a phone, desktop, or TV.

Let me know if you want anything clarified.

2 Likes

I’m still a bit confused as to how offset should fix these issues (without multiple layouts). So I’ll just move on to a practical recent example:

I worked on some UI for an employer, made some menus, focused on making everything large enough for mobile, so I set the height of the menus to 0.8 and width constrained to height. Now I didn’t realize (because of the output window and all open in Studio) that 0.8 is huge for PC, and was informed that I should make it smaller. So for whatever reason I decided to test my luck with pixels (not knowing about DPI), I checked my phone’s resolution, it goes up to 1080p but I had it set to 720p or so, so I thought: alright, 500px looks good on PC, and with my phone being 720p it sounds about right for mobile as well, with room to spare for smaller resolution phones. Sadly I didn’t check things first, and I didn’t simply switch the containers to offset and kept everything inside on scale, I switched ALL descendants to offset thinking it’s gonna be fine. So I wasted some 7 hours (not a UI person, so I’m slow at these things) just to realize the main menu is now larger than my screen and my employer’s screen (who’s phone also has sufficient resolution), and all the other stuff I changed is also too large.

So then I wasted some more hours setting all descendants of the main menu back to scale, set the container to 0.8 scale and added a UISizeConstraint with 500px max and realized it’s a pretty good solution, all I was missing initially was the Constraint. Now the height will never exceed 80% of the screen, and if 80% exceeds 500px (or, well… DPs) it will stay constrained to that. And if someone has a 1080p screen but uses 200% scale to see better, then the menu can still grow to take up to 80%.

Now I don’t see how sticking to offset entirely would be a better solution here, as I’ve already tried that and it was overflowing. There might be the case of ‘well what if somebody still doesn’t see it well at 0.8’ but the thing is, if it overflows, then the menu is useless. If I decided ‘okay I’m gonna tailor everything to the smallest possible screen (lowest DPI)’ - for argument’s sake let’s say 360dp (like my phone, but there’s probably smaller) - so I want the main menu to be 0.8 of that, so that’s 288 offset, and now for someone like me who uses a 1080p screen at 100% scale, that’s almost 50% less than what actually looks good and readable.

Am I missing something? I really don’t see how sticking to scale entirely takes care of this.
CriticalDucky called it

The most widespread misconception

but I’m thinking it wouldn’t be so widespread if it was a misconception, really, I’d be ecstatic if I could always use just offset without issues, it would make UI work so much faster.

Or is the answer that I shouldn’t be using 100% scale on my PC if things look too small’? Then it sort of circles back to me expecting all users to know about/use scale settings on their device, or making a custom scale setting inside the game (which I’ve seen done).

Again, am I missing something? How would use offset to make a menu look good on both my 720p - 200% scale phone, and my 1080p - 100% scale monitor, without changing the scale setting on either device?

You’re both right.

What @CriticalDucky is saying is that it is wrong to use only scale, since offset is more appropriate in many cases. What you are saying is that using only offset makes it difficult to correctly size and position things. These are both true.

That’s because both offset and scale should be used together to design UI. Sometimes offset will be more appropriate, while sometimes scale will be more appropriate. In general, scale should be used when you want things sized/positioned relative to the size of the screen (such as when centering menus) while offset should be used when you want things to look the same size to the user, without looking too large on big screens and too small on small screens (such as buttons, margins, and text).


In your example when you were making some UI for an employer, you actually did the right thing: you used scale and offset together. The fact is, some screens (like monitors) are larger than others (like phones). You obviously want your UI to fit the screen, and if you have a larger screen, it’s natural to want to take advantage of that to make the UI larger; though of course making it too large will be overwhelming to the user. You used scale to make the menu change size based on the screen, but you used offset in the size constraint to limit that size if it gets too big.

Just to nitpick, I would make a couple of tweaks to that menu sizing. I would use offset in conjunction with scale for the sizing to make the margins stay the same size on all screen sizes, assuming the UI is not too big.

If I understood your example correctly, this is likely very similar to the example you gave. The UI increases in size with the screen but stops growing if it gets too big.

The difference here is that the margins do not change size with the screen (that is until the screen gets too large). The way I do this is by using scale and offset together. In the above frame, the anchor point is 0.5, 0.5 and the position is {0.5, 0},{0.5, 0}, which ensures it is centered. The size is {1, -150},{1, -20}. The 1s are scale and make the UI’s size based on the screen size. However, notice the negative offset. This decreases the size of the UI (creating margins) that are a fixed size. Of course, the UI stops growing at a certain size because I have added a size constraint, as you did.


Let me now address your original post.

Since you want the frame to be positioned on the bottom right of the screen, you will use scale for that. But since you want the margin between the frame and the screen’s edge to be a fixed size regardless of screen size, you want to use offset for that. Here’s what you’re looking for:

Here’s what’s going on here: the anchor point is 1, 1 and the position is {1, -20},{1, -20} The anchor point and the 1s in scale ensure that the frame is aligned to the bottom right of the screen; however, the -20 offsets subtract a set distance from the position to create a 20 pixel* margin. (*It’s typically okay to refer to these as pixels even though they may not always correspond to actual pixels.)

As you can see, it is very helpful to use both scale and offset when designing UI. In your case, you neither want to use only scale nor only offset; you need both. Though offset can be frustrating, it is very useful when used correctly, and it is the best choice here.

Of course, you want to make sure that what you have looks good on mobile, since it has the smallest screen and is the hardest to use, so you want to make sure your UI is easy to use there. If you designed the UI right, it should scale up nicely to larger monitors. Of course, the actual physical size of offset may change because of DPI and such, but you should assume that such differences make sure your UI looks good on devices of different sizes (e.g. a set amount of offset will look larger on a TV but smaller on a phone).

Finally, I just want to add that you don’t have to worry about whether your DPI settings are correct. If your device looks fine, then simply designing your UI to look good on that device will automatically be a good size with your settings. Offset will then be sized correctly on other devices. The only concern with changing screen sizes and such is whether or not your UI was designed to look good on other sizes. (A classic example of failing to take into account other screen sizes is if someone centers a frame with offset. It will no longer be centered once you resize the screen.) It is important when designing UI to take into account how the UI’s appearance will change when the screen size changes (as you did when you made the menu use scale but used a size constraint to make the UI not be overwhelming for large screens). However, so long as you are designing your UI mobile first (as I mentioned before), you generally shouldn’t have to worry too much about text or buttons that use offset being too small or too large on other devices.


If you want the place file with my examples, here it is.

ScaleVsOffset.rbxl (40.9 KB)

If you have any other questions, let me know!

2 Likes

In the example place that you gave using offset to make it an equal offset from the corner it scales bad with other devices as im using an aspect ratio constraint to make it scale with all devices. I check with this on my phone and the square is clipping into the corner.