Development docs. Unreleased and may change.Switch to Release v9.6.0

Styles

The LVGL style system: properties, states, inheritance, and transitions.

Report on GitHub

An lv_style_t holds a set of property values (color, padding, border, font, and so on) that you attach to a widget, a specific part of a widget, and a state such as LV_STATE_PRESSED or LV_STATE_FOCUSED. Styles cascade through the parent/child tree, and transitions let property changes animate between states. This section covers property groups, state handling, and common composition patterns.

Arc stroke

Style the arc's ring and indicator into a modern progress dial.

arc_width and arc_rounded="true" give both parts a thick, round-capped stroke. On selector="main" arc_color is a light neutral track; on selector="indicator" it is the accent, so the same three properties produce a clean circular-progress look.

Background gradient

Blend two colors vertically and shift where the blend happens.

bg_color and bg_grad_color are the two stops; bg_grad_dir="ver" blends top-to-bottom. bg_main_stop="80" keeps the indigo solid only briefly and bg_grad_stop="220" stretches the blend almost to the bottom, so most of the card is transition rather than flat color.

Backdrop blur

Frost the text sitting behind a translucent card.

A paragraph fills the screen and the glass card is centered over its middle. The card's blur_backdrop="true" with blur_radius="14" blurs only what is behind it, and bg_opa="40%" keeps the card translucent so the blurred text shows through — sharp text around it, soft text under it.

Border

Frame a card with a colored, partially transparent border.

border_width="4" and border_color draw the frame and border_opa="60%" lets the surface show through it, so the border reads as a soft accent instead of a hard line. radius="20" rounds the corners and the border follows them.

Drop shadow

Unlike shadow_* (always a rectangle), drop_shadow_* blurs the actual shape of the part. Added to LV_PART_INDICATOR, the active arc gets a red shadow with drop_shadow_radius = 16 and an offset of (5, 10) that follows the curve. drop_shadow_* has no XML attribute yet, so this is C.

Four gradient button backgrounds

Stack four buttons using horizontal, vertical, linear, and radial gradients.

Two styles prepare complex gradients: a linear gradient from (0%, 0%) to (20%, 100%) with LV_GRAD_EXTEND_REFLECT, and a radial gradient centered at (30%, 30%) extending to (100%, 100%) with the same reflect mode. Four 150 by 50 buttons are aligned on LV_ALIGN_CENTER: the first two use local bg_grad_dir set to LV_GRAD_DIR_HOR and LV_GRAD_DIR_VER, and the last two apply the linear and radial gradient styles. A fallback label reports when LV_USE_DRAW_SW_COMPLEX_GRADIENTS is disabled.

Conical gradient metallic knob

Fill a circular object with a reflected conical gradient to mimic brushed metal.

A fully rounded radius = 500 style sets a black drop shadow and a background lv_grad_dsc_t built with lv_grad_conical_init centered on the object with LV_GRAD_EXTEND_REFLECT. The gradient uses up to eight grey stops depending on LV_GRADIENT_MAX_STOPS. The styled 200 by 200 object is centered on the active screen; when LV_USE_DRAW_SW_COMPLEX_GRADIENTS is disabled, a scrolling label announces the missing feature instead.

Radial gradient background

Fill the screen with a purple-to-black radial gradient.

A style's background lv_grad_dsc_t is built with lv_grad_radial_init, centered on the object and extending to the bottom-right corner with LV_GRAD_EXTEND_PAD. The stops run from 0x9B1842 to black. An object sized to the display resolution is created on the active screen and centered. When LV_USE_DRAW_SW_COMPLEX_GRADIENTS is disabled, a scrolling label reports the missing feature instead.

Image recolor and rotation

Tint and rotate an image purely through style properties.

image_recolor with image_recolor_opa="50%" mixes a blue tint into the bitmap without touching the source, and transform_rotation="300" turns the widget 30° (the unit is 0.1°). The radius, bg_color, and border_* on the same style transform together with the image.

Line stroke

line_color and line_width set the stroke and line_rounded rounds the end caps and vertices so the bends look smooth instead of mitred. The point array is fixed; only the stroke style changes the look. Line points are a C lv_point_precise_t array, which is why this is C.

Local style override

Local properties — including state selectors — beat the shared style.

All three buttons share style_shared (indigo, dark border, radius). "Override" adds a plain local style_bg_color, so it is always pink. "On press" adds a state-scoped local style_bg_color-pressed, so it turns green only while held. Both keep the shared border, showing local styles — and local state selectors — have the highest precedence.

Margin

Reserve space around one item on top of the layout's own gaps.

