Getting text height to size box correctly

You probably shouldn’t be using TextScaled if you want to achieve a chat system which automatically changes the size of frames depending on the amount of text. Instead of scaling the text, you want to change the size of the frame on the Y axis to account for the amount of text in the player’s message. In order to achieve this, you need to stick to one certain text size.


If you’re interested, here is how I calculate the size of my message frames:

local function measureSize(textObject)
	return TextService:GetTextSize(textObject.Text, textObject.TextSize, textObject.Font, Vector2.new(textObject.AbsoluteSize.X, 10000))
end

frame.Username.Size = UDim2.new(0, frame.Username.TextBounds.X, 0, 20)
frame.Message.Text = string.rep(" ", math.ceil(measureSize(frame.Username).X / TextService:GetTextSize(" ", frame.Username.TextSize, frame.Username.Font, Vector2.new(5000, 5000)).X) + 1) .. message
frame.Size = UDim2.new(1, 0, 0, measureSize(frame.Message).Y)
4 Likes
print(game:GetService('TextService'):GetTextSize(message, 16, Enum.Font.GothamSemibold, Message.AbsoluteSize))

Returns a different X value, but the Y value is consistenly 16

By using Message.AbsoluteSize you are restricting the text to only be as long as the message frame. You want to set the maximum Y value to a large number, here is an example of a Vector2 you should use:

Vector2.new(Message.AbsoluteSize.X, 10000)
1 Like
print(game:GetService('TextService'):GetTextSize(message, 16, Enum.Font.GothamSemibold, Vector2.new(Message.AbsoluteSize.X, 10000)))

Still returns 16 for Y value

local MessageFrame = Instance.new('Frame')
	MessageFrame.AnchorPoint = Vector2.new(0.5, 1)
	MessageFrame.BackgroundTransparency = 1
	MessageFrame.Position = UDim2.new(0.5, 0, 1, 0)
	MessageFrame.Size = UDim2.new(0.9, 0, 0.1, 0)
	
	local PlayerLabel = Instance.new('TextLabel')
	PlayerLabel.AnchorPoint = Vector2.new(0.5, 0.5)
	PlayerLabel.BackgroundTransparency = 1
	PlayerLabel.Position = UDim2.new(0, 0, 0.5, 0)
	PlayerLabel.Font = Enum.Font.GothamSemibold
	PlayerLabel.Text = tostring(speaker)
	PlayerLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
	PlayerLabel.TextSize = 16
	PlayerLabel.TextXAlignment = Enum.TextXAlignment.Left
	PlayerLabel.TextYAlignment = Enum.TextYAlignment.Top
	
	local Message = Instance.new('TextLabel')
	Message.AnchorPoint = Vector2.new(0.5, 0.5)
	Message.BackgroundTransparency = 1
	Message.Position = UDim2.new(0.5, 0, 0.5, 0)
	Message.Size = UDim2.new(0.95, 0, 0.9, 0)
	Message.Font = Enum.Font.GothamSemibold
	Message.Text = message
	Message.TextColor3 = Color3.fromRGB(255, 255, 255)
	Message.TextSize = 18
	Message.TextXAlignment = Enum.TextXAlignment.Left
	Message.TextYAlignment = Enum.TextYAlignment.Top
	
	local function measureSize(textObject)
		return game:GetService('TextService'):GetTextSize(textObject.Text, textObject.TextSize, textObject.Font, Vector2.new(textObject.AbsoluteSize.X, 10000))
	end

	PlayerLabel.Size = UDim2.new(0, PlayerLabel.TextBounds.X, 0, 18)
	Message.Text = ("%s%s"):format(string.rep(" ", math.ceil(measureSize(PlayerLabel).X / game:GetService('TextService'):GetTextSize(" ", PlayerLabel.TextSize, PlayerLabel.Font, Vector2.new(5000, 5000)).X) + 1), message)
	MessageFrame.Size = UDim2.new(0.95, 0, 0, measureSize(Message).Y)

This is what I got currently,


Doesn’t alter frame size still, and since I’ve now made the username a seperate label, it creates a large gap between the username and the message, as well as the message looking bigger than the username even tho they are the same size/font :confused:

1 Like

That’s strange, it is working perfectly fine for me. How is your frame currently set up? I have also edited the code you provided in the OP a bit and it is working as expected in studio. The size of the message inside the holder frame should be the same size as the holder frame on the Y axis, if you want to have spacing in between each frame I recommend using a UIListLayout or separately changing the position of each message frame.

local MessageFrame = Instance.new('Frame')
MessageFrame.AnchorPoint = Vector2.new(0.5, 1)
MessageFrame.BackgroundTransparency = 1
MessageFrame.Position = UDim2.new(0.5, 0, 1, 0)
MessageFrame.Size = UDim2.new(1, 0, 0, 16)

local Message = Instance.new('TextLabel')
Message.AnchorPoint = Vector2.new(0.5, 0.5)
Message.BackgroundTransparency = 1
Message.Position = UDim2.new(0.5, 0, 0.5, 0)
Message.Size = UDim2.new(0.95, 0, 1, 0)
Message.Font = Enum.Font.GothamSemibold
Message.Text = tostring(speaker) .. ': ' .. message
Message.TextSize = 16
Message.TextWrapped = true
Message.TextColor3 = Color3.fromRGB(255, 255, 255)
Message.TextXAlignment = Enum.TextXAlignment.Left
Message.TextYAlignment = Enum.TextYAlignment.Top
Message.Parent = MessageFrame

