Evaluate expressions
Compute attribute values from arithmetic, comparisons, ternaries, and string concatenation directly in your XML.
This feature requires LVGL Pro Editor v2.0 or higher.
Any XML attribute value can be an expression wrapped in { }. Instead of writing a fixed value, you let the Editor compute it from numbers, colors, strings, constants, and parameters.
<lv_obj width="{base_width * 2}"/>
<lv_label text="{'Hello, ' . user_name . '!'}"/>
<lv_obj hidden="{item_count == 0}"/>Overview
Expressions are useful whenever a value is derived from other values: a width that is twice a parameter, a label that joins a prefix with a name, a flag that depends on a count, and so on. Keeping the calculation in the XML means you don't have to duplicate or pre-compute values by hand.
A few important properties to keep in mind:
- Creation-time only. An expression is evaluated once, when the UI element is created. The result is then handed to the normal attribute parser exactly as if you had typed the computed value yourself.
- Not data binding. Expressions do not react to changes. If you need a value that updates at runtime when a subject changes, use data binding instead.
- The result type is inferred from the terms. You never declare the type — it follows from the literals and variables you use (see Value types).
Expressions are exported into the generated C code, not pre-computed to a fixed literal. They are re-evaluated every time the element is created — including when you create a component manually from C — using the parameter values passed at that moment.
Writing expressions
An expression is the whole attribute value, wrapped in a single pair of braces:
<lv_obj width="{10 + 20}"/> <!-- becomes width="30" -->Inside the braces you can use literals, operators, and variable names. A variable name is written as a bare identifier — without the $ or # prefixes used elsewhere in XML. The name is resolved, in order, against:
- Parameters declared in the element's
<api>— the value comes from the instance (or the parameter'sdefault), and the type from the declaredtype. - Constants from
<consts>— the type is inferred from the constant's value. - Other named items the XML processor resolves later (a font, image, subject, or screen name). These are passed through as plain strings.
<component>
<consts>
<int name="gap" value="8"/>
</consts>
<api>
<prop name="columns" type="int" default="3"/>
</api>
<view>
<!-- `gap` is a const, `columns` is a param -->
<lv_obj width="{columns * 100 + (columns - 1) * gap}"/>
</view>
</component>Note that $ and # are not used in expressions to reference properties and constants.
Value types
Each term has a type, inferred from how it is written:
| Term | Example | Type |
|---|---|---|
| Decimal integer | 42 | int |
| Number with a fraction | 3.5 | float |
| Hex literal | 0xff0000, 0xf00 | color |
| Single-quoted text | 'hello' | string |
true / false | true | bool |
| A comparison | a == b | bool |
| A variable | my_param | its own type |
Notes:
- Colors accept both the full
0xRRGGBBform and the0xRGBshorthand, which expands like CSS (0xf00→0xff0000). - Strings use single quotes (
'…'), since double quotes already delimit the XML attribute. - Floats require
LV_USE_FLOAT. Without it, a float degrades to its integer part. Float results are serialized with two decimals (e.g.3.50).
Operators
Arithmetic
+, -, *, /, % operate on numbers. % requires integer operands, and division or modulo by zero is an error.
<lv_obj width="{100 + pad * 2}"/>
<lv_obj height="{total / 3}"/>Comparison
== and != work on any two operands of the same type (numbers, strings, colors, or bools). The ordered comparisons <, <=, >, >= work on numbers only. Every comparison yields a bool.
<lv_obj hidden="{count == 0}"/>
<lv_obj checked="{mode == 'dark'}"/>Only one comparison is allowed per expression — comparisons cannot be chained (a < b < c is invalid).
Logical not
The unary ! accepts a number, bool, or string and returns a bool. An empty or missing string is falsy (like a NULL pointer in C).
<lv_obj clickable="{!locked}"/>There are intentionally no &&, ||, or ^^ operators.
Ternary
cond ? a : b chooses between two values. The condition must be a bool, a number, or a string (a non-empty string is truthy); it cannot be a color. Both branches must have the same type (int and float mix freely).
<lv_label text="{count == 0 ? 'Empty' : 'Has items'}"/>
<lv_obj style_bg_color="{is_on ? 0x00ff00 : 0x333333}"/>Ternaries cannot be nested, but each branch may itself be a string concatenation.
String concatenation
The . operator joins values into a single string. Each operand is automatically stringified — integers and floats as decimals, bools as true/false, colors as 0xRRGGBB.
<lv_label text="{'Battery: ' . level . '%'}"/>
<lv_label text="{first_name . ' ' . last_name}"/>Precedence and grouping
From highest to lowest:
- Unary
-,+,! *,/,%+,-- Comparisons (
==,!=,<,<=,>,>=) - Concatenation (
.) - Ternary (
? :)
Parentheses ( ) group arithmetic and comparison sub-expressions. They cannot contain a concatenation or a ternary.
<lv_obj width="{(a + b) * 2}"/>Error handling
If an expression is malformed — an unknown identifier, a type mismatch, a missing ) or :, division by zero, and so on — evaluation fails. A warning describing the exact problem and the offending expression is logged, and the attribute is left unset.
Common messages include:
- unknown identifier — the name is not a const, or prop.
- the two ternary branches must have the same type.
< <= > >=need numeric operands — use==/!=for strings, colors, and bools.- arithmetic
+ - * / %needs numeric operands. - unexpected character (note: use
==to compare,.to concatenate).
Examples
<!-- Arithmetic with a constant and a parameter -->
<lv_obj width="{card_width * column_count + gap * (column_count - 1)}"/>
<!-- Conditional text -->
<lv_label text="{unread == 0 ? 'No new messages' : 'New messages'}"/>
<!-- Building a string from several parts -->
<lv_label text="{'Room ' . room_id . ': ' . temperature . ' °C'}"/>
<!-- Boolean flag from a comparison -->
<lv_obj hidden="{progress >= 100}"/>
<!-- Color chosen by a flag -->
<lv_obj style_bg_color="{active ? 0x2e7d32 : 0x9e9e9e}"/>Last updated on