Try out LVGL Pro - A complete toolkit to build, test, share, and ship UIs efficiently!
LVGL
Release

LVGL Pro v2.1.0: XML Upgrades, Faster Preview, LVGL 9.6

LVGL 9.6 support, reactive XML bindings, improved XML validation, style transitions, hardware bezel overlays, and a much faster Preview and CLI.

William SemberWilliam Sember13 min read

Hello everyone! We are very excited to announce the release of LVGL Pro 2.1! 🎉 🥳 As you may recall, version 2.0 was a major upgrade. What could we improve after that? Well, as it turns out, everything...

Download LVGL Pro 2.1 and try it for yourself.

Breaking Changes

There are some small breaking and behavioral changes. Please see those at the end of this post.

New Features#

LVGL v9.6 Support#

Set it with lvgl_version="9.6.0" in project.xml. New projects use v9.6 by default; the VS Code, Zephyr, and Linux templates are all updated.

<project name="reference_project" lvgl_version="9.6.0">
	...
</project>
xml

Speed#

We've reworked how the Preview updates. Our goal is to make it update as fast as you can type. 🏎️ We think it's pretty close. 👌🏻

Typing in the XML editor while the Preview updates on every keystroke

On top of that, picking a license now takes a couple seconds instead of 10+ seconds.

Oh, and the CLI starts about 3× faster.

Vector Graphics Support#

SVG, Lottie, and vector graphics (ThorVG) are enabled in the Preview on LVGL v9.5 and v9.6.

Info

We've simply enabled these in the Editor's Preview. We have not yet added first-class support in XML for these.

New in v2.1: a <file src_path="….svg"> image is decoded by the Preview runtime.

SVG in lv_image
SVG logo rendered in the Preview

Color Subjects#

Subjects can now hold a color. Any color attribute or style property can bind to one, and the Subjects panel shows a color picker for it.

color demo
Swatches switching the accent color of a button, slider, switch, and arc

From C:

lv_subject_set_color(subject_accent, lv_color_hex(0x4caf50));
c

Style Transitions and Easing#

<transition props="…" duration="…" easing="…"/> inside a <style>. easing also works on <animation> and takes a built-in path, bezier(x1 y1 x2 y2), or your own easing callback.

components/transition_demo/transition_demo.xml
Three chips sliding with ease_in_out, overshoot, and bezier easing

Hardware Frame Overlay and Keyboard Input#

Draw a device bezel around the Preview with clickable hardware buttons that send key events. The Preview now has keyboard input and gridnav, so you can test keypad and encoder UIs without hardware.

This feature was highly requested internally and loved by the users who got an early preview. We've found it works wonders for product teams to situate the UI in the hardware context.

project.xml
Clicking the hardware buttons on a device bezel drawn around the Preview
How the arrow keys move between tiles (XML + C)

The overlay buttons send key events. To let the arrow keys move between the tiles, the tile row turns on gridnav with a few lines of C. The XML calls it once, right after the row is created:

<!-- screens/hardware_demo.xml -->
<lv_obj flex_flow="row" width="content" height="content">
	<!-- runs once after creation -->
	<event_cb callback="tiles_gridnav_cb" trigger="{true}"/>
 
	<lv_button checkable="true">
		<style name="style_tile"/>
		<style name="style_tile_focus" selector="focus_key"/>
		<style name="style_tile_on" selector="checked"/>
		<lv_label text="Lights" align="bottom_mid"/>
	</lv_button>
	<!-- … Fan, Heat, Music -->
</lv_obj>
xml
/* examples_announce_pro_2_1_0.c */
void tiles_gridnav_cb(lv_event_t * e)
{
    lv_obj_t * row = lv_event_get_current_target_obj(e);
    lv_group_t * group = lv_group_get_default();
    if(group == NULL) return;
 
    lv_gridnav_add(row, LV_GRIDNAV_CTRL_ROLLOVER);
 
    /* gridnav moves focus between the tiles, so only the row itself goes in the group */
    uint32_t cnt = lv_obj_get_child_count(row);
    for(uint32_t i = 0; i < cnt; i++) lv_group_remove_obj(lv_obj_get_child(row, i));
 
    lv_group_add_obj(group, row);
    lv_group_focus_obj(row);
}
c

The left and right buttons move focus, which applies style_tile_focus via the focus_key selector. Enter is passed on to the focused tile, which toggles its checked state.

Reactive XML#

Bindable Properties#

<prop bindable="true"> makes a component property follow a subject from outside. Give it an expression and it updates whenever the subject changes.

bindable props
Dragging sliders updates two temp_card components bound to subjects

Exported C code also gets a public setter and getter for the property:

void temp_card_set_temp(lv_obj_t * obj, int32_t temp);
int32_t temp_card_get_temp(lv_obj_t * obj);
c

A plain (non-bindable) prop is read once at creation, so {room} above does not update later.

Per-Instance Subjects#

Components and screens can declare their own <subjects>. Every instance gets a private copy that starts at the declared value. A local subject shadows a global subject with the same name. Note how the subject min/max are honored.

components/counter/counter.xml
Three counter components counting independently

Conditional Styles#

<style enabled="{…}"> switches a style on and off based on a condition. The style updates whenever a subject in the condition changes.

components/battery_badge/battery_badge.xml
Battery badge turning green above 60%, red below 20%, and getting a green border while charging

