Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Styling: Lumo and CSS

Vaadin components already look neat — that is the work of Lumo, the standard Vaadin theme. You can change the look on three levels: ready-made component variants from Java, Lumo utility CSS classes and your own CSS file. Start with the first one — it needs no CSS at all.

Loading styles

All stylesheets are loaded with @StyleSheet annotations on the main class:

// src/main/java/com/example/blog/Application.java
package com.example.blog;
 
import com.vaadin.flow.component.dependency.StyleSheet;
import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.component.page.ColorScheme;
import com.vaadin.flow.theme.lumo.Lumo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
@StyleSheet(Lumo.STYLESHEET)
@StyleSheet(Lumo.UTILITY_STYLESHEET)
@StyleSheet("styles.css")
@ColorScheme(ColorScheme.Value.LIGHT_DARK)
public class Application implements AppShellConfigurator {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
AnnotationWhat it loads
@StyleSheet(Lumo.STYLESHEET)The Lumo theme
@StyleSheet(Lumo.UTILITY_STYLESHEET)Lumo utility classes
@StyleSheet("styles.css")Your file src/main/resources/META-INF/resources/styles.css
@ColorScheme(LIGHT_DARK)Light or dark theme, following the system settings

Turn on dark mode in your system and reload the page: the background turns dark and the text light.

Component variants

Variants are ready-made styles you turn on from Java:

// src/main/java/com/example/blog/views/PostListView.java (part of the constructor)
add.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
grid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES);

The "New post" button is blue, and grid rows alternate in color. Similar variants exist for fields (TextFieldVariant.LUMO_SMALL), notifications (NotificationVariant.LUMO_ERROR) and other components.

Utility classes

LumoUtility is a set of constants with CSS classes for spacing, font sizes and colors:

// src/main/java/com/example/blog/views/MainLayout.java (part of the constructor)
H1 title = new H1("Blog admin");
title.addClassNames(LumoUtility.FontSize.LARGE, LumoUtility.Margin.NONE, LumoUtility.Flex.GROW);

The header title gets smaller, loses its margins and stretches, pushing the next header items to the right. Import: com.vaadin.flow.theme.lumo.LumoUtility.

Your own CSS

Give a component a class with addClassName and describe it in styles.css:

/* src/main/resources/META-INF/resources/styles.css */
.post-list {
  max-width: 960px;
  margin: 0 auto;
}
 
vaadin-grid::part(post-title) {
  font-weight: 600;
}
 
vaadin-grid::part(draft) {
  color: var(--lumo-error-text-color);
}

The list view with addClassName("post-list") is at most 960 pixels wide and centered. The two other rules style grid cells — Java gives the cells their names:

// src/main/java/com/example/blog/views/PostListView.java (part of the constructor)
grid.addColumn(Post::getTitle).setHeader("Title").setSortProperty("title")
        .setPartNameGenerator(post -> "post-title");
grid.addColumn(post -> post.isPublished() ? "Published" : "Draft").setHeader("Status")
        .setPartNameGenerator(post -> post.isPublished() ? null : "draft");

Post titles in the grid are bold, and the "Draft" status is red.

Common mistake

The stylesheet is in the wrong place, for example src/main/resources/styles.css. There is no error at startup, but the styles do not apply, and the browser console (F12) shows:

GET http://localhost:8080/styles.css 404 (Not Found)

The browser gets only files from src/main/resources/META-INF/resources/ — the path in @StyleSheet is relative to that folder. Older Vaadin 24 tutorials use another way, the @Theme annotation and the src/main/frontend/themes/ folder. Vaadin 25 recommends @StyleSheet.

Also remember that the inner parts of components are hidden in the shadow DOM: an ordinary selector does not reach them, so use ::part(...) as in the grid example.

Thanks for reading!

Donate to the site — we work hard for you.