Skip to content

Flex 与 Grid 布局详解

概要

FlexboxGrid 是前端最常用的两大布局方案。Flexbox擅长一维布局(行或列);Grid擅长二维布局(行 + 列)。它们并不是互斥的,很多时候需要结合使用。

一、Flex 布局

通过深入学习,我发现 flex-basis 是一个非常实用的属性。

1. 容器属性

属性作用示例
display定义弹性容器display: flex;
flex-direction主轴方向row / column
flex-wrap是否换行nowrap / wrap
justify-content主轴对齐flex-start / center / space-between
align-items交叉轴对齐stretch / center / flex-end
gap子项间距gap: 10px;

2. 子项属性

属性作用示例
flex-grow占据剩余空间flex-grow: 1;
flex-shrink空间不足时收缩flex-shrink: 0;
flex-basis初始大小flex-basis: 200px;
flex复合属性flex: 1 0 auto;
align-self覆盖单个子项的对齐方式align-self: center;

3. Flex 示例

左侧
右侧
scss
.gridWrap {
  display: flex;
  flex-wrap: wrap;

  .gridItem {
    flex: 1;
    flex-basis: 50%;
    box-sizing: border-box;

    &:nth-child(2n) {
      padding-left: 24rpx; // 希望两个之间有间隙的做法
    }
  }
}
scss
.wrap {
  display: flex;
  flex-wrap: wrap;

  .item {
    width: 32%;
    height: 100px;
    margin-bottom: 10px;
    background-color: #ccc;

    &:nth-child(3n + 2) {
      margin-right: 2%;
      margin-left: 2%;
    }

    &:nth-child(3n + 1) {
      margin-left: 0;
    }

    &:nth-child(3n + 3) {
      margin-right: 0;
    }
  }
}
scss
// 使用flex、gap属性来设置间隙
.imgWrap {
  width: 100%;
  max-height: 400px;
  display: flex;
  flex-wrap: wrap;
  padding: 20px 0;
  overflow-y: auto;
  gap: 16px;

  .imgWrap_item {
    width: calc(25% - 12px);
    height: 200px;
  }
}

// 或者使用margin来设置间隙
.imgWrap {
  width: 100%;
  max-height: 400px;
  display: flex;
  flex-wrap: wrap;
  padding: 20px 0;
  overflow-y: auto;
  margin: -8px;

  .imgWrap_item {
    position: relative;
    width: calc(25% - 16px);
    height: 200px;
    margin: 8px;
  }
}
scss
// 实现这个左右效果不需要固定宽
.infoItem {
  display: flex;
  align-items: center;

  .infoKey {
    flex: 1;
  }

  .infoValue {
    flex: 2;
  }
}

二、Grid 布局

Grid 是一种二维布局系统,可以同时在 行(rows)列(columns) 方向上精确控制元素的位置。与 Flexbox 专注于一维布局不同,Grid 更适合 整体页面结构复杂组件布局

1. 容器属性

属性作用示例
display: grid定义为网格容器display: grid;
grid-template-columns定义列数和列宽grid-template-columns: 200px 1fr 2fr;
grid-template-rows定义行数和行高grid-template-rows: 100px auto;
gap / row-gap / column-gap设置网格间距gap: 10px;
justify-items列方向对齐方式start / center / end / stretch
align-items行方向对齐方式start / center / end / stretch
justify-content整个网格的水平对齐start / center / space-between
align-content整个网格的垂直对齐start / center / space-between

2. 子项属性

属性作用示例
grid-column设置列的起止位置grid-column: 1 / 3;
grid-row设置行的起止位置grid-row: 2 / 4;
justify-self单个项目的水平对齐center
align-self单个项目的垂直对齐end

3. 常见布局速查表

