主题
Elevation 设计规范
最后更新:2026-02-21 版本:v1.0 状态:✅ 强制执行
本文档定义 Reading Vocab Helper 项目的 Elevation(阴影层级)设计规范,包括标准值、各组件使用规范、暗色模式处理等。
📋 目录
Elevation 标准层级
核心原则:使用 Material 3 标准层级值,确保视觉层次一致
Material 3 标准层级
| 层级 | 数值 | 用途 | 视觉效果 |
|---|---|---|---|
| Level 0 | 0dp | 平面元素、内嵌内容 | 无阴影 |
| Level 1 | 1dp | 悬浮卡片、轻量提升 | 微弱阴影 |
| Level 2 | 3dp | 菜单、下拉框、AppBar | 轻度阴影 |
| Level 3 | 6dp | 底部弹窗、抽屉、FAB | 明显阴影 |
| Level 4 | 8dp | 对话框 | 较强阴影 |
| Level 5 | 12dp | 模态层、全屏覆盖 | 最强阴影 |
层级关系图
Level 5 (12dp) ─────────────────────────
全屏模态、侧边抽屉
Level 4 (8dp) ──────────────────────────
对话框、AlertDialog
Level 3 (6dp) ──────────────────────────
底部弹窗、FAB、抽屉
Level 2 (3dp) ──────────────────────────
菜单、PopupMenu、AppBar
Level 1 (1dp) ──────────────────────────
悬浮卡片、ListTile 悬浮
Level 0 (0dp) ──────────────────────────
平面内容、内嵌元素组件 Elevation 规范
按组件类型
| 组件 | 默认 Elevation | 悬浮/按下状态 | 说明 |
|---|---|---|---|
| Card | 0-1dp | 1-3dp | 默认 0,悬浮时 1 |
| FilledButton | 0dp | 1dp(悬浮) | 默认平面 |
| OutlinedButton | 0dp | 0dp | 始终平面 |
| FloatingActionButton | 6dp | 8dp(按下) | 始终悬浮 |
| AppBar | 0-3dp | - | 滚动时 3dp |
| BottomNavigationBar | 3dp | - | 固定 3dp |
| BottomSheet | 6dp | - | 固定 6dp |
| AlertDialog | 8dp | - | 固定 8dp |
| PopupMenu | 3dp | - | 固定 3dp |
| Drawer | 6dp | - | 固定 6dp |
| SnackBar | 6dp | - | 固定 6dp |
状态变化规则
交互状态对 Elevation 的影响:
默认状态 → 悬浮状态 → 按下状态
0dp +1dp +3dp暗色模式处理
核心原则:暗色模式使用 Surface Tint 替代阴影
Material 3 暗色模式策略
在暗色模式下,阴影不可见。Material 3 使用 Surface Tint(表面着色) 来表达层级:
| 层级 | Surface Tint 透明度 | 视觉效果 |
|---|---|---|
| Level 0 | 0% | 基础表面色 |
| Level 1 | 5% | 轻微提升 |
| Level 2 | 8% | 明显提升 |
| Level 3 | 11% | 较高提升 |
| Level 4 | 12% | 高提升 |
| Level 5 | 14% | 最高提升 |
代码实现
dart
// Flutter 3.x 自动处理 Surface Tint
// 确保使用 Material 3 主题
ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark, // 暗色模式
),
)
// Card 自动应用 Surface Tint
Card(
elevation: 3, // 暗色模式下自动使用 surfaceTintColor
child: content,
)
// 手动设置 Surface Tint
Card(
elevation: 3,
surfaceTintColor: Theme.of(context).colorScheme.surfaceTint,
child: content,
)
// 禁用 Surface Tint(如需纯色背景)
Card(
elevation: 0,
surfaceTintColor: Colors.transparent,
child: content,
)暗色模式设计建议
不要依赖阴影来区分层级
- 暗色模式下阴影几乎不可见
- 使用 Surface Tint 或边框来区分
使用 Material 3 组件
- 自动处理 Surface Tint
- 无需手动适配暗色模式
测试暗色模式
- 确保层级关系在暗色模式下仍然清晰
- 检查对话框、菜单等弹出组件
决策树:如何选择 Elevation
组件类型?
├─ 按钮
│ ├─ FilledButton → 0dp(默认),悬浮 1dp
│ ├─ OutlinedButton → 0dp(始终)
│ ├─ TextButton → 0dp(始终)
│ └─ FAB → 6dp(默认),按下 8dp
│
├─ 卡片/容器
│ ├─ Card(内嵌内容) → 0dp
│ ├─ Card(悬浮内容) → 1dp
│ └─ Card(可点击,重要) → 1-3dp
│
├─ 导航
│ ├─ AppBar(静止) → 0dp
│ ├─ AppBar(滚动) → 3dp
│ ├─ BottomNavigationBar → 3dp
│ └─ Drawer → 6dp
│
├─ 弹出/模态
│ ├─ PopupMenu → 3dp
│ ├─ BottomSheet → 6dp
│ ├─ AlertDialog → 8dp
│ └─ 全屏模态 → 12dp
│
└─ 反馈
└─ SnackBar → 6dp代码示例
Card 示例
dart
// Level 0:内嵌卡片(无阴影)
Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(
color: colorScheme.outline.withOpacity(0.12),
),
),
child: content,
)
// Level 1:悬浮卡片
Card(
elevation: 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: content,
)
// 可点击卡片(悬浮状态提升)
Card(
elevation: isHovered ? 3 : 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: content,
),
)对话框示例
dart
// Material 3 标准对话框(自动 8dp)
AlertDialog(
title: Text('标题'),
content: Text('内容'),
actions: [
TextButton(onPressed: () {}, child: Text('取消')),
FilledButton(onPressed: () {}, child: Text('确认')),
],
)
// 自定义 elevation
Dialog(
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(28),
),
child: content,
)FAB 示例
dart
// 标准 FAB(6dp)
FloatingActionButton(
onPressed: onPressed,
elevation: 6,
highlightElevation: 8, // 按下状态
child: Icon(Icons.add),
)
// 小型 FAB
FloatingActionButton.small(
onPressed: onPressed,
elevation: 6,
child: Icon(Icons.add),
)
// 扩展 FAB
FloatingActionButton.extended(
onPressed: onPressed,
elevation: 6,
icon: Icon(Icons.add),
label: Text('新建'),
)AppBar 示例
dart
// 滚动时显示阴影
SliverAppBar(
elevation: 0, // 默认无阴影
scrolledUnderElevation: 3, // 滚动时 3dp
title: Text('标题'),
)
// 普通 AppBar
AppBar(
elevation: 0, // Material 3 默认无阴影
scrolledUnderElevation: 3,
title: Text('标题'),
)BottomSheet 示例
dart
// 模态底部弹窗(6dp)
showModalBottomSheet(
context: context,
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
),
builder: (context) => content,
)
// 持久底部弹窗
BottomSheet(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
),
builder: (context) => content,
onClosing: () {},
)反模式总结
Elevation 值反模式
| ❌ 错误 | ✅ 正确 | 原因 |
|---|---|---|
elevation: 2 | elevation: 1 或 3 | 非标准值 |
elevation: 4 | elevation: 3 或 6 | 非标准值 |
elevation: 5 | elevation: 6 | 非标准值 |
elevation: 10 | elevation: 8 或 12 | 非标准值 |
层级关系反模式
| ❌ 错误 | ✅ 正确 | 原因 |
|---|---|---|
| Card elevation > Dialog | Card < Dialog | 对话框应在卡片之上 |
| AppBar elevation > BottomSheet | AppBar < BottomSheet | 底部弹窗覆盖 AppBar |
| FAB elevation < Card | FAB > Card | FAB 应悬浮在内容之上 |
暗色模式反模式
| ❌ 错误 | ✅ 正确 | 原因 |
|---|---|---|
| 依赖阴影区分层级 | 使用 Surface Tint | 暗色模式阴影不可见 |
| 手动设置暗色背景色 | 使用 colorScheme.surface | 保持一致性 |
| 禁用 Surface Tint 后无边框 | 添加边框区分 | 保持层级可识别 |
快速参考表
标准 Elevation 值
| 层级 | 值 | 组件 |
|---|---|---|
| 0 | 0dp | FilledButton, OutlinedButton, 内嵌 Card |
| 1 | 1dp | 悬浮 Card, FilledButton 悬浮 |
| 2 | 3dp | AppBar 滚动, PopupMenu, BottomNavigationBar |
| 3 | 6dp | FAB, BottomSheet, Drawer, SnackBar |
| 4 | 8dp | AlertDialog, Dialog |
| 5 | 12dp | 全屏模态 |
状态变化
| 组件 | 默认 | 悬浮 | 按下 |
|---|---|---|---|
| FilledButton | 0 | 1 | 0 |
| Card | 0-1 | +1 | +2 |
| FAB | 6 | 8 | 8 |
| IconButton | 0 | 0 | 0 |
参考资料:
维护者:Reading Vocab Helper Team 问题反馈:请在项目中提 Issue