Comprehensive Java web application development framework that enables server-side Java development with modern web UI components and automatic client-server communication.
Vaadin provides a comprehensive theming system with built-in themes, CSS custom properties, and component variants. The theming system supports both design systems (Lumo, Material) and custom styling approaches.
// Theme configuration annotations
import com.vaadin.flow.theme.Theme;
import com.vaadin.flow.theme.AbstractTheme;
// Lumo theme
import com.vaadin.flow.theme.lumo.Lumo;
import com.vaadin.flow.theme.lumo.LumoUtility;
// Material theme
import com.vaadin.flow.theme.material.Material;
// Component theming interfaces
import com.vaadin.flow.component.HasTheme;
import com.vaadin.flow.component.shared.ThemeVariant;
// Component theme variants
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.textfield.TextFieldVariant;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.dialog.DialogVariant;
import com.vaadin.flow.component.notification.NotificationVariant;
// Styling interfaces
import com.vaadin.flow.component.HasStyle;
import com.vaadin.flow.dom.Style;
import com.vaadin.flow.dom.ThemeList;
// CSS value enums
import com.vaadin.flow.dom.Style.Display;
import com.vaadin.flow.dom.Style.Position;
// Icon system
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
// Theme management
import com.vaadin.flow.component.UI;
import com.vaadin.flow.dom.Element;
// JavaScript modules for themes
import com.vaadin.flow.component.dependency.JsModule;
// Standard Java types
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;Modern design system with light and dark variants, serving as Vaadin's default theme.
// Lumo theme is automatically included with Vaadin Platform
// No explicit import needed - automatically applied to all components
// Access Lumo CSS custom properties programmatically
public class LumoUtility {
// Color properties
public static final String PRIMARY_COLOR = "--lumo-primary-color";
public static final String ERROR_COLOR = "--lumo-error-color";
public static final String SUCCESS_COLOR = "--lumo-success-color";
// Spacing properties
public static final String SPACE_XS = "--lumo-space-xs";
public static final String SPACE_S = "--lumo-space-s";
public static final String SPACE_M = "--lumo-space-m";
public static final String SPACE_L = "--lumo-space-l";
public static final String SPACE_XL = "--lumo-space-xl";
// Typography properties
public static final String FONT_FAMILY = "--lumo-font-family";
public static final String FONT_SIZE_S = "--lumo-font-size-s";
public static final String FONT_SIZE_M = "--lumo-font-size-m";
public static final String FONT_SIZE_L = "--lumo-font-size-l";
}Material Design implementation providing Material Design 3 styling.
// To use Material theme, add dependency and import
// Dependency: com.vaadin:vaadin-material-theme
@Theme("material")
public class MaterialApp extends Component {
// Application using Material theme
}
// Material theme CSS custom properties
public class MaterialUtility {
public static final String PRIMARY_COLOR = "--material-primary-color";
public static final String SURFACE_COLOR = "--material-surface-color";
public static final String ON_SURFACE_COLOR = "--material-on-surface-color";
}Configure application theme and variant.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Theme {
String value() default "";
String variant() default "";
Class<? extends AbstractTheme> themeClass() default AbstractTheme.class;
}Global theme variants for dark mode and component density.
// Apply theme variants to the application
@Theme(variant = Lumo.DARK)
public class DarkModeApp extends Component {
}
@Theme(variant = Lumo.COMPACT)
public class CompactApp extends Component {
}
// Lumo theme constants
public final class Lumo {
public static final String DARK = "dark";
public static final String LIGHT = "light";
public static final String COMPACT = "compact";
}Interface for components that support theme variants.
public interface HasTheme {
void addThemeVariants(ThemeVariant... variants);
void removeThemeVariants(ThemeVariant... variants);
void setThemeName(String themeName);
String getThemeName();
void setThemeName(String themeName, boolean set);
boolean hasThemeName(String themeName);
void addThemeName(String themeName);
void removeThemeName(String themeName);
Set<String> getThemeNames();
}Theme variants for individual components.
// Button variants
public enum ButtonVariant implements ThemeVariant {
LUMO_PRIMARY, // Primary button styling
LUMO_SECONDARY, // Secondary button styling
LUMO_TERTIARY, // Tertiary button styling
LUMO_TERTIARY_INLINE, // Inline tertiary styling
LUMO_SUCCESS, // Success color variant
LUMO_ERROR, // Error color variant
LUMO_CONTRAST, // High contrast variant
LUMO_ICON, // Icon-only button
LUMO_SMALL, // Small size variant
LUMO_LARGE // Large size variant
}
// TextField variants
public enum TextFieldVariant implements ThemeVariant {
LUMO_SMALL, // Small size variant
LUMO_ALIGN_CENTER, // Center-aligned text
LUMO_ALIGN_RIGHT // Right-aligned text
}
// Grid variants
public enum GridVariant implements ThemeVariant {
LUMO_NO_BORDER, // Remove outer border
LUMO_NO_ROW_BORDERS, // Remove row borders
LUMO_ROW_STRIPES, // Alternating row colors
LUMO_COLUMN_BORDERS, // Add column borders
LUMO_COMPACT, // Compact row height
LUMO_WRAP_CELL_CONTENT // Allow cell content wrapping
}
// Dialog variants
public enum DialogVariant implements ThemeVariant {
LUMO_NO_PADDING // Remove default padding
}
// Notification variants
public enum NotificationVariant implements ThemeVariant {
LUMO_PRIMARY, // Primary color
LUMO_CONTRAST, // High contrast
LUMO_SUCCESS, // Success color
LUMO_ERROR // Error color
}Programmatically set CSS custom properties for theming.
// Set CSS custom properties on components
public void configureCustomProperties(Component component) {
component.getStyle().set("--custom-color", "#FF5722");
component.getStyle().set("--custom-spacing", "16px");
component.getStyle().set("--custom-border-radius", "8px");
}
// Set global CSS custom properties
public void configureGlobalProperties() {
UI.getCurrent().getElement().getStyle().set("--lumo-primary-color", "#1976D2");
UI.getCurrent().getElement().getStyle().set("--lumo-font-family", "Roboto, sans-serif");
}Complete set of Lumo theme custom properties.
// Color properties
public static final String LUMO_PRIMARY_COLOR = "--lumo-primary-color";
public static final String LUMO_PRIMARY_COLOR_50PCT = "--lumo-primary-color-50pct";
public static final String LUMO_PRIMARY_COLOR_10PCT = "--lumo-primary-color-10pct";
public static final String LUMO_ERROR_COLOR = "--lumo-error-color";
public static final String LUMO_ERROR_COLOR_50PCT = "--lumo-error-color-50pct";
public static final String LUMO_ERROR_COLOR_10PCT = "--lumo-error-color-10pct";
public static final String LUMO_SUCCESS_COLOR = "--lumo-success-color";
public static final String LUMO_SUCCESS_COLOR_50PCT = "--lumo-success-color-50pct";
public static final String LUMO_SUCCESS_COLOR_10PCT = "--lumo-success-color-10pct";
// Typography properties
public static final String LUMO_FONT_FAMILY = "--lumo-font-family";
public static final String LUMO_FONT_SIZE_XXS = "--lumo-font-size-xxs";
public static final String LUMO_FONT_SIZE_XS = "--lumo-font-size-xs";
public static final String LUMO_FONT_SIZE_S = "--lumo-font-size-s";
public static final String LUMO_FONT_SIZE_M = "--lumo-font-size-m";
public static final String LUMO_FONT_SIZE_L = "--lumo-font-size-l";
public static final String LUMO_FONT_SIZE_XL = "--lumo-font-size-xl";
public static final String LUMO_FONT_SIZE_XXL = "--lumo-font-size-xxl";
public static final String LUMO_FONT_SIZE_XXXL = "--lumo-font-size-xxxl";
public static final String LUMO_LINE_HEIGHT_XS = "--lumo-line-height-xs";
public static final String LUMO_LINE_HEIGHT_S = "--lumo-line-height-s";
public static final String LUMO_LINE_HEIGHT_M = "--lumo-line-height-m";
// Spacing properties
public static final String LUMO_SPACE_XS = "--lumo-space-xs";
public static final String LUMO_SPACE_S = "--lumo-space-s";
public static final String LUMO_SPACE_M = "--lumo-space-m";
public static final String LUMO_SPACE_L = "--lumo-space-l";
public static final String LUMO_SPACE_XL = "--lumo-space-xl";
// Sizing properties
public static final String LUMO_SIZE_XS = "--lumo-size-xs";
public static final String LUMO_SIZE_S = "--lumo-size-s";
public static final String LUMO_SIZE_M = "--lumo-size-m";
public static final String LUMO_SIZE_L = "--lumo-size-l";
public static final String LUMO_SIZE_XL = "--lumo-size-xl";
// Border radius properties
public static final String LUMO_BORDER_RADIUS_S = "--lumo-border-radius-s";
public static final String LUMO_BORDER_RADIUS_M = "--lumo-border-radius-m";
public static final String LUMO_BORDER_RADIUS_L = "--lumo-border-radius-l";
// Box shadow properties
public static final String LUMO_BOX_SHADOW_XS = "--lumo-box-shadow-xs";
public static final String LUMO_BOX_SHADOW_S = "--lumo-box-shadow-s";
public static final String LUMO_BOX_SHADOW_M = "--lumo-box-shadow-m";
public static final String LUMO_BOX_SHADOW_L = "--lumo-box-shadow-l";
public static final String LUMO_BOX_SHADOW_XL = "--lumo-box-shadow-xl";Interface for components that support direct CSS styling.
public interface HasStyle {
Style getStyle();
void setClassName(String className);
String getClassName();
void setClassName(String className, boolean set);
void addClassName(String className);
void removeClassName(String className);
void addClassNames(String... classNames);
void removeClassNames(String... classNames);
boolean hasClassName(String className);
Set<String> getClassNames();
}Object for manipulating CSS styles programmatically.
public class Style {
// CSS property manipulation
public Style set(String property, String value);
public Style remove(String property);
public Optional<String> get(String property);
public boolean has(String property);
// CSS class manipulation
public Style setDisplay(Display display);
public Style setPosition(Position position);
public Style setWidth(String width);
public Style setHeight(String height);
public Style setMargin(String margin);
public Style setPadding(String padding);
public Style setColor(String color);
public Style setBackground(String background);
public Style setBorder(String border);
public Style setFontSize(String fontSize);
public Style setFontWeight(String fontWeight);
public Style setTextAlign(String textAlign);
}
// CSS value enums
public enum Display {
BLOCK, INLINE, INLINE_BLOCK, FLEX, GRID, NONE
}
public enum Position {
STATIC, RELATIVE, ABSOLUTE, FIXED, STICKY
}Base class for creating custom themes.
public abstract class AbstractTheme implements Theme {
public abstract String getBaseUrl();
public abstract String getThemeUrl();
public List<String> getHeaderInlineContents() {
return Collections.emptyList();
}
public Map<String, String> getHtmlAttributes(String variant) {
return Collections.emptyMap();
}
}Creating and registering custom themes.
@JsModule("./themes/custom-theme/custom-theme.js")
@Theme("custom")
public class CustomTheme extends AbstractTheme {
@Override
public String getBaseUrl() {
return "/themes/custom-theme/";
}
@Override
public String getThemeUrl() {
return "custom-theme.css";
}
@Override
public Map<String, String> getHtmlAttributes(String variant) {
Map<String, String> attributes = new HashMap<>();
attributes.put("theme", "custom " + variant);
return attributes;
}
}Programmatically manage theme variants including dark mode.
public class ThemeManager {
public void enableDarkMode() {
UI.getCurrent().getElement().getThemeList().add(Lumo.DARK);
}
public void disableDarkMode() {
UI.getCurrent().getElement().getThemeList().remove(Lumo.DARK);
}
public void toggleDarkMode() {
ThemeList themeList = UI.getCurrent().getElement().getThemeList();
if (themeList.contains(Lumo.DARK)) {
themeList.remove(Lumo.DARK);
} else {
themeList.add(Lumo.DARK);
}
}
public boolean isDarkMode() {
return UI.getCurrent().getElement().getThemeList().contains(Lumo.DARK);
}
}Interface for managing theme variants on elements.
public interface ThemeList {
void add(String theme);
boolean remove(String theme);
boolean contains(String theme);
void clear();
void set(String theme, boolean set);
void toggle(String theme);
Stream<String> stream();
int size();
}Built-in icon system with 600+ icons.
public enum VaadinIcon {
// Navigation icons
ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ARROW_DOWN,
CHEVRON_LEFT, CHEVRON_RIGHT, CHEVRON_UP, CHEVRON_DOWN,
// Action icons
PLUS, MINUS, CLOSE, CHECK, EDIT, DELETE, SEARCH,
// File icons
FILE, FOLDER, DOWNLOAD, UPLOAD, PRINT, COPY,
// Communication icons
PHONE, ENVELOPE, CHAT, COMMENT, BELL,
// User icons
USER, USERS, USER_CHECK, USER_STAR, GROUP,
// Settings icons
COG, TOOLS, WRENCH, SLIDERS, FILTER,
// Status icons
INFO_CIRCLE, WARNING, ERROR, SUCCESS, QUESTION_CIRCLE,
// Media icons
PLAY, PAUSE, STOP, FAST_FORWARD, BACKWARD,
// Layout icons
GRID, LIST, COLUMNS, VIEWPORT, EXPAND, CONTRACT;
public Icon create();
public String name();
}
public class Icon extends Component implements HasSize, HasStyle {
public Icon(VaadinIcon icon);
public Icon(String collection, String icon);
public void setIcon(VaadinIcon icon);
public void setIcon(String collection, String icon);
public void setSize(String size);
public void setColor(String color);
}// Apply theme variants to components
Button primaryButton = new Button("Primary Action");
primaryButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_LARGE);
TextField smallField = new TextField("Small Field");
smallField.addThemeVariants(TextFieldVariant.LUMO_SMALL);
Grid<Person> grid = new Grid<>(Person.class);
grid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES, GridVariant.LUMO_COMPACT);// Direct CSS styling
Component component = new Div();
component.getStyle()
.set("background-color", "var(--lumo-primary-color)")
.set("padding", "var(--lumo-space-m)")
.set("border-radius", "var(--lumo-border-radius-m)");
// CSS class-based styling
component.addClassName("custom-component");public class ThemeSwitcher extends Component {
private Button toggleButton = new Button("Toggle Dark Mode");
public ThemeSwitcher() {
toggleButton.addClickListener(e -> {
ThemeList themeList = UI.getCurrent().getElement().getThemeList();
boolean isDark = themeList.contains(Lumo.DARK);
if (isDark) {
themeList.remove(Lumo.DARK);
toggleButton.setText("Enable Dark Mode");
} else {
themeList.add(Lumo.DARK);
toggleButton.setText("Disable Dark Mode");
}
});
}
}// Define application-wide custom properties
public void configureCustomTheme() {
Element body = UI.getCurrent().getElement();
// Primary brand color
body.getStyle().set("--app-primary-color", "#2563EB");
body.getStyle().set("--app-primary-color-hover", "#1D4ED8");
// Custom spacing scale
body.getStyle().set("--app-space-xs", "4px");
body.getStyle().set("--app-space-s", "8px");
body.getStyle().set("--app-space-m", "16px");
body.getStyle().set("--app-space-l", "24px");
body.getStyle().set("--app-space-xl", "32px");
// Custom component styling
body.getStyle().set("--app-card-shadow", "0 4px 6px -1px rgba(0, 0, 0, 0.1)");
}The theming system provides comprehensive control over application appearance while maintaining consistency and accessibility across all components.
Install with Tessl CLI
npx tessl i tessl/maven-com-vaadin--vaadin