The Style Sheet Syntax

omni.ui Style Sheet rules are almost identical to those of HTML CSS. It applies to the style of all omni ui elements.

Style sheets consist of a sequence of style rules. A style rule is made up of a selector and a declaration. The selector specifies which widgets are affected by the rule. The declaration specifies which properties should be set on the widget. For example:

![Code Result](The Style Sheet Syntax_0.png)

with ui.VStack(width=0, style={"Button": {"background_color": cl("#097eff")}}):
    ui.Button("Style Example")

In the above style rule, Button is the selector, and {“background_color”: cl(“#097eff”)} is the declaration. The rule specifies that Button should use blue as its background color.

Selector

There are three types of selectors, type Selector, name Selector and state Selector They are structured as:

Type Selector :: Name Selector : State Selector

e.g.,Button::okButton:hovered

Type Selector

where Button is the type selector, which matches the ui.Button’s type.

Name Selector

okButton is the type selector, which selects all Button instances whose object name is okButton. It separates from the type selector with ::.

State Selector

hovered is the state selector, which by itself matches all Button instances whose state is hovered. It separates from the other selectors with :.

When type, name and state selector are used together, it defines the style of all Button typed instances named as okButton and in hovered, while Button:hovered defines the style of all Button typed instances which are in hovered states.

These are the states recognized by omni.ui:

  • hovered : the mouse in the widget area

  • pressed : the mouse is pressing in the widget area

  • selected : the widget is selected

  • disabled : the widget is disabled

  • checked : the widget is checked

  • drop : the rectangle is accepting a drop. For example, style = {“Rectangle:drop” : {“background_color”: cl.blue}} meaning if the drop is acceptable, the rectangle is blue.

Style Override

Omit the selector

It’s possible to omit the selector and override the property in all the widget types.

In this example, the style is set to VStack. The style will be propagated to all the widgets in VStack including VStack itself. Since only background_color is in the style, only the widgets which have background_color as the style will have the background color set. For VStack and Label which don’t have background_color, the style is ignored. Button and FloatField get the blue background color.

![Code Result](The Style Sheet Syntax_1.png)

from omni.ui import color as cl
with ui.VStack(width=400, style={"background_color": cl("#097eff")}, spacing=5):
    ui.Button("One")
    ui.Button("Two")
    ui.FloatField()
    ui.Label("Label doesn't have background_color style")

Style overridden with name and state selector

In this example, we set the “Button” style for all the buttons, then override different buttons with name selector style, e.g. “Button::one” and “Button::two”. Furthermore, the we also set different style for Button::one when pressed or hovered, e.g. “Button::one:hovered” and “Button::one:pressed”, which will override “Button::one” style when button is pressed or hovered.

![Code Result](The Style Sheet Syntax_2.png)

from omni.ui import color as cl
style1 = {
    "Button": {"border_width": 0.5, "border_radius": 0.0, "margin": 5.0, "padding": 5.0},
    "Button::one": {
        "background_color": cl("#097eff"),
        "background_gradient_color": cl("#6db2fa"),
        "border_color": cl("#1d76fd"),
    },
    "Button.Label::one": {"color": cl.white},
    "Button::one:hovered": {"background_color": cl("#006eff"), "background_gradient_color": cl("#5aaeff")},
    "Button::one:pressed": {"background_color": cl("#6db2fa"), "background_gradient_color": cl("#097eff")},
    "Button::two": {"background_color": cl.white, "border_color": cl("#B1B1B1")},
    "Button.Label::two": {"color": cl("#272727")},
    "Button::three:hovered": {
        "background_color": cl("#006eff"),
        "background_gradient_color": cl("#5aaeff"),
        "border_color": cl("#1d76fd"),
    },
    "Button::four:pressed": {
        "background_color": cl("#6db2fa"),
        "background_gradient_color": cl("#097eff"),
        "border_color": cl("#1d76fd"),
    },
}

with ui.HStack(style=style1):
    ui.Button("One", name="one")
    ui.Button("Two", name="two")
    ui.Button("Three", name="three")
    ui.Button("Four", name="four")
    ui.Button("Five", name="five")

Style override to different levels of the widgets

It’s possible to assign any style override to any level of the widgets. It can be assigned to both parents and children at the same time.

In this example, we have style_system which will be propagated to all buttons, but buttons with its own style will override the style_system.

![Code Result](The Style Sheet Syntax_3.png)

from omni.ui import color as cl
style_system = {
    "Button": {
        "background_color": cl("#E1E1E1"),
        "border_color": cl("#ADADAD"),
        "border_width": 0.5,
        "border_radius": 3.0,
        "margin": 5.0,
        "padding": 5.0,
    },
    "Button.Label": {
        "color": cl.black,
    },
    "Button:hovered": {
        "background_color": cl("#e5f1fb"),
        "border_color": cl("#0078d7"),
    },
    "Button:pressed": {
        "background_color": cl("#cce4f7"),
        "border_color": cl("#005499"),
        "border_width": 1.0
    },
}

with ui.HStack(style=style_system):
    ui.Button("One")
    ui.Button("Two", style={"color": cl("#AAAAAA")})
    ui.Button("Three", style={"background_color": cl("#097eff"), "background_gradient_color": cl("#6db2fa")})
    ui.Button(
        "Four", style={":hovered": {"background_color": cl("#006eff"), "background_gradient_color": cl("#5aaeff")}}
    )
    ui.Button(
        "Five",
        style={"Button:pressed": {"background_color": cl("#6db2fa"), "background_gradient_color": cl("#097eff")}},
    )

Customize the selector type using style_type_name_override

What if the user has a customized widget which is not a standard omni.ui one. How to define that Type Selector? In this case, We can use style_type_name_override to override the type name. name attribute is the Name Selector and State Selector can be added as usual.

Another use case is when we have a giant list of the same typed widgets, for example Button, but some of the Buttons are in the main window, and some of the Buttons are in the pop-up window, which we want to differentiate for easy look-up. Instead of calling all of them the same Type Selector as Button and only have different Name Selectors, we can override the type name for the main window buttons as WindowButton and the pop-up window buttons as PopupButton. This groups the style-sheet into categories and makes the change of the look or debug much easier.

Here is an example where we use style_type_name_override to override the style type name.

![Code Result](The Style Sheet Syntax_4.png)

from omni.ui import color as cl
style={
    "WindowButton::one": {"background_color": cl("#006eff")},
    "WindowButton::one:hovered": {"background_color": cl("#006eff"), "background_gradient_color": cl("#FFAEFF")},
    "PopupButton::two": {"background_color": cl("#6db2fa")},
    "PopupButton::two:hovered": {"background_color": cl("#6db2fa"), "background_gradient_color": cl("#097eff")},
    }

with ui.HStack(width=400, style=style, spacing=5):
    ui.Button("Open", style_type_name_override="WindowButton", name="one")
    ui.Button("Save", style_type_name_override="PopupButton", name="two")

Default style override

From the above examples, we know that if we want to propagate the style to all children, we just need to set the style to the parent widget, but this rule doesn’t apply to windows. The style set to the window will not propagate to its widgets. If we want to propagate the style to ui.Window and their widgets, we should set the default style with ui.style.default.

from omni.ui import color as cl
ui.style.default = {
    "background_color": cl.blue,
    "border_radius": 10,
    "border_width": 5,
    "border_color": cl.red,
}

Debug Color

All shapes or widgets can be styled to use a debug color that enables you to visualize their frame. It is very useful when debugging complicated ui layout with overlaps.

Here we use red as the debug_color to indicate the label widget:

![Code Result](The Style Sheet Syntax_6.png)

from omni.ui import color as cl
style = {"background_color": cl("#DDDD00"), "color": cl.white, "debug_color":cl("#FF000055")}

ui.Label("Label with Debug", width=200, style=style)

If several widgets are adjacent, we can use the debug_color in the hovered state to differentiate the widget with others.

![Code Result](The Style Sheet Syntax_7.png)

from omni.ui import color as cl
style = {
    "Label": {"padding": 3, "background_color": cl("#DDDD00"),"color": cl.white},
    "Label:hovered": {"debug_color": cl("#00FFFF55")},}

with ui.HStack(width=500, style=style):
    ui.Label("Label 1", width=50)
    ui.Label("Label 2")
    ui.Label("Label 3", width=100, alignment=ui.Alignment.CENTER)
    ui.Spacer()
    ui.Label("Label 3", width=50)

Visibility

This property holds whether the shape or widget is visible. Invisible shape or widget is not rendered, and it doesn’t take part in the layout. The layout skips it.

In the following example, click the button from one to five to hide itself. The Visible all button brings them all back.

![Code Result](The Style Sheet Syntax_8.png)

def invisible(button):
    button.visible = False

def visible(buttons):
    for button in buttons:
        button.visible = True

buttons = []
with ui.HStack():
    for n in ["One", "Two", "Three", "Four", "Five"]:
        button = ui.Button(n, width=0)
        button.set_clicked_fn(lambda b=button: invisible(b))
        buttons.append(button)

    ui.Spacer()
    button = ui.Button("Visible all", width=0)
    button.set_clicked_fn(lambda b=buttons: visible(b))