前端 --- Flex布局
- Flex布局
-
- [flex-direction / justify-content](#flex-direction / justify-content)
- [align-items / align-content](#align-items / align-content)
- flex-wrap
- Example
-
- [Example 1](#Example 1)
- [Example 2](#Example 2)
- [Example 3](#Example 3)
- [Example 4](#Example 4)
- [Example 5](#Example 5)
- [Example 6](#Example 6)
- [Example 7](#Example 7)
- [Example 8](#Example 8)
Flex布局
- Flex 是 CSS 的一种「弹性盒子」布局模型,专门用于一维布局(横向或纵向)
- 通过在container上设置flex的property来控制子元素的布局 (也就是flex布局的设置只能影响子元素)
两种元素
javascript
// Flex 布局只有两种元素:
1. 容器 (Container) - 设置 display: flex 的元素
2. 项目 (Item) - 容器内的直接子元素
两个轴
javascript
主轴 (Main Axis) - 项目排列的方向
交叉轴 (Cross Axis) - 垂直于主轴的方向
默认:主轴=水平,交叉轴=垂直
flex-direction / justify-content
flex-direction 决定 flex 项目在容器中的「排列方向」 也就是主轴的方向, 选项包括:
row「横着排」从左到右row-reverse「横着排但反过来」从右到左column「竖着排」从上到下column-reverse「竖着排但反过来」从下到上
justify-content 控制 flex 项目在「主轴方向」上的对齐和分布方式, 选项包括:
flex-start「挤在开头」flex-end「挤在结尾」center「放中间」space-between「两头贴边,中间分家」space-around「人人有份,两边留空」space-evenly「所有间距都相等」
align-items / align-content
align-items - 控制 flex 项目在「交叉轴方向」上的对齐方式(单行内对齐),选项包括:
stretch 「拉伸填满」(默认)
flex-start「顶对齐/左对齐」center「居中对齐」(最常用!)flex-end「底对齐/右对齐」baseline「基线对齐」(文字对齐)
align-content - 控制多行 flex 项目在「交叉轴方向」上的分布方式(多行之间分布),必须配合 flex-wrap: wrap 使用,选项包括:
stretch 「行拉伸填满」(默认)
flex-start「所有行挤在开头」flex-end「所有行挤在结尾」center「所有行放中间」space-between「首行靠头,末行靠尾,中间分家」space-around「每行都有份,上下留空」space-evenly「所有行间距都相等」
flex-wrap
flex-wrap - 控制 flex 项目是否换行以及换行方向,选项包括:
nowrap「不换行」(默认)空间不够时压缩或溢出wrap「正常换行」空间不够时换到下一行/列wrap-reverse「反向换行」空间不够时反向换行
Example
Example 1

javascript
Box (最外层容器,块级布局 display: block)
│
├─ 样式特性:
│ ├─ backgroundColor: '#F4F7FC' (浅灰色背景)
│ ├─ minHeight: '100vh' (最小高度为视口高度)
│ └─ 布局行为:子元素按文档流垂直排列
│
├─ Header (头部导航组件,块级元素)
│ │
│ └─ 占据100%宽度,垂直排列在最顶部
│
└─ Box (主体内容区,Flex布局容器)
│
├─ 样式特性:
│ ├─ display: 'flex' (启用Flexbox)
│ ├─ justifyContent: 'center' (子元素水平居中)
│ └─ 默认方向:row (从左到右水平排列)
│
├─ Sidebar (左侧边栏,Flex子项1)
│ │
│ ├─ 宽度特性:固定或基于内容
│ ├─ 对齐特性:受父容器 justifyContent: 'center' 影响
│ └─ 内容:导航菜单、分类列表等
│
└─ Box (右侧内容区域,Flex子项2)
│
├─ 样式特性:
│ ├─ flexGrow: 1 (关键属性:占据剩余空间)
│ ├─ ml: { xs: 0, md: '280px' } (响应式左边距)
│ └─ p: 4 (内边距32px)
│
└─ Container (MUI容器组件)
│
├─ 样式特性:
│ ├─ maxWidth: 'lg' (约1280px)
│ └─ 自动居中:margin: 0 auto
│
└─ Grid (MUI网格系统容器)
│
├─ 样式特性:
│ ├─ display: 'flex' (实际上 Grid 使用 display: grid 或 flex)
│ ├─ flexWrap: 'wrap' (允许换行)
│ └─ spacing: 3 (子项间距24px)
│
├─ Grid item (网格项1)
│ │
│ ├─ 样式特性:
│ │ ├─ xs: 12 (在xs断点占12列,即100%宽度)
│ │ └─ 默认:flexBasis: 100% / maxWidth: 100%
│ │
│ └─ ArticleCard (文章卡片组件)
│ │
│ └─ 通常包含:标题、摘要、元信息等
│
└─ Grid item (网格项2)
│
├─ 样式特性:同上
│
└─ ArticleCard (文章卡片组件)
Example 2

javascript
[固定定位的AppBar]
├─ [Flex容器Toolbar] (justifyContent: 'space-between')
│ ├─ 左侧Logo (固定宽度)
│ ├─ 中间搜索框 (响应式宽度 + 响应式定位)
│ └─ 右侧操作区 (另一个Flex容器)
└─ [占位Toolbar] (保持页面内容不被遮挡)
Example 3

javascript
<Card> (块级容器)
├─ <CardContent> (块级容器,内边距p:3)
├─ 标题 (Typography - 块级)
├─ 摘要 (Typography - 块级,特殊截断布局)
└─ 元信息区域 (Box - Flex容器)
├─ 日期 (Box - Flex容器)
├─ 阅读量 (Box - Flex容器)
└─ 标签区域 (Box - Flex容器)
Example 4

javascript
Box (最外层容器,块级布局 display: block)
│
├─ 样式特性:
│ ├─ backgroundColor: '#F4F7FC' (浅灰色背景)
│ ├─ minHeight: '100vh' (最小高度为视口高度)
│ └─ 布局特性:子元素垂直排列(自然文档流)
│
├─ Header (头部导航组件)
│ │
│ └─ 通常包含:Logo、搜索框、用户操作
│
└─ Box (主体内容区,Flex布局容器)
│
├─ 样式特性:
│ ├─ display: 'flex' (启用Flex布局)
│ └─ 默认方向:row (水平排列)
│
├─ Sidebar (左侧边栏)
│ │
│ ├─ 位置特性:固定宽度(通常280px)
│ ├─ 内容可能包括:
│ │ ├─ 用户信息
│ │ ├─ 导航菜单
│ │ ├─ 文章分类
│ │ └─ 其他功能链接
│ │
│ └─ 布局特性:可能使用 position: fixed 或 position: sticky
│
└─ Box (右侧内容区域,Flex子项)
│
├─ 样式特性:
│ ├─ flexGrow: 1 (关键:占据所有剩余空间)
│ ├─ ml: '280px' (左边距,为侧边栏预留空间)
│ └─ p: 4 (内边距32px)
│
└─ Container (内容限制容器)
│
├─ 样式特性:
│ ├─ maxWidth: 'md' (约960px)
│ └─ position: 'relative' (为绝对定位子元素提供参考)
│
├─ Box (返回按钮容器,定位元素)
│ │
│ ├─ 小屏幕模式 (<1350px):
│ │ ├─ position: sticky
│ │ ├─ top: 80px (在Header下方固定)
│ │ ├─ zIndex: 10
│ │ └─ mb: 2 (底部间距16px)
│ │
│ └─ 大屏幕模式 (≥1350px):
│ ├─ position: absolute
│ ├─ top: 0
│ ├─ left: -140px (关键:移动到容器外部)
│ └─ height: '100%' (占满容器高度)
│
└─ Paper (文章内容卡片)
│
├─ 样式特性:
│ ├─ p: 4 (内边距32px)
│ ├─ borderRadius: 3 (圆角16px)
│ ├─ maxWidth: '900px' (最大宽度)
│ ├─ mx: 'auto' (水平居中)
│ └─ transform: { md: 'translateX(-60px)' } (中等屏幕左移)
│
├─ Typography (文章标题,块级元素)
│ │
│ ├─ variant: 'h3' (大标题)
│ ├─ fontWeight: 700 (粗体)
│ └─ 默认有 margin-bottom
│
├─ Box (文章元信息,Flex容器)
│ │
│ ├─ 样式特性:
│ │ ├─ display: 'flex' (水平排列)
│ │ ├─ alignItems: 'center' (垂直居中)
│ │ ├─ gap: 3 (子元素间距24px)
│ │ └─ flexWrap: 'wrap' (允许换行)
│ │
│ ├─ Box (日期信息,嵌套Flex容器)
│ │ │
│ │ ├─ 样式特性:
│ │ │ ├─ display: 'flex'
│ │ │ ├─ alignItems: 'center'
│ │ │ └─ gap: 0.5 (间距4px)
│ │ │
│ │ ├─ CalendarToday (图标组件)
│ │ └─ Typography (日期文本)
│ │
│ ├─ Box (阅读量信息,嵌套Flex容器)
│ │ │
│ │ ├─ 样式特性:同上
│ │ │
│ │ ├─ Visibility (图标组件)
│ │ └─ Typography (阅读量文本)
│ │
│ └─ Box (标签区域,嵌套Flex容器)
│ │
│ ├─ 样式特性:
│ │ ├─ display: 'flex'
│ │ ├─ gap: 1 (间距8px)
│ │ └─ flexWrap: 'wrap'
│ │
│ └─ Chip组件列表 (每个标签)
│
└─ Box (文章正文区域,块级元素)
│
├─ className: 'markdown-content' (Markdown样式)
└─ 包含:ReactMarkdown组件
Example 5

javascript
Box (最外层容器,块级布局 display: block)
│
├─ Header (头部导航组件 - 通常是固定定位)
│ │
│ ├─ 可能存在内部结构:
│ │ ├─ Logo区域
│ │ ├─ 搜索框
│ │ └─ 用户菜单
│ │
│ └─ 布局特性:position: fixed, top: 0, width: 100%, zIndex: 高值
│
├─ Container (内容容器,块级布局但有最大宽度限制)
│ │
│ ├─ 定位特性:position: relative (为子元素绝对定位提供参考)
│ ├─ 尺寸特性:maxWidth: 'lg' (约1280px)
│ ├─ 间距特性:py: 4 (上下内边距32px)
│ │
│ ├─ 返回按钮容器 Box (定位容器)
│ │ │
│ │ ├─ 小屏幕模式 (<1350px):
│ │ │ ├─ position: sticky (粘性定位)
│ │ │ ├─ top: 80px (距离顶部80px时固定)
│ │ │ ├─ zIndex: 10 (确保在内容上方)
│ │ │ ├─ mb: 2 (底部间距16px)
│ │ │ └─ pointerEvents: 'none' (允许内容穿透)
│ │ │
│ │ └─ 大屏幕模式 (≥1350px):
│ │ ├─ position: absolute (绝对定位)
│ │ ├─ top: 0 (对齐容器顶部)
│ │ ├─ left: -140px (移出容器左侧140px)
│ │ ├─ height: '100%' (占满容器高度)
│ │ └─ mb: 0 (取消底部间距)
│ │
│ └─ Paper (主要内容卡片,块级布局)
│ │
│ ├─ 内边距:p: 3 (24px)
│ ├─ 圆角:borderRadius: 3 (16px)
│ │
│ ├─ 标题区域 Typography (块级元素)
│ │ ├─ 字体:variant="h4"
│ │ ├─ 字重:fontWeight: 700
│ │ └─ 间距:gutterBottom (底部间距)
│ │
│ ├─ 标签页导航 Tabs (Flex容器)
│ │ │
│ │ ├─ 布局特性:display: flex (水平排列)
│ │ ├─ 间距:mb: 3 (底部间距24px)
│ │ │
│ │ ├─ Tab 1 (Articles标签)
│ │ │ └─ label: "Articles"
│ │ │
│ │ └─ Tab 2 (Categories标签)
│ │ └─ label: "Categories"
│ │
│ └─ 标签页内容区域 (条件渲染)
│ │
│ ├─ 状态1 (tab === 0):显示ArticleSection
│ │ │
│ │ └─ ArticleSection组件
│ │ ├─ 可能包含:文章列表、筛选器、操作按钮
│ │ └─ 布局:通常是Flex或Grid布局
│ │
│ └─ 状态2 (tab === 1):显示CategorySection
│ │
│ └─ CategorySection组件
│ ├─ 可能包含:分类列表、创建分类按钮
│ └─ 布局:通常是列表或卡片布局
│
└─ CategoryModal (模态对话框)
│
├─ 定位特性:position: fixed (固定定位)
├─ 层级特性:zIndex: 非常高 (覆盖所有内容)
├─ 位置特性:居中显示,有遮罩背景
└─ 内容:分类管理相关表单
Example 6

javascript
Box (块级容器,默认 display: block)
├─ 顶部操作栏 (Flex布局 - 水平两端对齐)
│ ├─ 左侧操作区 (Flex布局 - 水平排列)
│ │ ├─ 标题 Typography (内联块级)
│ │ └─ 搜索框 SearchBar (内联块级)
│ │
│ └─ 右侧操作区 (Flex布局 - 水平排列)
│ ├─ 筛选器1 FormControl (内联块级)
│ │ └─ Select + MenuItem (下拉组件)
│ ├─ 筛选器2 FormControl (内联块级)
│ │ └─ Select + MenuItem (下拉组件)
│ └─ 操作按钮 Button (内联块级)
│
├─ 表格区域 TableContainer (块级容器)
│ └─ Table (表格组件)
│ ├─ TableHead (表头区)
│ │ └─ TableRow (表头行)
│ │ ├─ TableCell[1] (列头)
│ │ ├─ TableCell[2] (列头)
│ │ ├─ TableCell[3] (列头)
│ │ ├─ TableCell[4] (列头)
│ │ ├─ TableCell[5] (列头)
│ │ └─ TableCell[6] (列头)
│ │
│ └─ TableBody (表体区)
│ ├─ TableRow (数据行1)
│ │ ├─ TableCell[1] (标题)
│ │ ├─ TableCell[2] (状态 - 包含Chip)
│ │ ├─ TableCell[3] (可见性 - 包含Chip)
│ │ ├─ TableCell[4] (阅读量)
│ │ ├─ TableCell[5] (创建时间)
│ │ └─ TableCell[6] (操作 - 包含两个IconButton)
│ │
│ ├─ TableRow (数据行2...)
│ │ └─ ...
│ │
│ └─ TableRow (空状态行)
│ └─ TableCell colSpan={6} (合并单元格)
│
└─ 分页控件 (Flex布局 - 水平居中)
├─ 上一页按钮 Button
├─ 分页信息区 (Flex布局 - 水平排列)
│ ├─ 当前页 Typography
│ ├─ 分隔符 (间距)
│ └─ 总条数 Typography
│
└─ 下一页按钮 Button
Example 7

javascript
Box (最外层容器,Flex布局 display: flex)
│
├─ 样式特性:
│ ├─ height: '100vh' (占满整个视口高度)
│ ├─ display: 'flex' (启用Flexbox)
│ ├─ flexDirection: 'column' (垂直方向排列子元素)
│ └─ backgroundColor: '#F4F7FC' (浅灰色背景)
│
├─ Paper (顶部操作栏,Flex子项1)
│ │
│ ├─ 样式特性:
│ │ ├─ elevation: 1 (轻微阴影)
│ │ ├─ p: 2 (内边距16px)
│ │ ├─ display: 'flex' (水平排列)
│ │ ├─ justifyContent: 'space-between' (两端对齐)
│ │ ├─ alignItems: 'center' (垂直居中)
│ │ └─ borderRadius: 0 (无圆角,贴合顶部)
│ │
│ ├─ Box (左侧区域,嵌套Flex容器)
│ │ │
│ │ ├─ 样式特性:
│ │ │ ├─ display: 'flex'
│ │ │ ├─ alignItems: 'center'
│ │ │ ├─ gap: 2 (元素间距16px)
│ │ │ ├─ flex: 1 (占据可用空间)
│ │ │ └─ mr: 3 (右边距24px)
│ │ │
│ │ ├─ Typography (页面标题)
│ │ │ ├─ variant: 'h6'
│ │ │ └─ fontWeight: 600
│ │ │
│ │ └─ TextField (文章标题输入框)
│ │ │
│ │ ├─ placeholder: 'Enter article title'
│ │ ├─ size: 'small'
│ │ └─ sx: { flex: 1 } (占据左侧剩余空间)
│ │
│ └─ Box (右侧区域,嵌套Flex容器)
│ │
│ ├─ 样式特性:
│ │ ├─ display: 'flex'
│ │ └─ gap: 2 (按钮间距16px)
│ │
│ ├─ Button (保存草稿按钮)
│ ├─ ExportMenu (导出菜单组件)
│ ├─ Button (导入按钮)
│ └─ Button (发布按钮,渐变背景)
│
└─ Box (编辑器区域,Flex子项2)
│
├─ 样式特性:
│ ├─ display: 'flex' (水平双栏布局)
│ ├─ flexGrow: 1 (占据所有剩余垂直空间)
│ └─ overflow: 'hidden' (防止内容溢出)
│
├─ Box (左侧编辑器列,Flex子项1)
│ │
│ ├─ 样式特性:
│ │ ├─ width: '50%' (固定50%宽度)
│ │ ├─ borderRight: '1px solid #e2e8f0' (分隔线)
│ │ ├─ display: 'flex'
│ │ └─ flexDirection: 'column' (内部垂直排列)
│ │
│ ├─ EditorToolbar (编辑器工具栏,固定高度)
│ │
│ ├─ Box (编辑器主体区域)
│ │ │
│ │ ├─ 样式特性:
│ │ │ ├─ flexGrow: 1 (占据工具栏和状态栏之间的空间)
│ │ │ ├─ overflow: 'hidden' (内容可滚动)
│ │ │ └─ height: '100%' (确保高度计算)
│ │ │
│ │ └─ CodeMirrorEditor (代码编辑器组件)
│ │
│ └─ Box (状态栏,固定高度)
│ │
│ ├─ 样式特性:
│ │ ├─ px: 3 (左右内边距24px)
│ │ ├─ py: 1 (上下内边距8px)
│ │ ├─ backgroundColor: '#f8fafc' (浅灰色背景)
│ │ ├─ borderTop: '1px solid #e2e8f0' (上边框)
│ │ ├─ display: 'flex'
│ │ ├─ justifyContent: 'flex-end' (内容右对齐)
│ │ └─ gap: 3 (元素间距24px)
│ │
│ └─ 三个Typography (字数、行号、列号统计)
│
└─ EditorPreview (右侧预览列,Flex子项2)
│
└─ 样式特性:width: '50%' (固定50%宽度)
Example 8

javascript
Box (最外层容器,块级布局 display: block)
│
├─ 样式特性:
│ ├─ backgroundColor: '#F4F7FC' (浅灰色背景)
│ ├─ minHeight: '100vh' (最小高度为视口高度)
│ └─ 布局行为:子元素按文档流垂直排列
│
├─ Header (头部导航组件)
│ │
│ └─ 通常:固定定位或占据顶部区域
│
└─ Container (内容容器,块级元素)
│
├─ 样式特性:
│ ├─ maxWidth: 'lg' (约1280px限制)
│ ├─ py: 4 (上下内边距32px)
│ └─ position: 'relative' (为绝对定位子元素提供参考)
│
├─ Box (返回按钮容器,定位元素)
│ │
│ ├─ 样式特性:
│ │ ├─ position: 'sticky' (默认粘性定位)
│ │ ├─ top: 80 (距离顶部80px时固定)
│ │ ├─ zIndex: 10 (确保在内容上方)
│ │ ├─ mb: 2 (底部间距16px)
│ │ └─ pointerEvents: 'none' (默认禁止交互)
│ │
│ ├─ 响应式特性:
│ │ └─ '@media (min-width: 1350px)': {
│ │ position: 'absolute',
│ │ top: 0,
│ │ left: -140,
│ │ height: '100%',
│ │ mb: 0
│ │ }
│ │
│ └─ Button (返回按钮)
│ │
│ ├─ 样式特性:
│ │ ├─ pointerEvents: 'auto' (覆盖父容器的none)
│ │ ├─ whiteSpace: 'nowrap' (防止文字换行)
│ │ └─ 响应式:大屏幕时额外偏移
│ │
│ └─ 内容:带箭头的"Back to Home"
│
└─ Paper (设置内容卡片,块级元素)
│
├─ 样式特性:
│ ├─ p: 3 (内边距24px)
│ ├─ borderRadius: 3 (圆角16px)
│ ├─ minHeight: '600px' (最小高度保障)
│ ├─ maxWidth: '900px' (最大宽度限制)
│ └─ mx: 'auto' (水平居中)
│
├─ Typography (页面标题,块级元素)
│ │
│ ├─ variant: 'h4'
│ ├─ fontWeight: 700
│ └─ gutterBottom (底部间距)
│
├─ Tabs (标签页导航,Flex容器)
│ │
│ ├─ 样式特性:
│ │ ├─ 默认:水平Flex布局
│ │ └─ mb: 4 (底部间距32px)
│ │
│ ├─ Tab (标签1 - Profile)
│ └─ Tab (标签2 - Security)
│
├─ 条件渲染区域1 (tab === 0 - 个人信息)
│ │
│ └─ Box (表单容器,块级元素)
│ │
│ ├─ 样式特性:
│ │ ├─ maxWidth: '900px' (最大宽度)
│ │ └─ mx: 'auto' (水平居中)
│ │
│ ├─ Typography (区块标题)
│ │ ├─ variant: 'h6'
│ │ ├─ gutterBottom
│ │ └─ sx: { mb: 3 } (底部间距24px)
│ │
│ ├─ TextField (用户名输入框)
│ │ │
│ │ ├─ 样式特性:
│ │ │ ├─ fullWidth (宽度100%)
│ │ │ ├─ disabled (禁用状态)
│ │ │ └─ sx: { mb: 3 } (底部间距24px)
│ │ │
│ │ ├─ label: "Username"
│ │ └─ helperText: "Username cannot be changed"
│ │
│ ├─ TextField (邮箱输入框,同上)
│ │
│ ├─ Divider (分隔线)
│ │ │
│ │ ├─ 样式特性:
│ │ │ └─ sx: { my: 4 } (上下外边距32px)
│ │ │
│ │ └─ 视觉作用:区分不同区块
│ │
│ ├─ Typography (另一个区块标题)
│ │
│ ├─ TextField (昵称输入框)
│ │ │
│ │ ├─ 样式特性:fullWidth, sx: { mb: 3 }
│ │ ├─ placeholder: 用户名作为占位符
│ │ └─ helperText: 显示用途说明
│ │
│ └─ Button (保存按钮)
│ │
│ ├─ 样式特性:
│ │ ├─ variant: 'contained'
│ │ ├─ startIcon: <Save />
│ │ └─ 渐变背景色
│ │
│ ├─ disabled状态:根据加载状态和值变化
│ └─ 动态文本:'Saving...' 或 'Save Changes'
│
├─ 条件渲染区域2 (tab === 1 - 安全设置)
│ │
│ └─ Box (表单容器,类似结构)
│ │
│ ├─ Typography (区块标题)
│ │
│ ├─ TextField (当前密码输入框)
│ │ ├─ type: 'password'
│ │ └─ sx: { mb: 3 }
│ │
│ ├─ TextField (新密码输入框)
│ │ ├─ type: 'password'
│ │ └─ sx: { mb: 3 }
│ │
│ ├─ TextField (确认密码输入框)
│ │ ├─ type: 'password'
│ │ └─ sx: { mb: 3 }
│ │
│ └─ Button (更新密码按钮)
│ ├─ disabled状态:根据表单填写情况
│ └─ 动态文本:'Updating...' 或 'Update Password'
│
└─ 无内容区域 (tab 其他值)
│
└─ 不渲染任何内容