MessageFrame.Size = UDim2.new(1, 0, 0, TextService:GetTextSize(Message.Text, Message.TextSize, Message.Font, Vector2.new(MessageFrame.AbsoluteSize.X, 10000)).Y)

On another note, the only reason I was making a seperate text label for the player’s username was in order to have control over the color of the username and it is completely optional to do so. Since you are not trying to do something exclusively to the player’s username it is unnecessary to create a separate frame for it.

1 Like

I did end up creating a seperate label for the player username, because I ended up realising that it needed to be seperate in order to add like different colors/etc to it

Are you using TextWrapped? I feel like that may have something to do with your issue.

1 Like

TextScaled and TextWrapped are both on false for both the username and message.

Just doing some tests as to why the username label wasn’t being sized correctly

print(PlayerLabel.TextBounds.X) -- prints 0
PlayerLabel.Size = UDim2.new(0, PlayerLabel.TextBounds.X, 0, 18)

So its setting the size for X to be 0, not sure if this could be causing problems?

I think the reason the function GetTextSize is returning 16 always is due to the fact you have TextWrapped off. Since you’re manually setting the size of the TextLabel to 16, it’s always going to return that.

I’m tryingto use this instead now

local function measureSize(textObject)
		return game:GetService('TextService'):GetTextSize(textObject.Text, textObject.TextSize, textObject.Font, Vector2.new(textObject.AbsoluteSize.X, 10000))
	end
	print(PlayerLabel.TextBounds.X) -- prints 0
	PlayerLabel.Size = UDim2.new(0, PlayerLabel.TextBounds.X, 0, 16)
	Message.Text = ("%s%s"):format(string.rep(" ", math.ceil(measureSize(PlayerLabel).X / game:GetService('TextService'):GetTextSize(" ", PlayerLabel.TextSize, PlayerLabel.Font, Vector2.new(5000, 5000)).X) + 1), message)
	MessageFrame.Size = UDim2.new(0.95, 0, 0, measureSize(Message).Y)

Strange. I did the exact thing you did (except no player label), and it works fine. I think it’s an issue on your end. Although, I do think your chat text goes off of the chat frame due to you not using TextWrapped.

Setting TextWrapped to true does nothing
If the text is too long, it just doesn’t show up

You don’t seem to be using the script in that screenshot, and you put tons of spaces in the front of the text. TextWrapped is basically like ClipsDescendants for your text.

This is the full message creator

local function CreateMessage(message, speaker)
	local MessageFrame = Instance.new('Frame')
	MessageFrame.AnchorPoint = Vector2.new(0.5, 1)
	MessageFrame.BackgroundTransparency = 1
	MessageFrame.Position = UDim2.new(0.5, 0, 1, 0)
	MessageFrame.Size = UDim2.new(0.9, 0, 0.1, 0)
	
	local PlayerLabel = Instance.new('TextLabel')
	PlayerLabel.AnchorPoint = Vector2.new(0, 0.5)
	PlayerLabel.BackgroundTransparency = 1
	PlayerLabel.Position = UDim2.new(0, 0, 0.5, 0)
	PlayerLabel.Font = Enum.Font.GothamSemibold
	PlayerLabel.Text = tostring(speaker)
	PlayerLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
	PlayerLabel.TextSize = 16
	PlayerLabel.TextXAlignment = Enum.TextXAlignment.Left
	
	local Message = Instance.new('TextLabel')
	Message.AnchorPoint = Vector2.new(0, 0.5)
	Message.BackgroundTransparency = 1
	Message.Position = UDim2.new(0, 0, 0.5, 0)
	Message.Size = UDim2.new(0.95, 0, 0.9, 0)
	Message.Font = Enum.Font.GothamSemibold
	Message.Text = message
	Message.TextColor3 = Color3.fromRGB(255, 255, 255)
	Message.TextSize = 16
	Message.TextWrapped = true
	Message.TextXAlignment = Enum.TextXAlignment.Left
	
	local function measureSize(textObject)
		return game:GetService('TextService'):GetTextSize(textObject.Text, textObject.TextSize, textObject.Font, Vector2.new(textObject.AbsoluteSize.X, 10000))
	end
	
	print(Message.TextBounds.X)
	PlayerLabel.Size = UDim2.new(0, PlayerLabel.TextBounds.X, 0, 16)
	Message.Text = ("%s%s"):format(string.rep(" ", math.ceil(measureSize(PlayerLabel).X / game:GetService('TextService'):GetTextSize(" ", PlayerLabel.TextSize, PlayerLabel.Font, Vector2.new(5000, 5000)).X) + 1), message)
	MessageFrame.Size = UDim2.new(0.95, 0, 0, measureSize(Message).Y)

	PushMessages(MessageFrame.Size.Y.Scale)
	
	Chats[#Chats + 1] = MessageFrame
	
	PlayerLabel.Parent = Message
	Message.Parent = MessageFrame

	MessageFrame.Parent = List
end

What you are doing should work perfectly, yet it doesn’t. I think it is an issue on your end because it works fine for me. Except, what is PushMessages?

That’s a commented out function atm (I basically use it to move the text up) but the function is empty atm. So that has nothing to do with whats going wrong

Weird. I don’t really know what else to say except maybe it’s something to do with how you parent the labels.

For all those people visiting this post in 2020 and sooner: Roblox has added a this feature, just find the AutomaticSize property on the text and set it to Y, this will do it for you without any coding and stuff.(If you cannot find it, go to FILE(at the upper left corner of roblox studio) > beta features and tick AutomaticSize option.)

5 Likes