CtrlK
BlogDocsLog inGet started
Tessl Logo

responsive-layouts

Guide Claude on building responsive Vaadin 25 layouts that adapt to different screen sizes. This skill should be used when the user asks to "make a layout responsive", "support mobile", "adapt to screen size", "use breakpoints", "use media queries", "use container queries", "responsive design", "mobile first", or needs help making a Vaadin Flow view work well on both desktop and mobile devices.

68

Quality

83%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

SKILL.md
Quality
Evals
Security

Building Responsive Layouts in Vaadin 25

Use the Vaadin MCP tools (search_vaadin_docs, get_component_java_api) to look up the latest documentation whenever uncertain about a specific API detail. Always set vaadin_version to "25" and ui_language to "java".

Design Philosophy

Responsiveness in Vaadin means adapting the UI to best use available screen space — not just squeezing or stretching elements. The goal is to present the right amount of information and interaction for each viewport size.

Three strategies, in order of increasing effort:

  1. Reduce features on small screens — hide secondary filters, collapse panels. Suitable when mobile is an occasional access mode.
  2. Build a responsive UI — same features, different layout. Use CSS media/container queries and responsive components. The recommended approach for most apps.
  3. Build separate UIs — independent mobile and desktop experiences. Only worth the effort when interaction patterns differ fundamentally (e.g., swipe-based mobile vs. data-grid desktop).

Start with strategy 2 unless you have a strong reason not to.

Built-in Responsive Components

Leverage these before writing custom responsive logic — they handle adaptation automatically:

  • AppLayout — drawer auto-collapses to hamburger menu on small viewports
  • Dashboard — grid layout automatically adjusts to screen size
  • FormLayout — adjusts column count and label positions based on width
  • MenuBar — shows overflow menu when items don't fit
  • Tabs — horizontal scroll buttons appear when tabs overflow
  • Context Menu — docks to bottom of screen on mobile
  • Dialog / Confirm Dialog — button toolbar switches to vertical on narrow viewports
  • CRUD — editor switches to overlay on small viewports
  • Date Picker / Select — overlay docks to bottom on mobile

CSS Media Queries

The primary tool for viewport-based responsiveness. Define styles that activate at specific viewport widths.

/* In your view's CSS file */
.filter-panel {
    display: flex;
}

@media (max-width: 640px) {
    .filter-panel {
        display: none;
    }
}

Apply CSS class names from Java and let the CSS handle the responsive logic. This keeps responsive behavior in CSS where it belongs, rather than trying to detect screen sizes server-side.

CSS Container Queries

When responsiveness should be based on a component's container width rather than the viewport. Useful for resizable panels, reusable components that appear in different contexts, and dashboard widgets.

.sidepanel {
    container-type: inline-size;
    container-name: sidepanel;
}

.sidepanel .footer {
    display: none;
}

@container sidepanel (min-width: 400px) {
    .footer {
        display: flex;
    }
}

Container queries make components self-contained — they adapt to their own available space rather than assuming a specific viewport size.

Utility Classes for Responsive Design (Lumo Only)

Vaadin's Lumo utility classes provide a mobile-first responsive system similar to Tailwind CSS. They are the fastest way to add responsive behavior without writing custom CSS.

Note: These utility classes only work with the Lumo theme. If using Aura, use CSS media queries or container queries instead (see sections above).

Setup (required in Vaadin 25):

@StyleSheet(Lumo.STYLESHEET)
@StyleSheet(Lumo.UTILITY_STYLESHEET)
@StyleSheet("styles.css")
public class Application implements AppShellConfigurator {
}

Note: Loading Lumo Utility Classes through theme.json is no longer supported in Vaadin 25. Use @StyleSheet imports instead.

Breakpoints (mobile-first):