The row sets style_pad_column="8" between chips. The middle chip adds style_margin_left="24" and style_margin_right="24", so it sits visibly further from its neighbors than the 8 px flex gap — margin reserves space around a Widget without changing the Widget's size.

Compare a full-screen dim layer against a recolor overlay for modal dialogs.

The scene from lv_example_style_multiple is reused as the background, then a modal overlay is drawn over it. By default a semi-transparent black background is set on lv_layer_top(); toggling the #if 0 branch switches to lv_obj_set_style_recolor on the active screen instead. A slider is added to lv_layer_top() and centered, then lv_refr_now and lv_tick_elaps print the render cost of the chosen approach through LV_LOG_USER.

Cascading styles

Stack a second style that overrides only a few properties of a shared base.

style_base defines the whole card — fill, border, shadow, radius, padding, text color. style_warning sets only bg_color, border_color, and text_color. The right card has both: the later style wins for the properties it sets, the base shows through for the rest, so one small style re-themes the card without redefining it.

Opacity and transform

Fade and geometrically transform a Widget via style properties.

Three identical buttons: the first is untouched, the second sets style_opa="128" (50%), the third also rotates 15° with style_transform_rotation="150" and scales to 1.25× with style_transform_scale_x/y="320". opa and the transforms render the button to a layer first, so its label fades and transforms with it.

Outline

Add a focus-style ring that sits outside the card and ignores layout.

An outline is painted outside the box, so unlike a border it never resizes the Widget. outline_color + outline_width="3" draw the ring and outline_pad="6" is the gap between the card edge and the ring — the look of a modern keyboard-focus halo.

Padding

Inset a Widget's content per side with the directional pad_* properties.

Padding shrinks the content area. The left card pads only top and left (style_pad_top/style_pad_left = 26, the opposite sides 8); the right card pads every side by 18. An accent block fills each card at 100% × 100%, so the offset makes asymmetric vs uniform inset obvious.

Parts and states

Style one part normally and again for a state with selector.

selector="indicator" gives the slider's filled part a violet→pink gradient. selector="pressed|indicator" adds a glow that applies only while the indicator is pressed, so the same part carries one base look plus a state-specific overlay — the core of LVGL's part/state model.

Box shadow

Lift a card off the page with a soft, offset shadow.

shadow_width="30" sets the blur and shadow_color tints it. shadow_offset_y="12" drops the shadow below the card so it reads as elevation, and shadow_opa="80" keeps it soft. With both offsets at 0 the same blur becomes an even glow instead.

Size and padding

Set a Widget's width and padding; its height follows the content.

Both cards share one style but set a different width (140 vs 240) and style_pad_all (12 vs 28). height="content" lets each grow to exactly fit its label plus that padding, so the same style yields a tight chip and a roomy panel — size comes only from these properties.

Text styling

Color text, widen letter/line spacing, and underline it.

text_color recolors the glyphs, text_letter_space="4" and text_line_space="14" open up tracking and leading, and text_decor="underline" underlines every line — the spacing makes the two lines read as a styled heading rather than body text.

Extending the current theme

Create a child theme that adds a green style to every button.

A first button labeled Original theme is added to the active screen under the system theme. The helper new_theme_init_and_set clones the current theme via lv_theme_copy, reparents it with lv_theme_set_parent, and registers an apply callback that attaches style_btn to any lv_button_class object. The new theme is assigned with lv_display_set_theme, and a second button labeled New theme renders with the green background and darker border. A LV_EVENT_DELETE handler on the display frees the theme.

Transform a card with arc and slider

Rotate and scale a styled profile card using an arc and a slider.

Separate styles configure a grid-based card with shadow and rounded corners, a circular avatar with shadow, and a gradient like-button. The helper card_create assembles the card from an avatar image, a name label, and a like-button. Two cards are centered on the active screen; the back one is faded with LV_OPA_50. A large arc and a bottom-aligned slider drive the front card through LV_EVENT_VALUE_CHANGED: the arc writes transform_rotation from lv_arc_get_angle_end * 10, while the slider (range 128 to 300, initial 256) sets transform_scale_x and transform_scale_y.

Style transitions on press

Smoothly animate color and border changes when an object is pressed.

Two lv_style_transition_dsc_t instances animate LV_STYLE_BG_COLOR, LV_STYLE_BORDER_COLOR, and LV_STYLE_BORDER_WIDTH: the default transition runs for 100 ms with a 200 ms delay, while the pressed transition runs for 500 ms with no delay. A red pressed style is attached to LV_STATE_PRESSED on a centered base object, so pressing it eases to red and releasing eases back.

Last updated on

On this page