Use markup in Label components and GUI text nodes to apply nested visual styles and effects, and inspect links and sprites from Lua.
label.set_text("#label", "Score: <color=#69D2E7>1200</color>")
Alternatively, define a reusable named object style on the font and select it from a link:
local fontpath = "/fonts/ui.fontc"
font.set_style(fontpath, "menu_link", "<color=#69D2E7>")
label.set_text("#label", "Open <link style=menu_link src=inventory>inventory</link>")
| Tag | Purpose | Example |
|---|---|---|
color |
Set the glyph face color. | |
size |
Change glyph shaping and layout size. | |
gradient |
Apply a static or animated color gradient. | |
ul |
Underline text. | |
strike |
Strike through text. | |
outline |
Set the glyph outline width and color. | |
shadow |
Add a shadow to text. | |
shake |
Apply an animated random offset. | |
wave |
Move text in an animated sine wave. | |
sprite |
Add an inline sprite object. | |
link |
Add an interactive link object. |
Tags and attribute names are case-sensitive. A paired tag applies to the visible UTF-32 text inside it. Sprite objects use self-closing tags.
<color=#69D2E7>colored text</color>
<ul pattern=dashed>underlined text</ul>
<outline size=2 color=#000000>outlined text</outline>
<shadow x=2 y=-2 color=#00000080>shadowed text</shadow>
<sprite src=images/icon.png width=2em/>
Attributes may be unquoted when they contain no whitespace, or quoted with single or double quotes. color and size support a shorthand first value as well as the named value form.
<color=#FF8800>Orange</color>
<color value="#FF8800">Orange</color>
<size='120%'>Larger</size>
Tags must close in last-in, first-out order. Inner style values override the same property from an outer style. Different properties combine. Span effects remain independently active, so nested gradients multiply colors and nested position effects add their offsets.
<color=#FFCC00>
Gold <outline size=2 color=#000000>with a black outline</outline>
</color>
Use &, ', >, <, and " for reserved characters in visible text. Numeric entities are not currently supported.
Rich-text tags either style an enclosed text span or describe an object that can be inspected from Lua. Style tags use a matching closing tag. The sprite object is self-closing, while link encloses its linked text.
colorSets the glyph face color. Colors use #RRGGBB or #RRGGBBAA. The hash prefix is required; 0xFF0000 and FF0000 are invalid. The result multiplies the label or renderer base color.
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| =color or value=color | Yes | No default | Face color in RGB or RGBA hexadecimal form. |
<color=#00FF00>Opaque green</color>
<color=#00FF0080>Half-alpha green</color>
#00FF00
#00FF0080
sizeChanges glyph shaping and layout size, not only vertex scale. Relative values always use the layout’s base font size. They do not compound with an enclosing size tag.
| Attribute | Required | Default | Meaning |
|---|---|---|---|
=size or value=size |
Yes | No default | Absolute size, percentage, base-size multiple, or signed base-size offset using one of the forms below. |
| Form | Example at 32 px | Resolved size |
| — | — | — |
| Bare number or px | 24, 24px | 24 px |
| Percentage of base size | 120% | 38.4 px |
| Multiple of base size | 2em | 64 px |
| Signed offset from base size | +4, -4 | 36 px, 28 px |
<size=24px>Exactly 24 pixels</size>
<size=120%>120% of the layout base size</size>
<size=2em>Twice the layout base size</size>
24px
120% of 32px
2em of 32px
gradientA gradient accepts exactly one complete attribute set. Mixing sets or omitting a member is invalid.
| Mode | Required attributes | Interpolation |
|---|---|---|
| Horizontal | left, right |
Interpolates between the two horizontal colors. |
| Vertical | bottom, top |
Interpolates between the bottom and top colors. |
| Four-corner | tl, tr, bl, br |
Interpolates between four vertex colors. |
| Attribute | Required | Default | Meaning |
|---|---|---|---|
left, right |
For horizontal mode | None | Horizontal endpoint colors in #RRGGBB or #RRGGBBAA form. Both must be present. |
bottom, top |
For vertical mode | None | Vertical endpoint colors. Both must be present. |
tl, tr, bl, br |
For four-corner mode | None | Top-left, top-right, bottom-left, and bottom-right colors. All four must be present. |
fit |
No | span |
glyph samples each shaped text position; span distributes the gradient across the complete tagged text. |
hz |
No | 0 |
Complete flowing cycles per second in [0,); zero keeps the gradient static. |
direction |
No | forward |
forward or reverse. Controls the flow direction when hz is non-zero. |
When fit is omitted, fit=span distributes the gradient across the complete tagged text. fit=glyph samples each shaped text position independently. Optional hz specifies complete flowing animation cycles per second; its default of zero keeps the gradient static. The repeating mirrored color ramp flows continuously and wraps without a color jump. direction=forward is the default; use direction=reverse to reverse the flow.
<gradient left=#FF00FF right=#FFFFFF>Horizontal Gradient</gradient>
<gradient hz=0.25 fit=glyph bottom=#182848 top=#4B6CB7>Animated vertical glyphs</gradient>
<gradient hz=0.25 direction=reverse left=#FF0000 right=#0000FF>Reverse flow</gradient>
<gradient hz=0.25 direction=reverse fit=span left=#FF0000 right=#0000FF>One animated span color</gradient>
<gradient fit=glyph tl=#FF0000 tr=#00FF00 bl=#0000FF br=#FFFFFF>
Four corners
</gradient>
Horizontal
Vertical
Four corner
fit=glyph
fit=span
Animated
fit=glyph
fit=span
Gradient colors multiply the current face color. A gradient inside color=#808080 therefore cannot produce a channel brighter than that base multiplier.
ulDraws an underline using the font’s underline metrics when they are available. The tag has no independent color: the line inherits the effective face color, including horizontal, vertical, and four-corner gradients.
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| pattern | No | solid | solid or dashed. |
<ul>Solid underline</ul>
<ul pattern=dashed>Dashed underline</ul>
<ul><gradient left=#FF00FF right=#FFFFFF>Gradient line</gradient></ul>
Solid
Dashed
Gradient
strikeDraws a line through the enclosed text. It accepts the same pattern values as ul and likewise inherits the effective face color.
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| pattern | No | solid | solid or dashed. |
<strike>No longer available</strike>
<strike pattern=dashed>Dashed strikethrough</strike>
Solid
Dashed
outlineSets outline width, outline color, or both. At least one attribute is required. A zero width explicitly disables the outline for the span.
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| size | One of size/color | Inherited; 0 on a default font | Width in layout units, range [0,). Unit suffixes are not accepted. |
| color | One of size/color | Inherited; #000000 on a default label | Single outline color in hexadecimal RGB (#RRGGBB) or RGBA (#RRGGBBAA) form; the alpha component controls opacity. |
<outline size=3 color=#000000>Black outline</outline>
<outline color=#FF0000>Keep inherited width, change color</outline>
<outline size=0>Disable inherited outline</outline>
External black outline
shadowAdds a hard shadow to the enclosed text. At least one attribute is required. Attributes omitted by a nested tag retain the enclosing shadow value; attributes omitted by the outermost tag retain the font’s base shadow value.
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| color | No | Inherited; #000000 on a default label | Shadow color in #RRGGBB or #RRGGBBAA form. |
| x | No | Inherited; 0 on a default font | Horizontal shadow offset in layout units. Positive values move it right. |
| y | No | Inherited; 0 on a default font | Vertical shadow offset in layout units. Positive values move it up. |
| blur | No | Inherited; 0 on a default font | Blur radius in layout units, range [0,). |
<shadow x=6 y=-6 blur=4 color=#000000A0>Shadow</shadow>
<shadow x=-2>Override only the horizontal offset</shadow>
x=6, y=-6, blur=4
Shadow blur is generated and stored in the glyph atlas. A span can request a smaller blur than the font’s baked blur; larger values are preserved in the layout but currently render using the largest blur available in the atlas.
shakeApplies a deterministic animated random offset without changing line breaking or layout bounds. The effect keeps time internally; scripts do not need to modify the label text for each animation frame.
| Attribute | Required | Default | Valid values | Meaning |
| — | — | — | — | — |
| hz | No | 20 | [0,) | Random target transitions per second. Zero pauses the effect. |
| amplitude | No | 0.5 | [0,) | Maximum displacement in layout units. |
| fit | No | glyph | glyph or span | glyph samples a cluster-safe offset for each shaped glyph unit. span moves the complete tagged text span as one rigid unit. |
<shake>Default shake</shake>
<shake hz=12 amplitude=0.8 fit=glyph>Glyph shake</shake>
<shake hz=12 amplitude=0.8 fit=span>Rigid span shake</shake>
fit=glyph
fit=span
waveMoves characters up and down in an animated sine wave without changing line breaking or layout bounds. The layout accumulates animation time when it is updated.
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| amplitude | No | 1 | Maximum vertical displacement in layout units, range [0,). |
| hz | No | 1 | Complete temporal cycles per second, range [0,). Zero pauses the wave. |
| wavelength | No | 6 | Visible UTF-32 text positions per complete spatial cycle, range [1,). Characters that the font shapes together, such as a base character and its combining accent, move as a unit. |
| fit | No | glyph | glyph applies the spatial wave across the text. span gives the complete tagged text span one shared vertical sine offset. |
| direction | No | forward | forward advances normally. reverse reverses the wave’s travel direction. |
<wave>Animated character wave</wave>
<wave amplitude=4 hz=3 wavelength=8 fit=glyph>Travelling wave</wave>
<wave amplitude=4 hz=3 wavelength=8 fit=glyph direction=reverse>Reverse travelling wave</wave>
<wave amplitude=4 hz=1 fit=span>Whole span moves together</wave>
fit=glyph
fit=span
spriteAdds a self-closing sprite object at the current position in the visible text. Its attributes are preserved as metadata for label.get_layout_objects() and gui.get_layout_objects().
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| id | No | Generated | Stable identifier hashed into the returned layout object’s id. |
| src | No | None | Application-defined sprite resource identifier, such as an image or atlas project path. |
| animation | No | None | Application-defined animation identifier within the resource. |
| width | No | 1em | Resolved sprite width. |
| height | No | 1em | Resolved sprite height. |
| Any other attribute | No | Absent | Application-defined metadata preserved for the object resolver and the layout-object APIs. |
A <sprite src=engine/engine/content/builtins/assets/images/logo/logo_256.png/> logo
<sprite src=images/banner.png width=4em height=2em/>
<sprite src=images/icons.atlas animation=coin width=2em/>
Resolved inline sprite
Dimensions accept positive bare layout units, px, em, or %. Both em and % use the text layout’s base font size.
Each missing dimension defaults independently to 1em. Omitting both produces a 1em × 1em object; specifying only the width does not derive the height automatically from a resource aspect ratio.
The sprite tag is merely a placeholder for the developer to fit whatever object in that place!
linkDescribes a range of visible text as a link object. The enclosed text is laid out normally and receives the named link style by default. Label and GUI components select link:hover and link:active in response to input without reshaping the text. See Interaction messages for the messages produced by link input.
| Attribute | Required | Default | Meaning |
| — | — | — | — |
| src | No | None | Application-defined link target. The value is returned as a string without automatic validation or navigation. |
| id | No | Generated | Stable identifier hashed into the returned layout object’s id. |
| style | No | link | Named default style for the link text. |
| Any other attribute | No | Absent | Application-defined metadata, such as an identifier, action, tooltip, or analytics value. |
<ul><link id=website src=https://www.defold.com>www.defold.com</link></ul>
<link id=inventory style=menu_link action=open_inventory item=sword>Iron sword</link>
style=link
The component tracks each link’s pointer state. It applies link:hover while the pointer is over the link and link:active while the pointer is pressed. When neither state applies, the component restores the style named by the link’s style attribute, or link when the attribute is absent.
Link interaction uses Defold’s normal input system. Add a Mouse Trigger binding for MOUSE_BUTTON_LEFT, which also enables single-touch input, and acquire input focus in the game object’s script or GUI script:
function init(self)
msg.post(".", "acquire_input_focus")
end
See Input focus and Mouse and touch input for setup details.
When a label or GUI component receives pointer input, links produce the following messages. Label messages are sent to the owning game object; GUI messages are sent to the GUI script.
| Message | When sent |
|---|---|
text_object_hovered |
The pointer enters a link. |
text_object_unhovered |
The pointer leaves a link. |
text_object_clicked |
A press is released over the same link. |
Each message contains these fields:
| Field | Type | Description |
| — | — | — |
| id | hash | The object’s id attribute, or its generated layout-object id. |
| type | hash | The layout-object type, currently hash("link"). |
| src | string | The application-defined value of the object’s src attribute, or an empty string when absent. |
function on_message(self, message_id, message)
if message_id == hash("text_object_clicked") then
assert(message.type == hash("link"))
print(message.id, message.src)
end
end
Each font collection contains render-only named object styles. A link uses the style named by its style attribute, or link when the attribute is absent. There is no general `` span tag.
Defold provides the following defaults:
| Style | Face-color multiplier | Decoration |
|---|---|---|
link |
(0.10, 0.45, 0.90, 1.0) |
Solid underline |
link:hover |
(0.30, 0.65, 1.00, 1.0) |
None |
link:active |
(0.05, 0.30, 0.70, 1.0) |
None |
Define a style with a text string containing opening tags. The tags are implicitly closed in reverse order, so closing tags and visible text are not allowed.
font.set_style("/fonts/ui.fontc", "link",
"<color=#2673ff><outline color=#000000 size=1>")
font.set_style("/fonts/ui.fontc", "link:hover",
"<color=#66b3ff><shake amplitude=0.2 hz=20>")
Tags are applied from left to right, as though they were nested around the object text. A caller-selected object style is applied after the default style. When multiple tags set the same render property, the value applied later overrides earlier values. Effects are appended in left-to-right order.
Calling font.set_style() replaces that named style’s render properties and effects. Resource-defined decorations remain unchanged, so redefining link does not remove its default underline. Named styles accept render-only tags such as color, outline, shadow, gradient, wave, and shake. Layout-changing, decoration, and object tags are rejected.
Use label.get_layout_objects() or gui.get_layout_objects() to retrieve the sprite and link objects from laid-out text.
label.get_layout_objects()objects = label.get_layout_objects(url)
| Argument | Type | Description |
|---|---|---|
url |
string, hash, or url |
The label component to inspect, for example "#label". |
gui.get_layout_objects()objects = gui.get_layout_objects(node)
| Argument | Type | Description |
|---|---|---|
node |
node |
The GUI text node to inspect, for example gui.get_node("rich_text"). |
Both functions return a newly created array containing the current layout objects in source order. They return an empty array when the text contains no object tags. Since the objects and their attributes are copied into Lua on every call, cache the result and query again after changing the text or another property that changes its layout.
| Field | Type | Description |
|---|---|---|
type |
string |
"sprite" or "link". |
id |
hash |
Object identifier used in interaction messages. |
text_offset |
number |
Zero-based position in the visible text, measured in Unicode codepoints. Markup is excluded, and entities count as their decoded characters. For a sprite, this is its insertion point. |
text_length |
number |
Length of the enclosed visible text in Unicode codepoints. A sprite has length one for its inserted U+FFFC object-replacement codepoint. |
width |
number |
Resolved width in text-layout units. Links currently have width zero. |
height |
number |
Resolved height in text-layout units. Links currently have height zero. |
x |
number |
Horizontal position of the object’s lower-left corner relative to the text layout’s upper-left origin. |
y |
number |
Vertical position of the object’s lower-left corner relative to the text layout’s upper-left origin. |
attributes |
table |
All tag attributes as string key/value pairs. Attribute values retain their source representation, such as "2em". A shorthand unnamed value is stored under the key value. |
text_offset and text_length are not UTF-8 byte offsets. A non-ASCII character such as å or 猫 counts as one position.
local text = [[
Read the <link src=https://defold.com/manuals/ id=manual>manual</link>
or inspect <sprite src=images/info.png width=2em/> for more information.
]]
label.set_text("#label", text)
local objects = label.get_layout_objects("#label")
for _, object in ipairs(objects) do
if object.type == "link" then
print("link", object.attributes.src)
print("visible range", object.text_offset, object.text_length)
print("position", object.x, object.y)
elseif object.type == "sprite" then
print("sprite", object.x, object.y, object.width, object.height)
pprint(object.attributes)
end
end
local gui_objects = gui.get_layout_objects(gui.get_node("rich_text"))
<outline size=2 color=#101820>
<gradient left=#FEE715 right=#FF6F61>Gradient title</gradient>
</outline>
The gradient multiplies the face color only; the outline keeps its own color.
<shake hz=20 amplitude=0.5>
This <gradient left=#FF00FF right=#FFFFFF>whole</gradient> text shakes!
</shake>
The outer position effect applies to every glyph. The nested color effect applies only to “whole”.
<color=#FFFFFF><outline size=2 color=#000000>
Normal <color=#FF4040>warning</color> normal
</outline></color>
The inner color changes the face while retaining the inherited outline width and color.