布局场景代码示例说明
等宽多列布局grid-template-columns: repeat(3, 1fr);三列等分,可改 3 为任意列数
固定宽度 + 自适应列grid-template-columns: 200px 1fr;第一列固定宽度,第二列占剩余空间
自适应列数(响应式)grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));列宽最小 200px,多余空间自动增加列
自动填充列(不折叠空列)grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));auto-fit 类似,但会保留空列
两列固定 + 中间自适应grid-template-columns: 150px 1fr 150px;左右侧边栏固定,中间内容自适应
网格间距gap: 10px;同时设置行间距和列间距
单个元素跨列grid-column: 1 / 3;从第 1 列跨到第 3 列(不含 3)
单个元素跨行grid-row: 1 / 3;从第 1 行跨到第 3 行(不含 3)
垂直 & 水平居中place-items: center;相当于 align-items + justify-items
命名区域布局grid-template-areas: "header header" "sidebar main" "footer footer";通过区域名控制布局

💡 速记技巧:

  • fr 表示比例分配,1fr = 占剩余空间的 1 份
  • repeat(n, …) 批量定义重复模式
  • minmax(min, max) 让列/行在指定范围内伸缩
  • auto-fit 自动收缩填满空间,auto-fill 会保留空格子

4. Grid 示例

scss
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
scss
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}
html
<!-- 实现一个 三栏响应式布局,带顶部导航和底部区域。 -->
<style>
.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: 60px auto 60px;
  grid-template-areas:
    "header header header"
    "sidebar main ads"
    "footer footer footer";
  gap: 10px;
}
.header { grid-area: header; background: #333; color: white; }
.sidebar { grid-area: sidebar; background: #ccc; }
.main { grid-area: main; background: #eee; }
.ads { grid-area: ads; background: #ddd; }
.footer { grid-area: footer; background: #999; color: white; }
</style>

<div class="container">
  <div class="header">Header</div>
  <div class="sidebar">Sidebar</div>
  <div class="main">Main</div>
  <div class="ads">Ads</div>
  <div class="footer">Footer</div>
</div>

三、Flex vs Grid 对比

特性FlexboxGrid
布局维度一维(行或列)二维(行+列)
对齐方式justify-content + align-itemsjustify-items + align-items
适合场景导航栏、按钮组、居中布局页面整体布局、宫格、仪表盘
灵活性内容驱动容器驱动
学习成本简单稍复杂

四、常用css

css
.item {
  padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
}
scss
.item {
  word-break: break-all; // 纯数字换行
  shape-outside: circle(50% at 50% 50%); // 不规则的文字环绕
  white-space: pre; // 文字两端对齐
}

// 滑动吸附效果--常见于swiper
.wrap {
  scroll-snap-type: x mandatory; // 可更换为proximity 表示为附近吸附

  .item {
    scroll-snap-align: start; // 排列
    scroll-snap-stop: always; // 吸附是否停止
  }
}

// 设置宽高比例
.box {
  width: 90%;
  aspect-ratio: 16/9;
}

// 逻辑属性
.box {
  margin-block: 5px 10px; /* 上边距 5px,下边距 10px */
  margin-inline: 20px 30px; /* 左边距 20px,右边距 30px */

  padding-block: 10px 20px; /* 上下内边距 */
  padding-inline: 15px 25px; /* 左右内边距 */
}

// 平滑滚动
html {
  scroll-behavior: smooth;
}

五、css好网站

这里是一些优秀的网站资源,可以用于 CSS 相关的开发和设计:

以下是一些可以在线绘制 SVG 波浪效果的网站:

此外,以下是一些与 echarts 相关的网站资源:

  • PPChart - 提供多种样式的图表模板和代码示例。
  • madeapie - 一个在线生成 echarts 图表的工具。
  • echarts Demo 集 - 包含了丰富的 echarts 示例和演示。
  • MCChart - 提供多种样式的 echarts 图表模板。
  • echart 社区 - 一个 echarts 资源分享和交流的社区。

小小棱镜,无限可能 | CC BY-NC-SA 4.0 协议