Blog

Theming Vaadin applications: a practical guide

By  
Sebastian Kuehnau
Sebastian Kuehnau
·
On Dec 17, 2024 4:27:48 PM
·

The appearance of a web application plays a key role in the user experience and how your Vaadin application will be accepted in your Usergroup. With Vaadin's powerful theming system and style options, you can customize your application's design to meet the requirements of corporate brandings and usability aspirations.

In this article, you will learn:

  1. How to apply themes in Vaadin applications,
  2. How to style individual components and what to consider with Web Components,
  3. Best practices for styling your application.

Understanding Vaadin theming

Vaadin separates the logic of an application from its style definition and appearance using themes. This enables the source code to be kept clearly organized and separated according to technical requirements and creates reusable styles across views and components. The default theme, Lumo, provides a consistent and modern design that can be extended with customizations.

Applying a theme

As mentioned, the Lumo Theme is applied automatically. To use a custom theme, apply the @Theme annotation to the class implementing AppShellConfigurator:

@Theme("my-stylish-theme")
public class Application implements AppShellConfigurator {
...
}

The theme is loaded from the theme folder inside the frontend/themes directory. A styles.css file must be located there, which can then integrate other parts of the styling like fonts, colors, styles for components, and views. You can define Variants such as LIGHT and DARK, which can be toggled at runtime. The theme itself can’t be changed during runtime.

Steps to create a custom theme:

  1. Create the folder src/main/frontend/themes/my-stylish-theme.
  2. Add a styles.css file.
  3. Activate the theme using @Theme("my-stylish-theme").

The diagram shows you how to make style definitions in a Vaadin application.

The diagram shows you how to make style definitions in a Vaadin application.

The essence of styling best practices is to address as much as possible through the theme and CSS. Next, leverage options in the Java code when necessary, and only as a last resort, apply styles directly to the specific element.

Styling specific components

There are several ways to customize the design of individual components in Vaadin:

1. Customizing CSS Variables

You can modify CSS variables defined by the Lumo theme to ensure consistent styling:

heading text in orange

html {
   --lumo-header-text-color: orange;
}

To customize the CSS variables, have a look at the Lumo Editor.

To add custom variables:

underlined text

html {
   --my-stylish-color: orange;
}

h1 {
   color: var(--my-stylish-color);
   text-decoration: var(--my-stylish-color) underline;
}

These CSS variables are great because they set constants for colors or distances in the application that you can easily reuse and avoid using inconsistent colors or using the 9th shade of white in the application.

2. Using CSS Classes

Create custom classes and link them to components: Styling in Vaadin text in orange and underlined

.headline {
   color: var(--my-stylish-color);
   font-size: var(--lumo-font-size-xxl);
   text-decoration: var(--my-stylish-color) underline;
}

Linking the class in Java:

viewTitle.addClassNames("headline");

3. Using theme variants

Many components support predefined theme variants that can be applied directly:black button with white text

var blackButton = new Button("black");
blackButton.addThemeVariants(
ButtonVariant.LUMO_CONTRAST,
     ButtonVariant.LUMO_PRIMARY);
add(blackButton);

4. Styling with Lumo utility classes

Vaadin provides CSS utility classes accessible through LumoUtility: red button with white text

var redButton = new Button("red");
redButton.addClassNames(
       LumoUtility.Background.ERROR,
       LumoUtility.TextColor.ERROR_CONTRAST);
add(redButton);

5. Global and individual styles

Global styling, which is applied to all components of the application: blue button with white text

/***** global *****/
vaadin-button {
   background-color: dodgerblue;
   color: white;
}

Individual styling, which is applied to components with the according classname:orange button with white text

/***** individual *****/
vaadin-button.orange-button {
   background-color: orange;
   color: white;
}

6. Styling specific views

To restrict styles to a specific view or area, you can add CSS class names to the view: purple button with white text

.styling-view {
   vaadin-button {
       width: 200px;
   }

   vaadin-button.purple-button {
       background-color: purple;
       color: white;
   };
}

7. Direct styling in Java

Flexible styling is also possible through direct CSS definitions in Java via Vaadin's Style API. This should be used sparingly, as it can be error-prone:green button with white text

var greenButton = new Button("green");
greenButton.getStyle()
       .set("background-color", "green")
       .set("color", "white") ;
add(greenButton);

Consideration of Web Component specifics

As Vaadin components are Web Components, access to various parts of a component is regulated. The Vaadin documentation lists the available parts, states, and style variants that can be adjusted accordingly.

var purpleButton = new Button("purple");
purpleButton.setPrefixComponent(VaadinIcon.BELL.create());
purpleButton.setSuffixComponent(VaadinIcon.BELL.create());
purpleButton.addClassNames("purple-button");
add(purpleButton);

vaadin-button.purple-button::part(suffix),
vaadin-button.purple-button::part(prefix) {
   color: gold;
}

purple button with white text and gold bells

Best practices for styling Vaadin applications

1. Leverage existing interfaces

Prioritize customizing CSS variables or using theme variants before directly setting CSS attributes.

//working but not elegant
greenButton.getElement().getStyle()
.set("background-color", "green");

//fine but improvable
greenButton.addClassNames(
     LumoUtility.Background.SUCCESS,
     LumoUtility.TextColor.PRIMARY_CONTRAST);

//very nice
greenButton.addClassNames("green-button");

This is my personal opinion. Each option has merits, depending on the specific requirement and application.

2. Organize styles

Separate global styles, view-specific styles, and component styles into different CSS files:

@import url('./main-layout.css');
@import url('./views/master-detail-view.css');
@import url('./views/stylish-view.css');

/**** Global Styling Definition ****/
html {
   /*--lumo-header-text-color: orange;*/
   --my-stylish-color: orange;
}

h1 {
   color: var(--my-stylish-color);
   text-decoration: var(--my-stylish-color) underline;
}

3. Document your changes

Refer to the styling documentation for each Vaadin component to discover available selectors and variables.

Component styling tab in the Vaadin Docs

Conclusion

Vaadin's theming system provides extensive options for customizing your application's appearance, from global themes to granular modifications of individual components.

Feel free to play around with the theme settings on Vaadin Start as well as the Lumo Editor to gain experience with how it works. You will find the links below.

Take advantage of this flexibility to maintain a consistent and maintainable design for your application. Check out an example project on GitHub.

Have fun styling your Vaadin application!

Sources