UI 组件的样式

Vaadin 和 Jmix 组件都提供了多种更改外观样式的方法。建议先使用高级别的样式定义,仅在必要时编写自定义 CSS。

按以下顺序使用:

  1. 自定义应用程序主题。

  2. 使用组件内置的样式版本。

  3. 为组件自定义 CSS。

  4. 在 Java 中更改样式。

应用程序主题

通过主题可以为应用程序及其组成部分设置统一的样式。Vaadin 为 Aura 和 Lumo 都提供了 可视化主题编辑器,可以配置样式属性。

请参见 自定义 Aura自定义 Lumo

组件样式版本

许多组件提供了内置的样式版本,可以更改颜色、大小或其他样式。通过 themeNames XML 属性或 Java API(例如 addThemeVariants()addThemeNames())设置组件的不同样式。

<hbox>
    <button text="Primary" themeNames="primary"/>
    <button text="Success" themeNames="success"/>
    <button text="Tertiary" themeNames="tertiary"/>
</hbox>
button theme variants
Figure 1. 不同样式版本的按钮
Aura 和 Lumo 支持的组件样式版本并不完全相同。组件的参考文档中标明了每个样式版本是支持 Aura、Lumo 还是两者都支持。

自定义组件样式版本

可以使用针对 theme 属性的 CSS 来覆盖内置的组件样式版本:

my-project.css
vaadin-button[theme~="primary"] {
    background-color: purple;
}

将 CSS 应用于组件

通过应用程序 CSS 可以设置组件的样式属性,或编写针对组件内部元素和状态的样式。

对于 Vaadin 组件,请参考其官方文档中组件的 Styling 页面查找支持的样式属性和选择器。对于 Jmix 组件,请使用浏览器的开发者工具检查渲染后的结构。如果其中包含 vaadin-* 元素,则还是参考 Vaadin 组件的 Styling 页面。请参见 Vaadin 样式概述

设置所有组件实例的样式

Vaadin 组件提供了带有 --vaadin- 前缀的 CSS 自定义属性。Vaadin 称之为 组件样式属性。这些属性是更改组件样式的主要 API。

html 元素中设置组件样式属性,可以更改所有使用该属性的组件实例。使用组件选择器可以将公共样式属性限制为特定组件类型中的样式:

my-project.css
html {
    --vaadin-button-border-radius: 1em;
}

vaadin-text-field {
    --vaadin-input-field-border-radius: 2em;
}

设置特定组件实例的样式

使用 XML 的 classNames 属性或 Java 的 addClassName() 方法可以为特定的组件设置 CSS 类:

<textField classNames="wide"/>
my-project.css
vaadin-text-field.wide {
    width: 24em;
}

也可以将样式限定在具有自定义类的父元素内的组件:

my-project.css
.button-row vaadin-button {
    flex: 1;
}

组件的 parts

Vaadin 和 Jmix 组件比原生 HTML 元素更复杂。许多内部元素位于 shadow DOM 中。Shadow DOM 可以防止全局 CSS 意外更改内部元素的样式。

element shadow dom
Figure 2. 组件 HTML 元素结构

根元素

每个组件都有一个 HTML 根元素,其名称通常以 vaadin-jmix- 开头,例如 vaadin-buttonjmix-value-picker

my-project.css
jmix-value-picker {
    margin-block: 1em;
}

Shadow Parts

Shadow Parts 是组件 shadow DOM 内部的元素。使用 ::part() 选择器。例如,使用 input-field part 更改文本控件的输入部分:

my-project.css
vaadin-text-field::part(input-field) {
    background: white;
    border: 1px solid black;
}
styled textfield
Figure 3. 具有自定义背景和边框的文本控件
有关组件的所有 shadow parts,请参见 文本控件 CSS 选择器

常规子元素

常规子元素位于组件的 shadow DOM 之外。使用 > 选择器定位直接子元素。例如,以下规则针对的是放在按钮内的图标:

my-project.css
vaadin-button > vaadin-icon {
    color: blue;
}
有关组件支持的 CSS 选择器,请参见 按钮 CSS 选择器

组件状态

组件开放了例如 disabled、read-only、invalid 和 focused 等状态。大多数状态作为属性存在于组件根元素上。状态属性选择器可以与 parts 选择器组合使用:

my-project.css
vaadin-text-field[readonly]::part(input-field) {
    border-color: gray;
}

原生状态(如 hover)使用 CSS 伪类。可以与开放的伪元素组合。例如,Button 为其悬停高亮开放了一个 ::before 伪元素:

my-project.css
vaadin-button:hover::before {
    background-color: blue;
}

在 Java 中更改样式

在 Java 中使用组件的 Style API 设置内联样式:

@ViewComponent
private JmixButton myBtn;

@Subscribe
public void onInit(final InitEvent event) {
    myBtn.getStyle().set("color", "white");
    myBtn.getStyle().set("background-color", "purple");
}
内联样式仅应用于组件根元素。无法直接用于组件的部件,也无法根据组件状态有条件地应用。

另一种方式是使用 CSS 自定义属性。这些属性可以是内置的组件或主题的样式属性,也可以是由应用程序定义的属性。在 CSS 中使用,并在 Java 中设置值:

my-project.css
html {
    --my-button-text-color: darkblue;
    --my-button-bg-color: yellow;
}

vaadin-button.my-button {
    color: var(--my-button-text-color);
    background-color: var(--my-button-bg-color);
}
视图 XML
<button id="myBtn"
        text="Button"
        classNames="my-button"/>
@Subscribe
public void onInit(final InitEvent event) {
    UI.getCurrent().getElement().getStyle()
            .set("--my-button-text-color", "white");
    UI.getCurrent().getElement().getStyle()
            .set("--my-button-bg-color", "purple");
}

CSS 存在于应用程序的样式表中,因此可以针对组件的 parts 和状态。同一个自定义属性也可以在多个 CSS 规则中使用。