responsive-layouts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuilding Responsive Layouts in Vaadin 25
在Vaadin 25中构建响应式布局
Use the Vaadin MCP tools (, ) to look up the latest documentation whenever uncertain about a specific API detail. Always set to and to .
search_vaadin_docsget_component_java_apivaadin_version"25"ui_language"java"当不确定特定API细节时,使用Vaadin MCP工具(、)查阅最新文档。请始终将设置为,设置为。
search_vaadin_docsget_component_java_apivaadin_version"25"ui_language"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:
- Reduce features on small screens — hide secondary filters, collapse panels. Suitable when mobile is an occasional access mode.
- Build a responsive UI — same features, different layout. Use CSS media/container queries and responsive components. The recommended approach for most apps.
- 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.
Vaadin中的响应式意味着让UI充分利用可用屏幕空间——不只是简单地挤压或拉伸元素。目标是为每个视口尺寸呈现适量的信息和交互方式。
按实现难度递增排序的三种策略:
- 在小屏幕上精简功能——隐藏次要筛选器、折叠面板。适合移动端为偶尔访问场景的情况。
- 构建响应式UI——功能相同,布局不同。使用CSS媒体/容器查询和响应式组件。这是大多数应用的推荐方案。
- 构建独立UI——移动端和桌面端体验完全独立。仅当交互模式存在本质差异时(例如移动端基于滑动操作 vs 桌面端基于数据网格),才值得投入此精力。
除非有充分理由,否则从策略2开始。
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
在编写自定义响应式逻辑前,优先使用这些组件——它们会自动处理适配:
- AppLayout——在小视口下,侧边抽屉会自动折叠为汉堡菜单
- Dashboard——网格布局会自动适配屏幕尺寸
- FormLayout——根据宽度调整列数和标签位置
- MenuBar——当菜单项无法容纳时,显示溢出菜单
- Tabs——当标签页溢出时,出现横向滚动按钮
- Context Menu——在移动端停靠到屏幕底部
- Dialog / Confirm Dialog——在窄视口下,按钮工具栏切换为垂直排列
- CRUD——在小视口下,编辑器切换为覆盖层
- Date Picker / Select——在移动端,覆盖层停靠到屏幕底部
CSS Media Queries
CSS媒体查询
The primary tool for viewport-based responsiveness. Define styles that activate at specific viewport widths.
css
/* 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
/* 在视图的CSS文件中 */
.filter-panel {
display: flex;
}
@media (max-width: 640px) {
.filter-panel {
display: none;
}
}从Java代码中应用CSS类名,让CSS处理响应式逻辑。这样可以将响应式行为保留在CSS中,而非尝试在服务端检测屏幕尺寸。
CSS Container Queries
CSS容器查询
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.
css
.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.
当响应式需要基于组件容器的宽度而非视口宽度时适用。适用于可调整大小的面板、在不同场景中复用的组件,以及仪表板小部件。
css
.sidepanel {
container-type: inline-size;
container-name: sidepanel;
}
.sidepanel .footer {
display: none;
}
@container sidepanel (min-width: 400px) {
.footer {
display: flex;
}
}容器查询让组件具备自包含性——它们会根据自身可用空间进行适配,而非假设特定的视口尺寸。
Utility Classes for Responsive Design (Lumo Only)
响应式设计工具类(仅适用于Lumo主题)
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):
java
@StyleSheet(Lumo.STYLESHEET)
@StyleSheet(Lumo.UTILITY_STYLESHEET)
@StyleSheet("styles.css")
public class Application implements AppShellConfigurator {
}Note: Loading Lumo Utility Classes through is no longer supported in Vaadin 25. Use imports instead.
theme.json@StyleSheetBreakpoints (mobile-first):
| Breakpoint | Min width | Java constant prefix |
|---|---|---|
| (default) | 0px | |
| Small | 640px | |
| Medium | 768px | |
| Large | 1024px | |
| XLarge | 1280px | |
| XXLarge | 1536px | |
Example — show a mobile toolbar only on small screens:
java
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:
java
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.
Vaadin的Lumo工具类提供了类似Tailwind CSS的移动端优先响应式系统。这是无需编写自定义CSS即可添加响应式行为的最快方式。
**注意:**这些工具类仅适用于Lumo主题。如果使用Aura主题,请改用CSS媒体查询或容器查询(参见上文章节)。
配置(Vaadin 25中必填):
java
@StyleSheet(Lumo.STYLESHEET)
@StyleSheet(Lumo.UTILITY_STYLESHEET)
@StyleSheet("styles.css")
public class Application implements AppShellConfigurator {
}注意:在Vaadin 25中,不再支持通过加载Lumo工具类,请改用导入。
theme.json@StyleSheet断点(移动端优先):
| 断点 | 最小宽度 | Java常量前缀 |
|---|---|---|
| 默认 | 0px | |
| 小屏 | 640px | |
| 中屏 | 768px | |
| 大屏 | 1024px | |
| 超大屏 | 1280px | |
| 极超大屏 | 1536px | |
示例——仅在小屏幕上显示移动端工具栏:
java
mobileToolbar.addClassNames(
LumoUtility.Display.FLEX, // 默认可见(移动端)
LumoUtility.Display.Breakpoint.Small.HIDDEN // 640px及以上隐藏
);示例——在断点处从垂直布局切换为水平布局:
java
container.addClassNames(
LumoUtility.Display.FLEX,
LumoUtility.FlexDirection.COLUMN, // 垂直堆叠(移动端)
LumoUtility.FlexDirection.Breakpoint.Medium.ROW // 768px及以上改为行布局
);工具类遵循移动端优先模式:将移动端样式设为默认,然后在更大的断点处覆盖样式。这符合CSS惯例,代码更简洁。
Responsive Patterns
响应式模式
Pattern: Collapsible filter panel (Lumo utility classes)
模式:可折叠筛选面板(Lumo工具类)
On desktop, show a filter sidebar. On mobile, hide it behind a toggle button.
java
// 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+
);在桌面端显示筛选侧边栏,在移动端将其隐藏在切换按钮后。
java
// 仅适用于Lumo主题——使用LumoUtility类
// 筛选面板——移动端隐藏,桌面端显示
VerticalLayout filterPanel = new VerticalLayout();
filterPanel.addClassNames(
LumoUtility.Display.HIDDEN, // 默认隐藏
LumoUtility.Display.Breakpoint.Medium.FLEX // 768px及以上显示
);
// 切换按钮——移动端显示,桌面端隐藏
Button filterToggle = new Button("筛选器");
filterToggle.addClassNames(
LumoUtility.Display.INLINE_FLEX, // 默认显示
LumoUtility.Display.Breakpoint.Medium.HIDDEN // 768px及以上隐藏
);Pattern: Responsive card grid
模式:响应式卡片网格
Use CSS Grid for a card layout that adapts its column count.
css
.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 */
}
}java
Div cardGrid = new Div();
cardGrid.addClassName("card-grid");
// Add Card components to cardGrid使用CSS Grid实现可自适应列数的卡片布局。
css
.card-grid {
display: grid;
gap: 1rem; /* 或使用主题令牌:Lumo主题下用var(--lumo-space-m) */
grid-template-columns: 1fr; /* 移动端1列 */
}
@media (min-width: 640px) {
.card-grid {
grid-template-columns: repeat(2, 1fr); /* 2列 */
}
}
@media (min-width: 1024px) {
.card-grid {
grid-template-columns: repeat(3, 1fr); /* 3列 */
}
}java
Div cardGrid = new Div();
cardGrid.addClassName("card-grid");
// 向cardGrid中添加Card组件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.
使用带抽屉布局的AppLayout。在小视口下,AppLayout会自动将抽屉转换为覆盖层。如需完全自定义,可结合媒体查询将导航栏移至底部。
Best Practices
最佳实践
- Use CSS for responsiveness, not server-side detection — avoid or
Page.retrieveExtendedClientDetails()for layout decisions. CSS media/container queries are more performant and don't require a server round-trip.UI.getCurrent().getPage().addBrowserWindowResizeListener() - Mobile first — define the mobile layout as the default and add complexity for larger screens. This matches how Lumo utility breakpoints work.
- Leverage built-in responsive components — AppLayout, FormLayout, Dashboard, MenuBar already handle adaptation. Don't rebuild what they provide.
- Prefer container queries for reusable components — if a component might appear in different-width containers, container queries make it self-adapting.
- 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."
- Test wrapping behavior — when using on HorizontalLayout or flex-wrap in CSS, verify that items wrap gracefully at intermediate sizes, not just at your target breakpoints.
setWrap(true)
- 使用CSS实现响应式,而非服务端检测——避免使用或
Page.retrieveExtendedClientDetails()来做布局决策。CSS媒体/容器查询性能更优,且无需服务端往返通信。UI.getCurrent().getPage().addBrowserWindowResizeListener() - 移动端优先——将移动端布局设为默认,为更大屏幕添加复杂样式。这与Lumo工具类的断点逻辑一致。
- 利用内置响应式组件——AppLayout、FormLayout、Dashboard、MenuBar已具备适配能力,无需重复造轮子。
- 复用组件优先使用容器查询——如果组件可能出现在不同宽度的容器中,容器查询可使其具备自适配能力。
- 设计流式尺寸——不要针对特定设备分辨率。用户会调整浏览器大小、使用分屏和缩放功能。请在多种宽度下测试,而非仅测试“手机”和“桌面”尺寸。
- 测试换行行为——在HorizontalLayout上使用或在CSS中使用flex-wrap时,请验证元素在中间尺寸下能否优雅换行,而非仅在目标断点处。
setWrap(true)
Detailed Reference
详细参考
For the complete list of Lumo utility class breakpoints and responsive constants, see .
references/responsive-patterns.md如需查看Lumo工具类断点和响应式常量的完整列表,请参阅。
references/responsive-patterns.md