Skip to content

06. Flexbox 与 Grid 布局

Flexbox 和 Grid 是现代 CSS 布局的两大核心,它们让复杂布局变得简单高效。

一、Flexbox 弹性布局

1. 基础概念

┌─────────────────────────────────────┐
│       Main Axis(主轴)              │
│  ┌──────┐  ┌─────┐  ┌─────┐       │
│  │  1   │  │  2  │  │  3  │  ←───  │
│  │      │  │     │  │     │ Cross  │
│  │      │  │     │  │     │ Axis  │
│  └──────┘  └─────┘  └─────┘  (交叉轴)│
└─────────────────────────────────────┘
        Container(容器)       Items(项目)

2. 容器属性

flex-direction(主轴方向)

css
.container {
    flex-direction: row;            /* 水平向右(默认) */
    flex-direction: row-reverse;    /* 水平向左 */
    flex-direction: column;         /* 垂直向下 */
    flex-direction: column-reverse; /* 垂直向上 */
}

flex-wrap(换行)

css
.container {
    flex-wrap: nowrap;     /* 不换行(默认) */
    flex-wrap: wrap;       /* 换行,第一行在上 */
    flex-wrap: wrap-reverse; /* 换行,第一行在下 */
}

flex-flow(简写)

css
.container {
    /* flex-flow: flex-direction flex-wrap; */
    flex-flow: row wrap;
}

justify-content(主轴对齐)

css
.container {
    justify-content: flex-start;    /* 左对齐(默认) */
    justify-content: flex-end;      /* 右对齐 */
    justify-content: center;        /* 居中 */
    justify-content: space-between; /* 两端对齐,间距相等 */
    justify-content: space-around;  /* 两端间距是中间的一半 */
    justify-content: space-evenly;  /* 所有间距完全相等 */
}

align-items(交叉轴对齐)

css
.container {
    align-items: stretch;       /* 拉伸(默认) */
    align-items: flex-start;    /* 起点对齐 */
    align-items: flex-end;      /* 终点对齐 */
    align-items: center;        /* 居中 */
    align-items: baseline;      /* 基线对齐 */
}

align-content(多行对齐)

css
.container {
    align-content: stretch;       /* 拉伸(默认) */
    align-content: flex-start;    /* 起点对齐 */
    align-content: flex-end;      /* 终点对齐 */
    align-content: center;        /* 居中 */
    align-content: space-between; /* 两端对齐 */
    align-content: space-around;  /* 均匀分布 */
    align-content: space-evenly;  /* 完全均匀 */
}

3. 项目属性

order(顺序)

css
.item {
    order: 0;  /* 默认 */
    order: -1; /* 排到最前 */
    order: 2;  /* 排到后面 */
}

flex-grow(放大比例)

css
.item {
    flex-grow: 0;  /* 不放大(默认) */
    flex-grow: 1;  /* 有剩余空间,放大 */
    flex-grow: 2;  /* 放大比例是 1 的 2 倍 */
}

flex-shrink(缩小比例)

css
.item {
    flex-shrink: 1;  /* 缩小(默认) */
    flex-shrink: 0;  /* 不缩小 */
}

flex-basis(基准大小)

css
.item {
    flex-basis: auto;  /* 自动(默认) */
    flex-basis: 200px; /* 固定基准 */
}

flex(简写)

css
.item {
    /* flex: flex-grow flex-shrink flex-basis; */
    flex: 1;           /* flex: 1 1 0% */
    flex: auto;        /* flex: 1 1 auto */
    flex: none;        /* flex: 0 0 auto */
    flex: 0 0 200px;   /* 不放大不缩小,固定 200px */
}

align-self(单独对齐)

css
.item {
    align-self: auto;       /* 继承容器(默认) */
    align-self: flex-start;
    align-self: flex-end;
    align-self: center;
    align-self: baseline;
    align-self: stretch;
}

二、Grid 网格布局

1. 基础概念

┌─────────┬─────────┬─────────┬─────────┐
│  Grid   │  Cell   │  Cell   │  Cell   │
│  Row    ├─────────┼─────────┼─────────┤
├─────────┤  Cell   │  Cell   │  Cell   │
│  Grid   ├─────────┼─────────┼─────────┤
│  Row    │  Cell   │  Cell   │  Cell   │
├─────────┼─────────┼─────────┼─────────┤
│  Grid   │  Cell   │  Cell   │  Cell   │
│  Row    └─────────┴─────────┴─────────┘
└───────────────────────────────────────┘
   Grid Lines(网格线)

2. 容器属性

display(启用 Grid)

css
.container {
    display: grid;
    display: inline-grid;
}

grid-template-columns(列定义)

