Using Themes

The built-in themes are all customisable and provide a great starting point for an application. Completely custom themes can also be built from scratch.

Existing Themes

You can choose to use one of the built-in themes or a theme provided by another package. The Lumo theme is used by default unless explicitly configured otherwise.

Note
It is recommended to start with an existing theme and customize it (instead of creating a completely custom theme) as it is the easier approach and works for the majority of applications.

In server-side views (Java), use the @Theme annotation to choose the theme. The annotation must be set for the root navigation class or the router layout defined in the @Route annotation. Otherwise an exception is thrown on startup.

@Route(value = "")
@Theme(value = Lumo.class)
public class LumoApplication extends Div {
}

Custom Themes

There are two ways to customize themes:

  1. Customize existing themes

  2. Create a completely new theme

It’s easier to customise one of the existing themes. This is accomplished by overriding custom properties and by writing and importing additional style sheets (to further override styles). This approach works best when you only need to make small adjustments. See Styling Components, Lumo, and Material for more information.

If you need to make more substantial changes, which will effectively override a large portion of an existing theme’s CSS, it can be better to create a completely new theme from scratch. See Creating a Custom Theme Class for more information.

No Theme

You can opt-out of loading any theme if you want to control the importing of style sheets manually. This means that you rely on application-specific style sheets to handle component styling. You are also responsible for any lazy-loading or code-splitting of the style sheets.

For server-side views, use the @NoTheme annotation to opt-out of loading any theme style sheets.

@Route(value = "")
@NoTheme
public class UnThemedApplication extends Div {
}

In client-side views/templates, to get a minimal starting point, import the un-themed version of each component. For Vaadin components, the un-themed versions are located in the src folder of each component package.

// For example, if you are using the <vaadin-button> component,
// import the un-themed version
import '@vaadin/vaadin-button/src/vaadin-button.js';

Theme Resolving Order

For server-side views, the following logic is used to determine which theme is used:

  1. If the @Theme annotation is found at the root navigation level, the theme set in the annotation is used

  2. If the @NoTheme annotation is found at the root navigation level, no theme style sheets are loaded

  3. If the com.vaadin.flow.theme.lumo.Lumo class is available in the classpath, the Lumo theme is used

Resolving stops when a match is found. No theme is used if none of the conditions are met.

Limitations

It is not possible to switch themes at runtime

Full page reload is required. You can’t for example use different themes for different views.

It is not possible to mix component themes

For example, you can’t use the Lumo theme for Date Picker and the Material theme for Button at the same time, because Date Picker internally uses the Button component. If you did, both themes would be applied simultaneously and would cause style conflicts.

This mainly affects client-side development, where you have fine-grained control over the component imports which you use in your views and templates.