Understanding Rich Text in Roblox
The Roblox engine has always supported basic text formatting through Luau, but getting it to behave consistently across different devices and screen sizes is where things fall apart. I spent a solid week last year debugging why player names in my game would render one way on mobile and completely differently on PC, and it came down to a single misunderstanding about how Roblox handles rich text. At its core, Rich Text Roblox refers to using the `` tag system that Roblox provides through the rich text parser in text labels and text boxes. You're working with HTML-like syntax, but it's a very restricted subset. Colors come from hex codes, font sizes are capped, and the list of available fonts is limited to whatever Roblox ships by default unless you're using ImageButtons with custom textures, which is a completely different approach.
Getting Rich Text Roblox to Work in Practice
The simplest way to use this is through a TextLabel. Set the property RichText to true on whatever UI element you're using, and then wrap your content in the appropriate tags. Here's what that actually looks like when you're putting together a HUD element: TextLabel.RichText = true
TextLabel.Text = "Warning: Player entered restricted zone"
TextLabel.TextWrapped = true The color value needs to be a proper hex string. If you forget the hash symbol or provide a seven-character string, the parser just ignores it and falls back to the default color. That happened to me on a build pipeline project where someone had set up automated text generation, and about 40% of the warnings were showing up in plain white because the hex values were coming through without the leading #. Took me two hours to trace it back to a serialization issue in the data layer.
Font size works the same way. The range is 7 to 100 points, and anything outside that gets clamped silently. There's no error message, no warning flag, nothing. You'll just look at your output and wonder why the text looks wrong until you check the tag values.
Get the Full Details

Common Pitfalls That Break Your UI
The most frustrating thing about this system is how it handles nested or malformed tags. Roblox will attempt to parse the string and close any open tags automatically, but the results are unpredictable. If you have mismatched brackets or a typo inside a tag attribute, the rest of your string might render as raw markup instead of formatted text. I ran into this with a dynamic chat display system where player-generated messages could contain arbitrary text. Someone once pasted a string with an unclosed `` tag in the middle of their message, and suddenly the entire chat box was showing raw tag syntax for the rest of the session. The fix was wrapping every dynamic text source through a sanitization function that either closed all open tags or stripped the formatting entirely if the input was too corrupted to trust. Another thing nobody mentions: the parser is case-sensitive on tag names but not on attribute names. `` won't work. `` will. But `` and `` both work fine. That inconsistency caught me off guard when I was writing a formatter script that converted markdown-style input into Roblox rich text. A couple of edge cases in the conversion logic meant some messages were losing their color entirely because the attribute name wasn't normalized to lowercase before being inserted.
There's also a practical limit on text length. Very long strings with lots of formatting tags will start to stutter on lower-end devices, particularly on mobile. I tested this on a mid-range Android phone and saw noticeable frame drops when a single text label had more than about 500 characters with mixed formatting. Breaking the text into multiple labels or simplifying the formatting on smaller viewports cut the stutter to almost nothing.
What Rich Text Roblox Can't Do
For all its usefulness, this system has hard limitations. You cannot load custom fonts. The built-in font list is fixed and includes things like Helvetica, Arial, and a handful of others, but if you need a specific typeface for branding purposes, you're looking at either image-based text or a third-party solution that pre-renders text to sprites, which adds a whole different layer of complexity around caching and texture management. You also can't apply shadow effects, gradients, or stroke outlines through the rich text parser. Those have to be faked using layered UI elements if you really need them, and that quickly becomes expensive in terms of rendering overhead. I saw a game attempt to put a drop shadow on every chat message by stacking a slightly offset TextLabel behind each one, and it tanked performance on group chats where thirty people were talking at once. The color palette is another constraint. You're limited to standard RGB hex values, which means no alpha blending on text itself. If you want semi-transparent text, you have to adjust the color value to include the translucency manually, and even then it doesn't interact correctly with the background in all scenarios. The text will render on top of whatever is behind it, but the transparency math doesn't account for anti-aliasing artifacts at the edges, so you'll get a faint halo effect around letters against busy backgrounds.

A Realistic Approach to Building With This
If you're building something that needs dynamic formatted text, the cleanest setup I've found involves a dedicated text formatting module that handles sanitization, tag normalization, and fallback logic in one place. You feed it raw strings, and it outputs safe, properly structured rich text that the UI layer can consume without issues. The module I ended up using does three things: it strips any tags that don't belong to the allowed set, it auto-closes any open tags by appending the necessary closing markers, and it normalizes all attribute names to lowercase before passing the result to the label. That last step alone fixed half the bugs we were seeing in production. For static text that never changes at runtime, there's really no reason to go through code. You can type the tags directly into the Text property in the Roblox Studio editor and preview it in real time. The Studio preview even shows you when a tag is malformed by displaying the raw text instead of rendering it, which is at least something.
The tradeoff with using the editor approach is that you can't easily swap out text based on language or context without going back into code anyway. If your project needs localization or any kind of runtime text generation, the programmatic route with the sanitization wrapper is worth the extra setup time, even if it adds maybe fifteen minutes to your initial development cycle. One more thing that comes up occasionally: if you're using these formatted strings inside a DataStore or passing them between servers through RemoteEvents, make sure you're encoding the data properly. The angle brackets and special characters in rich text tags can interfere with JSON serialization if you're not escaping them, and I've seen enough projects lose formatted text data to broken serialization that I now run every string through a quick round-trip test before committing it to storage.