css
.container {
    /* 固定宽度 */
    grid-template-columns: 100px 200px 100px;

    /* 重复 */
    grid-template-columns: repeat(3, 100px);

    /* 百分比 */
    grid-template-columns: 33.33% 33.33% 33.33%;

    /* fr(fraction,占据剩余空间) */
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-columns: 1fr 2fr 1fr;

    /* auto(自适应) */
    grid-template-columns: 1fr auto 1fr;

    /* minmax(最小最大) */
    grid-template-columns: 1fr minmax(100px, 1fr) 2fr;

    /* 自动填充 */
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

    /* 自动填充+合适 */
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

grid-template-rows(行定义)

css
.container {
    grid-template-rows: 100px 200px 100px;
    grid-template-rows: repeat(3, auto);
}

grid-template-areas(区域命名)

css
.container {
    grid-template-areas:
        "header header header"
        "sidebar main main"
        "footer footer footer";
}

.item {
    grid-area: header;
    grid-area: sidebar;
    grid-area: main;
    grid-area: footer;
}

grid-template(简写)

css
.container {
    grid-template:
        "header header header" 80px
        "sidebar main    main"   1fr
        "footer footer footer" 60px /
        200px    1fr      1fr;
}

gap(间距)

css
.container {
    gap: 10px;              /* 行列相同 */
    row-gap: 10px;          /* 行间距 */
    column-gap: 20px;       /* 列间距 */
    gap: 10px 20px;         /* 行 10px,列 20px */
}

justify-items(水平对齐)

css
.container {
    justify-items: stretch;     /* 拉伸(默认) */
    justify-items: start;
    justify-items: end;
    justify-items: center;
}

align-items(垂直对齐)

css
.container {
    align-items: stretch;       /* 拉伸(默认) */
    align-items: start;
    align-items: end;
    align-items: center;
}

justify-content(整体水平对齐)

css
.container {
    justify-content: start;
    justify-content: end;
    justify-content: center;
    justify-content: space-between;
    justify-content: space-around;
    justify-content: space-evenly;
}

align-content(整体垂直对齐)

css
.container {
    align-content: start;
    align-content: end;
    align-content: center;
    align-content: space-between;
    align-content: space-around;
    align-content: space-evenly;
}

place-items(简写)

css
.container {
    place-items: center;    /* align-items + justify-items */
}

3. 项目属性

grid-column(列位置)

css
.item {
    /* 从第1条线开始,到第3条线结束 */
    grid-column: 1 / 3;

    /* 从第1条线开始,跨越2列 */
    grid-column: 1 / span 2;

    /* 简写 */
    grid-column-start: 1;
    grid-column-end: 3;
}

grid-row(行位置)

css
.item {
    grid-row: 1 / 3;
    grid-row: 1 / span 2;
}

grid-area(区域)

css
.item {
    grid-area: header;

    /* 等价于 */
    grid-row-start: 1;
    grid-column-start: 1;
    grid-row-end: 2;
    grid-column-end: 4;
}

justify-self(单独水平对齐)

css
.item {
    justify-self: start;
    justify-self: end;
    justify-self: center;
}

align-self(单独垂直对齐)

css
.item {
    align-self: start;
    align-self: end;
    align-self: center;
}

三、Flexbox vs Grid

特性FlexboxGrid
维度一维(行或列)二维(行和列)
适用场景导航、对齐、弹性布局页面整体布局、网格系统
溢出处理自动换行需要显式定义
浏览器支持更好的兼容性较新的浏览器

选择建议

  • 使用 Flexbox:导航栏、对齐元素、弹性组件
  • 使用 Grid:页面布局、网格系统、卡片布局
  • 结合使用:Grid 负责大布局,Flexbox 负责内部对齐

四、实际案例

1. 水平垂直居中

css
/* Flexbox */
.container {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Grid */
.container {
    display: grid;
    place-items: center;
}

2. 均分列

css
/* Flexbox */
.container {
    display: flex;
}
.item {
    flex: 1;
}

/* Grid */
.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}

3. 圣杯布局

css
.container {
    display: grid;
    grid-template-columns: 200px 1fr 200px;
    grid-template-rows: 60px 1fr 60px;
    grid-template-areas:
        "header header header"
        "sidebar main ads"
        "footer footer footer";
    min-height: 100vh;
}

4. 响应式网格

css
.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 20px;
    /* 自动适应,不小于250px,平分剩余空间 */
}

5. 卡片悬停效果

css
.container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 20px;
}

.card {
    transition: transform 0.3s;
}

.card:hover {
    transform: translateY(-5px);
}

五、浏览器兼容性

css
/* 前缀 */
.container {
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
    display: -webkit-grid;
    display: -ms-grid;
    display: grid;
}

/* 检测支持 */
@supports (display: grid) {
    /* Grid 支持代码 */
}

@supports (display: flex) {
    /* Flexbox 支持代码 */
}

总结

Flexbox 适合一维布局,Grid 适合二维布局。掌握这两种布局方式可以解决大部分布局需求,建议根据实际场景选择最合适的方案。