How to perfectly auto-resize textlabel's and their text!

  • Let me know if someone has made this tutorial already!

(Intended for text inside a Y axis only scrolling frame, although it will probably work with a normal frame.)

This tutorial will teach you how to make a textlabel auto-resize itself and its text, with the final product being that the text stays the same size ratio no matter how much text you have, and no matter what device your on.

Example:

Alright, lets set up!

  1. Setting up scrolling frame
    a) Make sure you have some UI to work on, containing a ScrollingFrame.
    b) Then, make your scrolling frame’s AutomaticCanvasSize set to Y.
    Also make sure CanvasSize is set to {0, 0},{0, 0}.

  2. Setting up TextLabels
    a) Insert a TextLabel into the ScrollingFrame and make sure it’s size is in Offset only, and it’s position is in Scale (I chose {0, 0},{0, 0}, not sure how others positions work with it.)
    Keep the anchor point the same (0,0), along with the position ({0, 0},{0, 0}).
    b) Copy the TextLabel created above, this is going to be our reference for size later.
    c) This time, make the size in Scale only (i did 1,1)

Now, for the fun part! scripting.

  1. Start by creating a LocalScript inside our first TextLabel.
  2. Now, lets define some things.
    a) local cc = workspace.CurrentCamera - We will use this to get the screen size.
    b) local textserv = game:GetService("TextService") - This service will help some calculations.
    Also, we need to define our UI elements, make sure to define TextLabel (the second one we made) - we don’t need to reference our first, because it is the parent of the script. Also define your ScrollingFrame
local scrollingframe = ...
local textlabelref = ...

d) Full Definitions:

local cc = workspace.CurrentCamera
local textserv = game:GetService("TextService")

local max_px_size = Vector2.new(math.huge, math.huge)
local sf = ...
local textlabelref = ...
  1. Creating the main function
function updateTextSize()
	local sizeratio = 0.15 -- The size of the text, experiment! (Below 1)
	local refsize = textlabelref.AbsoluteSize -- The size of our reference text.
	local sfsize = sf.AbsoluteSize -- The size of our ScrollingFrame
	
	local yoffset = sfsize.Y -- How many pixels deep the ScrollingFrame is.

	script.Parent.TextSize = math.clamp(yoffset * sizeratio, 1, 100) -- Setting the text size based on our ratio and the depth of the scrolling frame.

	local gettxtboundsparams = Instance.new("GetTextBoundsParams") -- Params for size calculations

    -- Self Explanatory
	
	gettxtboundsparams.Text = script.Parent.Text
	gettxtboundsparams.Font = Font.new(("rbxasset://fonts/families/" .. script.Parent.Font.Name .. ".json"), Enum.FontWeight.Regular, Enum.FontStyle.Normal)
	gettxtboundsparams.Size = script.Parent.TextSize
	gettxtboundsparams.Width = textlabelref.AbsoluteSize.X

	local txtsize = textserv:GetTextBoundsAsync(gettxtboundsparams) -- Performing the calculation.

	script.Parent.Size = UDim2.new(0, txtsize.X, 0, txtsize.Y) -- Setting the text size!
end
  1. Detecting changes
script.Parent.Changed:Connect(function(property) -- When a property changes in the main TextLabel.
	if property == "Text" then -- If the property is the text string.
		updateTextSize()
        -- Call our function.
	end
end)
cc.Changed:Connect(function(p) -- When a property changes in the CurrentCamera
	if p == "ViewportSize" then -- If the property is the screen size.
		updateTextSize() -- Call our function.
	end
end)

-- Also, at the end of this script, we need to initially update our text size.
updateTextSize()
  1. Conclusion
    Final Script:
-- Jhettblocks789 18/08/2024
local cc = workspace.CurrentCamera
local textserv = game:GetService("TextService")

local max_px_size = Vector2.new(math.huge, math.huge)
local sf = ...
local textlabelref = ...

function updateTextSize()
	local sizeratio = 0.15 -- The size of the text, experiment! (Below 1)
	local refsize = textlabelref.AbsoluteSize -- The size of our reference text.
	local sfsize = sf.AbsoluteSize -- The size of our ScrollingFrame
	
	local yoffset = sfsize.Y -- How many pixels deep the ScrollingFrame is.

	script.Parent.TextSize = math.clamp(yoffset * sizeratio, 1, 100) -- Setting the text size based on our ratio and the depth of the scrolling frame.

	local gettxtboundsparams = Instance.new("GetTextBoundsParams") -- Params for size calculations

    -- Self Explanatory
	
	gettxtboundsparams.Text = script.Parent.Text
	gettxtboundsparams.Font = Font.new(("rbxasset://fonts/families/" .. script.Parent.Font.Name .. ".json"), Enum.FontWeight.Regular, Enum.FontStyle.Normal)
	gettxtboundsparams.Size = script.Parent.TextSize
	gettxtboundsparams.Width = textlabelref.AbsoluteSize.X

	local txtsize = textserv:GetTextBoundsAsync(gettxtboundsparams) -- Performing the calculation.

	script.Parent.Size = UDim2.new(0, txtsize.X, 0, txtsize.Y) -- Setting the TextLabel size!
end

script.Parent.Changed:Connect(function(property) -- When a property changes in the main TextLabel.
	if property == "Text" then -- If the property is the text string.
		updateTextSize()
        -- Call our function.
	end
end)

cc.Changed:Connect(function(property) -- When a property changes in the CurrentCamera
	if property == "ViewportSize" then -- If the property is the screen size.
		updateTextSize() -- Call our function.
	end
end)

-- Also, at the end of this script, we need to initially update our text size.
updateTextSize()

Let me know if I made any errors in this tutorial! - Including if i did unnecessary stuff.

Hopefully, you should have dynamically updating UI in your ScrollingFrame that stays the same size ratio across all screens.

10 Likes

Can u pls show me how this works??? Pleaseeeeeeeeeee

1 Like

yeah when i get the chance ill add a clip showing how it works

1 Like

Right now, how im doing this is by checking the textscaled value, then add a uipadding to the textlebal or button

there’s a simple clip just showing basically how it works now.

Could this work with no scrolling frame?

Yeah, pretty sure it could, just swap the ScrollingFrame out for a real frame.

Is this actually correct? Or should i use your one?