Flexbox与Grid混合布局

44 阅读5分钟

第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;
  }
}

💡 最佳实践

  1. 语义化选择: 根据内容结构选择布局方式
  2. 性能优先: 避免不必要的布局计算
  3. 渐进增强: 确保基础功能在所有浏览器可用
  4. 响应式设计: 为不同设备优化布局

🎯 下一章预览

下一章将深入探讨容器查询(Container Queries),实现真正的组件级响应式设计。


最后更新: 2024年12月