TextLabel alignment issues on different devices

Hello,

I’m currently experimenting around with animating each individual letter of a text. Each letter is it’s own TextLabel within a Frame and I position them side by side based on their TextBounds.

However when testing on different devices the alignment slightly breaks even though I’m updating positions whenever the container’s AbsoluteSize changes.

How can I ensure the letters stay perfectly aligned and maintain consistent spacing, regardless of the screen size or resolution?

Code for individual TextLabel
--[=[
    @class TitleScreenLoadingEntry
]=]

local require = require(script.Parent.loader).load(script)

local TextService = game:GetService("TextService")

local BasicPane = require("BasicPane")
local Blend = require("Blend")
local ValueObject = require("ValueObject")
local Rx = require("Rx")

local TitleScreenLoadingEntry = setmetatable({}, BasicPane)
TitleScreenLoadingEntry.ClassName = "TitleScreenLoadingEntry"
TitleScreenLoadingEntry.__index = TitleScreenLoadingEntry

function TitleScreenLoadingEntry.new()
    local self = setmetatable(BasicPane.new(), TitleScreenLoadingEntry)

    self._percentVisibleTarget = self._maid:Add(ValueObject.new(0))
    self._labelText = self._maid:Add(ValueObject.new(""))
    self._textSize = self._maid:Add(ValueObject.new(0))
    self._entryHeight = self._maid:Add(ValueObject.new(0))

    self._maid:GiveTask(self.VisibleChanged:Connect(function(isVisible)
        self._percentVisibleTarget.Value = isVisible and 1 or 0
    end))

    return self
end

function TitleScreenLoadingEntry:SetText(text: string)
    self._labelText.Value = text
    self:_adjustBounds()
end

function TitleScreenLoadingEntry:_adjustBounds()
    local bounds = TextService:GetTextSize(
        self._labelText.Value,
        self._entryHeight.Value * 0.8,
        Enum.Font.ArimoBold,
        Vector2.new(math.huge, math.huge)
    )
    self._textSize.Value = bounds.X
end

function TitleScreenLoadingEntry:Render(props)
    local target = self._percentVisibleTarget:Observe()

    local percentVisible = Blend.Spring(target, 25, 0.6)
    local percentAlpha = Blend.AccelTween(target, target:Pipe({
        Rx.map(function(value)
            return value == 1 and 200 or 400
        end)
    }))

    local transparency = Blend.Computed(percentAlpha, function(percent)
        return 1 - percent
    end)

    local rotation = Blend.Computed(percentVisible, function(percent)
        return 45 - percent * 45
    end)

    return Blend.New "Frame" {
        Name = "LoadingEntry";
        BackgroundTransparency = 1;
        Parent = props.TargetParent;

        Size = Blend.Computed(self._textSize, function(size)
            return UDim2.new(0, size, 1, 0)
        end);

        [Blend.OnChange "AbsoluteSize"] = function(size)
            self._entryHeight.Value = size.Y
            self:_adjustBounds()
        end;

        Blend.New "TextLabel" {
            Name = "label";
            AnchorPoint = Vector2.new(0.5, 0.5);
            BackgroundTransparency = 1;
            Rotation = rotation;
            TextTransparency = transparency;
            TextColor3 = Color3.fromRGB(231, 227, 209);
            FontFace = Font.fromEnum(Enum.Font.ArimoBold);
            Size = UDim2.fromScale(1, 1);

            Position = Blend.Computed(percentVisible, function(percent)
                return UDim2.fromScale(-0.5 + percent, 1.5 + -percent)
            end);

            TextSize = Blend.Computed(self._entryHeight, function(size)
                return size * 0.8
            end);

            Text = Blend.Computed(self._labelText, function(text)
                return text
            end)
        }
    }
end

return TitleScreenLoadingEntry

Here’s a short clip of my problem:

bump still need help on this haven’t figured it out yet


(edit 1): i just noticed when i change the device emulation to Fit To Window somehow my ui is aligned on other devices can someone explain that to me because when i set it to Actual Resolution it’s not aligned anymore


(edit 2): changed a few things, tested it out in-game on my phone and it seems to be working just fine there, weird that the studio preview was bugged like that