Link copied to clipboard!

LVGL – Using global styles

Table of Contents

    Introduction

    When building embedded GUIs, style consistency and clean architecture matter.
    LVGL provides a powerful way to control the entire look & feel of your application using global styles and a custom theme system.
    This article explains how to:

    • define global styles,
    • attach them to a custom theme,
    • update the entire interface with a single function call,
    • and why this approach improves engineering workflow, especially in large or growing GUI projects.

    And everything using our standard Riverdi 10″ display.

    How it works

    LVGL allows you to:

    1. Define styles (lv_style_t),
    2. Create a custom theme,
    3. Assign a callback that applies styles based on object type,
    4. Tell LVGL to rebuild the theme and refresh all objects.

    This is an engineering-friendly architecture: one place changes everything.

    Code Example – Reusable Global Theme

    Below is the complete example demonstrating:

    • global styles for buttons and sliders,
    • dynamic palette switching,
    • automatic restyling of all objects.

    Global style variables

    static lv_style_t style_common_main;
    static lv_style_t style_slider_main;
    static lv_style_t style_slider_indicator;
    static lv_style_t style_slider_knob;
    static lv_palette_t current_palette = LV_PALETTE_ORANGE;

    Theme apply callback

    Automatically applies styles to widget by class. Can be easily extended to next widget types.

    static void theme_apply_cb(lv_theme_t * th, lv_obj_t * obj)
    {
    if(lv_obj_check_type(obj, &lv_button_class)) {
    lv_obj_add_style(obj, &style_common_main, 0);
    }

    if(lv_obj_check_type(obj, &lv_slider_class)) {
    lv_obj_add_style(obj, &style_slider_main, LV_PART_MAIN);
    lv_obj_add_style(obj, &style_slider_indicator, LV_PART_INDICATOR);
    lv_obj_add_style(obj, &style_slider_knob, LV_PART_KNOB);
    }
    }

    Rebuild theme (core engineering trick)

    This rebuilds styles, attaches them to a theme, and forces a global refresh.

    static void rebuild_theme(void)
    {
    lv_style_reset(&style_common_main);
    lv_style_reset(&style_slider_main);
    lv_style_reset(&style_slider_indicator);
    lv_style_reset(&style_slider_knob);

    /* Button style */
    lv_style_init(&style_common_main);
    lv_style_set_bg_color(&style_common_main, lv_palette_main(current_palette));
    lv_style_set_border_color(&style_common_main, lv_palette_darken(LV_PALETTE_BLUE, 3));
    lv_style_set_border_width(&style_common_main, 3);
    lv_style_set_radius(&style_common_main, 6);

    /* Slider styles */
    lv_style_init(&style_slider_main);
    lv_style_set_bg_color(&style_slider_main, lv_palette_lighten(current_palette, 2));
    lv_style_set_bg_opa(&style_slider_main, LV_OPA_COVER);

    lv_style_init(&style_slider_indicator);
    lv_style_set_bg_color(&style_slider_indicator, lv_palette_darken(current_palette, 2));

    lv_style_init(&style_slider_knob);
    lv_style_set_bg_color(&style_slider_knob, lv_color_white());

    /* Attach theme */
    lv_theme_t * th_act = lv_display_get_theme(NULL);
    static lv_theme_t th_new;
    th_new = *th_act;

    lv_theme_set_parent(&th_new, th_act);
    lv_theme_set_apply_cb(&th_new, theme_apply_cb);
    lv_display_set_theme(NULL, &th_new);

    lv_obj_report_style_change(NULL);
    }

    Switch theme color

    Here we have the function that changes the color in the currently used theme when pressing the button. It is just to present the ease of doing that. For more colors, I recommend using an array.

    static void color_change_event_cb(lv_event_t * e)
    {
    if(current_palette == LV_PALETTE_ORANGE)
    current_palette = LV_PALETTE_GREEN;
    else if(current_palette == LV_PALETTE_GREEN)
    current_palette = LV_PALETTE_BLUE;
    else
    current_palette = LV_PALETTE_ORANGE;

    rebuild_theme();
    }

    Final demonstration

    Here we create the default button on the top from the display center. Then we call rebuild_theme() function to change the main style of widgets we use. Now we can create another button below the first one and also create a slider below it. You should be able to see the different styles between the buttons. Also, after pressing the button, we change the style color of the new widgets, while the default one stays unchanged.

    void lv_example_style_change(void)
    {
    lv_obj_t * btn_default = lv_button_create(lv_screen_active());
    lv_obj_align(btn_default, LV_ALIGN_CENTER, 0, -100);
    lv_label_set_text(lv_label_create(btn_default), “Default button”);

    rebuild_theme();

    lv_obj_t * btn_themed = lv_button_create(lv_screen_active());
    lv_obj_align(btn_themed, LV_ALIGN_CENTER, 0, 100);
    lv_obj_add_event_cb(btn_themed, color_change_event_cb, LV_EVENT_CLICKED, NULL);
    lv_label_set_text(lv_label_create(btn_themed), “Change Theme Color”);

    lv_obj_t * slider = lv_slider_create(lv_screen_active());
    lv_obj_align(slider, LV_ALIGN_CENTER, 0, 200);
    lv_obj_set_width(slider, 250);
    lv_slider_set_value(slider, 40, LV_ANIM_OFF);
    }

    Why global styles are useful

    Most engineers quickly discover that GUI styling becomes messy when every button, slider, or widget has its own style code.

    Global themes solve several engineering problems:

    1. Centralized visual control

    All styling logic is in one place. You don’t need to visit 10 files to change a button or slider.

    1. Faster UI changes

    Switching brand colors is instant.
    Marketing asks for “green instead of orange”?
    Change one variable → the entire GUI updates.

    1. Scalable architecture for large projects

    When the UI grows beyond a few screens, local styling becomes unmanageable.
    Global themes guarantee:

    • consistent margins,
    • consistent radiuses,
    • consistent palette usage,
    • consistent widget behavior.

     

    1. No copy–paste styling

    Without themes, engineers duplicate style code across screens.

    Global styles eliminate duplication and reduce code size.

    1. Runtime theme switching like:
      • Dark/Light mode,
      • User-selectable themes,
      • Safety modes (e.g., “Warning” UI uses red theme),
      • OEM branding (one firmware, multiple visual skins).

     

    If you want to learn more, visit LVGL website.

    DISCOVER OUR

    Whitepaper

    Achieve the perfect user-display interaction with the right Touch Sensor IC. Ever faced issues with phantom touch events or certification? Boost your R&D like a pro with our Whitepaper!

    Save by quality

    Go to our product catalog and see how you can save by quality, not on quality.

    Contact us now, save with quality, not on quality.