This replaces <bind_style name="style_low" subject="subject_battery" ref_value="…"/>, which could only test for equality.

AND and OR#

You can combine conditions in any { } expression. In XML attributes, & and < have to be escaped. To avoid that, LVGL 9.6 also accepts the uppercase keywords AND, OR, LT, LE, GT, GE, EQ, and NE.

AND and OR
Wi-Fi icon hiding and a warning card turning red as conditions change

Both sides are always evaluated (there's no short-circuiting).

Expressions in set_subject_event#

A value written in { } is evaluated each time the event fires, and the subject's min_value/max_value clamp the result. One event can therefore set, toggle, step, or cycle a value. This replaces <subject_set_int_event>, <subject_toggle_event>, and <subject_increment_event>.

set_subject_event
Buttons setting, toggling, stepping, and cycling subjects

Expression Triggers#

Any event can take trigger="{expr}" instead of an event name. The action runs every time the expression goes from false to true, and also right away if it is already true at creation.

components/alarm_banner/alarm_banner.xml
Alarm banner sliding in and out, and the fan switching on above 30 °C

An expression without any subjects is evaluated once. If it evaluates to a name instead of true or false, that name is used as the event, e.g. trigger="{compact ? long_pressed : clicked}".


Honorable Mentions: Also in 2.1#

  • The CLI didn't support Mac Intel. Now it does.
  • CLI screenshot command can take target and language: lvglpro screenshot --target … --language ….
  • You can use your own emsdk install (must be version 4.0.6) instead of the Editor's managed one.
    • Just add emsdk to your PATH and the Editor will pick it up. Useful for strict networks.
  • <PROJECT>_COMPILE_TARGET in <project>.h sets the default responsive target(s). Existing projects keep their <project>.h; to choose targets, add #define <PROJECT>_COMPILE_TARGET ... above #include "<project>_gen.h".
  • Broader XML validation:
    • A missing asset is reported in every attribute that refers to it
    • An invalid enum value error lists the valid values
    • Prop defaults and #const values are type-checked
    • Many { } expression fixes
  • Subject values are kept when the Preview reloads, instead of resetting to their initial values.
  • As mentioned elsewhere, keyboard input to the Preview is now enabled.

Breaking Changes & Migration Steps#

Editor and CLI#

  1. The CLI command is now lvglpro (was lved), and old CLI tokens do not work in lvglpro v2.1+. Generate a new token at lvgl.io/pro/account and replace it wherever you use it: --token, LVGLPRO_CLI_TOKEN, CI secrets, etc.
  2. macOS and Linux need ninja on the PATH to build the Preview (brew install ninja / sudo apt-get install ninja-build). Previously, the Editor used make on these OSes. You still must have git and cmake installed.
  3. New download formats: a .dmg on macOS and an .AppImage on Linux (no libfuse2 needed), instead of .zip.
    • The AppImage uses zstd compression and the new static AppImage runtime, which AppImageLauncher 2.x does not support. If you use AppImageLauncher, upgrade to 3.x or uninstall it; otherwise the Editor fails to start with a "Squashfs image uses (null) compression" error. Tools such as Gear Lever work fine.
  4. The Preview only renders a valid project. While any file has an error, the Preview keeps its last render and names the error. Tests also follow this rule.

XML#

  1. On LVGL v9.6, the expression keywords are uppercase-only: AND / OR. The lowercase and / or only apply on v9.5.
  2. On LVGL v9.6, @{ } bindings are removed. Use { }, which is re-applied whenever a subject it reads changes. The validator flags old @{ } uses and shows the replacement.
  3. <lv_image bind_src> is removed on LVGL v9.6. Use src="{subject}", which also works for compiled-in images. v9.4 and v9.5 keep bind_src.
  4. Binding a component's own property from outside requires <prop bindable="true">. Without it, the value is only used when the instance is created, and the validator reports the binding.

Generated C Code#

  1. On LVGL v9.6, global subjects are exported as pointers (extern lv_subject_t * temperature;), since they are created with lv_subject_create(). In your own C code, drop the & when you use one: lv_subject_set_int(temperature, 25) instead of lv_subject_set_int(&temperature, 25). v9.4 and v9.5 projects are unchanged.

Conclusion#

And that's a wrap! This was personally very exciting for me to write. After my team has been working so hard for so long, taking feedback from our users and our co-workers, refining, creating, adjusting... I truly didn't envision how much more evolved this release would be. I'm positively chuffed we keep upping the bar in support of our users! Cheers! 🍻

Get LVGL Pro 2.1

Download the Editor and CLI for Windows, macOS, and Linux.

About the author

William Sember
William Sember

Team Lead - LVGL Pro

Team lead at LVGL Pro with nearly two decades of software and web development experience for industrial and small business applications. Passionate about building quality editing tools that help users bring their embedded UIs to life.

Meet the people behind the blog

Discover the talented writers sharing their knowledge about LVGL

View Authors

Subscribe to our newsletter to not miss any news about LVGL. We will send maximum of 2 mails per month.

LVGL

LVGL is the most popular free and open source embedded graphics library targeting any MCU, MPU and display type to build beautiful UIs.

We also do services like UI design, implementation and consulting.

© 2026 LVGL. All rights reserved.
YouTubeGitHubLinkedIn