docs/src/common-widget-features/styles/overview.rst
.. include:: /include/external_links.txt .. _styles_overview:
Styles are used to set the appearance of Widgets. Styles in LVGL are heavily inspired
by CSS. The concept in a nutshell is that a style is an :cpp:type:lv_style_t
variable which can hold properties like border width, font, text color and so on.
It's similar to a class in CSS.
style_blue to the knob of a slider when it's
in pressed state.style_btn can result in a default gray button and style_btn_red can add only
a background-color=red to overwrite the background color.local styles <style_local> with higher precedence than
"normal" styles.:focus), in
LVGL a property is assigned to a given state.For the full list of style properties click :ref:here <style_properties>.
.. _style_states:
States
The Widgets can be in the combination of the following states:
LV_STATE_DEFAULT: (0x0000) Normal, released stateLV_STATE_CHECKED: (0x0001) Toggled or checked stateLV_STATE_FOCUSED: (0x0002) Focused via keypad or encoder or
clicked via touchpad/mouseLV_STATE_FOCUS_KEY: (0x0004) Focused via keypad or encoder but
not via touchpad/mouseLV_STATE_EDITED: (0x0008) Edit by an encoderLV_STATE_HOVERED: (0x0010) Hovered by mouseLV_STATE_PRESSED: (0x0020) Being pressedLV_STATE_SCROLLED: (0x0040) Being scrolledLV_STATE_DISABLED: (0x0080) Disabled stateLV_STATE_USER_1: (0x1000) Custom stateLV_STATE_USER_2: (0x2000) Custom stateLV_STATE_USER_3: (0x4000) Custom stateLV_STATE_USER_4: (0x8000) Custom stateA Widget can be in a combination of states such as being focused and pressed at the
same time. This is represented as :cpp:expr:LV_STATE_FOCUSED | LV_STATE_PRESSED.
A style can be added to any state or state combination. For example, setting a
different background color for the default and pressed states. If a property is not
defined in a state the best matching state's property will be used. Typically this
means the property with :cpp:enumerator:LV_STATE_DEFAULT is used. If the property is
not set even for the default state the default value will be used. (See later)
Since :cpp:enumerator:LV_PART_MAIN and :cpp:enumerator:LV_STATE_DEFAULT both have
zero values, you can simply pass 0 as the selector argument instead of
LV_PART_MAIN | LV_STATE_DEFAULT as a shortcut when adding styles to an object.
States have a precedence which is shown by their value (see in the above list). A higher value means higher precedence. To determine which state's property to use let's take an example. Imagine the background color is defined like this:
LV_STATE_DEFAULT: whiteLV_STATE_PRESSED: grayLV_STATE_FOCUSED: redLV_STATE_PRESSED | LV_STATE_FOCUSED. In this case, this combined state
has 0x0020 + 0x0002 = 0x0022 precedence, which is higher than the pressed state's
precedence so rose color would be used.Some practical notes:
.. _style_cascading:
Cascading Styles
It's not required to set all the properties in one style. It's possible to add more styles to a Widget and have the latter added style modify or extend appearance. For example, create a general gray button style and create a new one for red buttons where only the new background color is set.
This is much like in CSS when used classes are listed like <div class=".btn .btn-red">.
Styles added later have precedence over ones set earlier. So in the gray/red button example above, the normal button style should be added first and the red style second. However, the precedence of the states are still taken into account. So let's examine the following case:
In this case, when the button is released (it's in default state) it will be red because a perfect match is found in the most recently added style (red). When the button is pressed the light-gray color is a better match because it describes the current state perfectly, so the button will be light-gray.
.. _style_inheritance:
Inheritance
Some properties (typically those related to text) can be inherited from the parent Widget's styles. Inheritance is applied only if the given property is not set in the Widget's styles (even in default state). In this case, if the property is inheritable, the property's value will be searched up the parent hierarchy until a Widget specifies a value for the property. The parents will use their own state to determine the value. So if a button is pressed, and the text color comes from a parent, the pressed text color will be used.
.. _style_parts:
Parts
Widgets can be composed of parts which may each have their own styles.
The following predefined parts exist in LVGL:
LV_PART_MAIN: (0x000000) A background like rectangleLV_PART_SCROLLBAR: (0x010000) The scrollbar(s)LV_PART_INDICATOR: (0x020000) Indicator, e.g. for slider, bar,
switch, or the tick box of the checkboxLV_PART_KNOB: (0x030000) Like a handle to grab to adjust a valueLV_PART_SELECTED: (0x040000) Indicate the currently selected
option or sectionLV_PART_ITEMS: (0x050000) Used if the widget has multiple similar
elements (e.g. table cells)LV_PART_CURSOR: (0x060000) Mark a specific place e.g. Text Area's
or chart's cursorLV_PART_CUSTOM_FIRST: (0x080000) Custom part identifiers can be
added starting from here.LV_PART_ANY: (0x0F0000) Special value can be used in some
functions to target all parts.For example a :ref:Slider <lv_slider> has three parts:
This means all three parts of the slider can have their own styles. See later how to add styles to Widgets and parts.
Since :cpp:enumerator:LV_PART_MAIN and :cpp:enumerator:LV_STATE_DEFAULT both have
zero values, you can simply pass 0 as the selector argument instead of
LV_PART_MAIN | LV_STATE_DEFAULT as a shortcut when adding styles to an object.
.. _style_opacity_blend_modes_transformations:
Properties Requiring New Layers
If the opa, blend_mode, transform_angle, or transform_zoom properties
are set to a non-default value LVGL creates a snapshot of the widget and its children
in order to blend the whole widget with the set opacity, blend mode and transformation
properties.
These properties have this effect only on the MAIN part of the widget.
The created snapshot is called "intermediate layer" or simply "layer". If only opa
and/or blend_mode is set to a non-default value LVGL can build the layer from
smaller chunks. The size of these chunks can be configured by the following properties
in lv_conf.h:
LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size.
LVGL will try to allocate this size of memory.LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if
:cpp:enumerator:LV_LAYER_SIMPLE_BUF_SIZE couldn't be allocated.If transformation properties were also used the layer cannot be rendered in chunks
.. _typical bg props:
Typical Background Properties
In documentation of widgets you will see sentences like "XY Widget uses the typical background style properties". These "typical background properties" are the properties being referred to:
.. _style_examples:
Examples
.. include:: /examples/styles/index.rst