BreakpointMin widthJava constant prefix
(default)0pxLumoUtility.Display.FLEX etc.
Small640pxDisplay.Breakpoint.Small.*
Medium768pxDisplay.Breakpoint.Medium.*
Large1024pxDisplay.Breakpoint.Large.*
XLarge1280pxDisplay.Breakpoint.XLarge.*
XXLarge1536pxDisplay.Breakpoint.XXLarge.*

Example — show a mobile toolbar only on small screens:

mobileToolbar.addClassNames(
    LumoUtility.Display.FLEX,               // visible by default (mobile)
    LumoUtility.Display.Breakpoint.Small.HIDDEN  // hidden at 640px+
);

Example — switch from vertical to horizontal layout at a breakpoint:

container.addClassNames(
    LumoUtility.Display.FLEX,
    LumoUtility.FlexDirection.COLUMN,                          // stack vertically (mobile)
    LumoUtility.FlexDirection.Breakpoint.Medium.ROW            // row at 768px+
);

The utility classes follow a mobile-first pattern: define the mobile style as the default, then override at larger breakpoints. This matches the CSS convention and produces cleaner code.

Responsive Patterns

Pattern: Collapsible filter panel (Lumo utility classes)

On desktop, show a filter sidebar. On mobile, hide it behind a toggle button.

// Lumo theme only — uses LumoUtility classes
// Filter panel — hidden on mobile, shown on desktop
VerticalLayout filterPanel = new VerticalLayout();
filterPanel.addClassNames(
    LumoUtility.Display.HIDDEN,                           // hidden by default
    LumoUtility.Display.Breakpoint.Medium.FLEX             // shown at 768px+
);

// Toggle button — shown on mobile, hidden on desktop
Button filterToggle = new Button("Filters");
filterToggle.addClassNames(
    LumoUtility.Display.INLINE_FLEX,                       // shown by default
    LumoUtility.Display.Breakpoint.Medium.HIDDEN           // hidden at 768px+
);

Pattern: Responsive card grid

Use CSS Grid for a card layout that adapts its column count.

.card-grid {
    display: grid;
    gap: 1rem;  /* or use theme token: var(--lumo-space-m) for Lumo */
    grid-template-columns: 1fr;  /* 1 column on mobile */
}

@media (min-width: 640px) {
    .card-grid {
        grid-template-columns: repeat(2, 1fr);  /* 2 columns */
    }
}

@media (min-width: 1024px) {
    .card-grid {
        grid-template-columns: repeat(3, 1fr);  /* 3 columns */
    }
}
Div cardGrid = new Div();
cardGrid.addClassName("card-grid");
// Add Card components to cardGrid

Pattern: Desktop sidebar → mobile bottom sheet

Use AppLayout with drawer placement. On small viewports, AppLayout automatically converts the drawer to an overlay. For full customization, combine with media queries to move navigation to a bottom bar.

Best Practices

  1. Use CSS for responsiveness, not server-side detection — avoid Page.retrieveExtendedClientDetails() or UI.getCurrent().getPage().addBrowserWindowResizeListener() for layout decisions. CSS media/container queries are more performant and don't require a server round-trip.
  2. Mobile first — define the mobile layout as the default and add complexity for larger screens. This matches how Lumo utility breakpoints work.
  3. Leverage built-in responsive components — AppLayout, FormLayout, Dashboard, MenuBar already handle adaptation. Don't rebuild what they provide.
  4. Prefer container queries for reusable components — if a component might appear in different-width containers, container queries make it self-adapting.
  5. Design for fluid sizes — don't target specific device resolutions. Users resize browsers, use split screens, and zoom. Test at many widths, not just "phone" and "desktop."
  6. Test wrapping behavior — when using setWrap(true) on HorizontalLayout or flex-wrap in CSS, verify that items wrap gracefully at intermediate sizes, not just at your target breakpoints.

Detailed Reference

For the complete list of Lumo utility class breakpoints and responsive constants, see references/responsive-patterns.md.

Repository
vaadin/claude-plugin
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.