Version: 2023.1
Apply styles in C# scripts
Theme Style Sheet (TSS)

Best practices for USS

Follow these best practices when you write USS to style visual elements.

Avoid inline styles

Use USS files instead of inline styles when you can for more efficient memory usage.

Inline styles are per element and can cause memory overhead. When you use inline styles in a C# script or a UXML file on many elements, the memory usage becomes high quickly.

Selector architecture consideration

All USS selectors are applied at runtime so the architecture affects initialization performance. USS selectors are applied when an element first appears or when its classes change:

  • The :hover selector is the main culprit for selectors to cause interactivity issues and a re-styling.
  • The performance impact appears under the Update Styling in the Profiler.

Usually, it’s not a problem if you have a lot of selectors because each USS file is turned into a lookup table. However, the performance decreases linearly as you add classes to an element. Each class in the list is used to query the lookup table. The complexity is N1 x N2, where:

  • N1 is the number of class on the element
  • N2 is the current number of applicable USS files

The number of elements in the hierarchy is the main fact that affects performance. Update Styling might be negligible for simple UIs but is significant for large UIs that have several thousands of elements. If an element matches a lot of selectors, it causes overhead to merge the styles coming from each rule.

Complex selectors hierarchy guidelines

In general, complex selectors have more impact on performance than simple selectors. Complex selectors depend on the ancestors of an element to match it. When possible, consider the following:

  • If you want to have partial match, use the child selector (selector1 > selector2 > selector3) instead of the descendant selector (selector1 selector2 selector3).
  • Avoid using universal selector at the end of complex selectors (selector1 > selector2 > *) or the combination of descendant selector with the universal selector (selector1 * selector2). The universal selector tests every potential element against the selector which can impact performance.
  • Avoid using :hover pseudo-class in selectors on elements with many descendants, such as .yellow:hover > * > Button. Mouse movements invalidate the entire hierarchy of elements targeted by an :hover selector.

Use BEM to improve performance

You can use the Block Element Modifier(BEM) convention to reduce hierarchical selectors. With BEM, each element receives a class that combines its specific existence inside another element.

About BEM

BEM 表示块元素修饰符。BEM 是一个简单的系统,有助于编写结构化、明确、易于维护的选择器。通过 BEM 可以向元素分配类,然后将这些类用作样式表中的选择器。

BEM 类最多包含三个组件:

  • 块名称:块是有意义的独立实体或控件。例如,menubuttonlist-view
  • 元素名称:块的一部分,没有独立含义,并且在语义上与其块相关。元素名称用两个下划线追加到块名称之后。例如,menu__itembutton__iconlist-view__item
  • 修饰符:一个可更改块或元素外观或行为的标记。修饰符用两个短划线追加到块或元素名称之后。例如,menu--disabledmenu__item--disabledbutton--smalllist-view__item--selected

每个名称部分可能由拉丁字母、数字和短划线组成。每个名称部分用双下划线 __ 或双短划线 -- 连接起来。

The following example shows UXML code for a menu:

<VisualElement class="menu">
    <Label class="menu__item" text="Banana" />
    <Label class="menu__item" text="Apple" />
    <Label class="menu__item menu__item--disabled" text="Orange" />
</VisualElement>

Each element is equipped with classes that describe its role and appearance, you can write most of your selectors with only one class name:

.menu {
}

.menu__item {
}

.menu__item--disabled {
}

You can style elements with a single class name. Sometimes, you might need to use complex selectors. For example, you can use a complex selector when the style of an element depends on the modifier of its block:

.button {
}

.button__icon {
}

.button--small {
}

.button--small .button__icon {
}

注意

  • Avoid specifying long selectors. A long selector could indicate inconsistencies in the graphic design of your UI.
  • Avoid using type names (Button, Label) or element names (#my-button) in your BEM selectors.

Make visual elements BEM-friendly

UI 工具包遵循 BEM。每个视觉元素都附有必要的类名。例如,所有 TextElement 具有 unity-text-element 类。从 TextElement 派生的 Button 的每个实例在类列表中都填充有 unity-buttonunity-text-element 类。

如果从 VisualElement 或其某个后代派生新元素,请遵循以下准则以确保元素易于使用 BEM 方法进行样式设置:

  • 使用构造函数中的 AddToClassList(),将相关 USS 类添加到元素实例。
  • 如果新元素在其构造函数中实例化子元素,请将相关类分配给子元素。例如,my-block__first-childmy-block__other-child
  • 如果您的元素支持多种状态或变体(例如不同大小),请在元素状态变化或选择元素变体时添加和删除相关类。
  • If you use the element in other projects, consider prefixing your classes to avoid conflicts with existing user class names.

其他资源

Apply styles in C# scripts
Theme Style Sheet (TSS)