第6章: Flexbox与Grid混合布局实战
🎯 本章重点
- 何时选择Flexbox vs Grid
- 混合布局的最佳实践
- 复杂界面布局实现
📖 内容概述
6.1 布局选择指南
6.1.1 选择Flexbox的场景
- 一维布局: 水平或垂直方向的排列
- 内容驱动布局: 项目大小由内容决定
- 等分布局: 需要项目均匀分布
- 对齐控制: 需要精细的对齐控制
- 导航菜单: 水平或垂直导航
- 卡片组件: 内容卡片排列
6.1.2 选择Grid的场景
- 二维布局: 同时控制行和列
- 固定网格: 需要精确的网格结构
- 复杂布局: 圣杯布局、杂志布局等
- 区域命名: 使用语义化的区域名称
- 响应式网格: 自适应列数和行高
- 重叠元素: 需要元素重叠效果
6.2 混合布局模式
6.2.1 Grid容器 + Flexbox项目
/* Grid定义整体结构 */
.page-layout {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 250px 1fr;
grid-template-rows: 80px 1fr 60px;
min-height: 100vh;
}
/* Flexbox处理内部布局 */
.header {
grid-area: header;
display: flex;
justify-content: space-between;
align-items: center;
}
.sidebar {
grid-area: sidebar;
display: flex;
flex-direction: column;
}
.main {
grid-area: main;
display: flex;
flex-direction: column;
}
.footer {
grid-area: footer;
display: flex;
justify-content: center;
align-items: center;
}
6.2.2 Flexbox容器 + Grid项目
/* Flexbox定义整体流式布局 */
.card-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
}
/* Grid处理单个项目的复杂布局 */
.card {
display: grid;
grid-template-areas:
"image image"
"title price"
"description description"
"button button";
grid-template-columns: 1fr auto;
grid-template-rows: auto auto 1fr auto;
gap: 10px;
width: 300px;
}
.card-image { grid-area: image; }
.card-title { grid-area: title; }
.card-price { grid-area: price; }
.card-description { grid-area: description; }
.card-button { grid-area: button; }
6.3 实战案例
6.3.1 电商产品列表
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
.product-card {
display: flex;
flex-direction: column;
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
}
.product-image {
height: 200px;
object-fit: cover;
}
.product-info {
display: flex;
flex-direction: column;
padding: 16px;
flex: 1;
}
.product-title {
font-size: 1.1rem;
margin-bottom: 8px;
}
.product-price {
font-weight: bold;
color: #e74c3c;
margin-bottom: 12px;
}
.product-actions {
display: flex;
gap: 8px;
margin-top: auto;
}
6.3.2 仪表板布局
.dashboard {
display: grid;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
grid-template-columns: 250px 1fr;
grid-template-rows: 60px 1fr 40px;
min-height: 100vh;
}
.sidebar {
grid-area: sidebar;
display: flex;
flex-direction: column;
background: #2c3e50;
color: white;
}
.sidebar-header {
padding: 20px;
border-bottom: 1px solid #34495e;
}
.sidebar-nav {
display: flex;
flex-direction: column;
padding: 10px 0;
flex: 1;
}
.sidebar-footer {
padding: 20px;
border-top: 1px solid #34495e;
}
.header {
grid-area: header;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
background: #ecf0f1;
}
.main {
grid-area: main;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
padding: 24px;
}
.widget {
display: flex;
flex-direction: column;
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.footer {
grid-area: footer;
display: flex;
align-items: center;
justify-content: center;
background: #ecf0f1;
}
6.3.3 博客文章布局
.blog-post {
display: grid;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
grid-template-columns: 300px 1fr;
grid-template-rows: auto 1fr auto;
gap: 30px;
max-width: 1200px;
margin: 0 auto;
}
.post-header {
grid-area: header;
display: flex;
flex-direction: column;
gap: 16px;
}
.post-title {
font-size: 2.5rem;
margin: 0;
}
.post-meta {
display: flex;
gap: 20px;
color: #666;
}
.post-sidebar {
grid-area: sidebar;
display: flex;
flex-direction: column;
gap: 20px;
}
.toc {
display: flex;
flex-direction: column;
gap: 8px;
}
.author-card {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.post-content {
grid-area: content;
display: flex;
flex-direction: column;
gap: 24px;
}
.content-section {
display: flex;
flex-direction: column;
gap: 16px;
}
.post-footer {
grid-area: footer;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 0;
border-top: 1px solid #e0e0e0;
}
6.4 响应式混合布局
移动端适配
/* 基础移动端布局 */
.dashboard {
display: flex;
flex-direction: column;
}
.sidebar {
order: 2;
display: none; /* 移动端隐藏侧边栏 */
}
.header {
order: 1;
}
.main {
order: 3;
display: flex;
flex-direction: column;
gap: 16px;
}
.footer {
order: 4;
}
/* 平板端适配 */
@media (min-width: 768px) {
.dashboard {
display: grid;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
grid-template-columns: 200px 1fr;
}
.sidebar {
display: flex;
}
.main {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
}
/* 桌面端适配 */
@media (min-width: 1024px) {
.dashboard {
grid-template-columns: 250px 1fr;
}
.main {
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
}
6.5 性能优化技巧
6.5.1 减少布局计算
/* 好的做法:使用稳定的布局结构 */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
/* 避免的做法:频繁改变布局结构 */
.container.dynamic {
/* 避免在JavaScript中频繁修改这些属性 */
grid-template-columns: var(--dynamic-columns);
gap: var(--dynamic-gap);
}
6.5.2 合理使用will-change
.animated-element {
will-change: transform, opacity;
/* 仅对需要动画的元素使用 */
}
6.5.3 避免过度嵌套
/* 好的做法:扁平化结构 */
.page {
display: grid;
grid-template-columns: 1fr 3fr;
}
/* 避免的做法:过度嵌套 */
.page {
display: flex;
}
.page > div {
display: grid;
}
.page > div > div {
display: flex;
}
6.6 浏览器兼容性处理
6.6.1 特性检测
@supports (display: grid) {
.container {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
@supports not (display: grid) {
.container {
display: flex;
flex-wrap: wrap;
}
.container > * {
flex: 1 0 300px;
margin: 10px;
}
}
6.6.2 渐进增强
/* 基础布局(支持所有浏览器) */
.container {
display: block;
}
.item {
float: left;
width: 50%;
margin: 10px 0;
}
/* 增强布局(支持Grid的浏览器) */
@supports (display: grid) {
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.item {
float: none;
width: auto;
margin: 0;
}
}
💡 最佳实践
- 语义化选择: 根据内容结构选择布局方式
- 性能优先: 避免不必要的布局计算
- 渐进增强: 确保基础功能在所有浏览器可用
- 响应式设计: 为不同设备优化布局
🎯 下一章预览
下一章将深入探讨容器查询(Container Queries),实现真正的组件级响应式设计。
最后更新: 2024年12月