Skip to content

CSS 布局

作者:青见春山
发表于:2026-07-29
字数统计:9000 字
预计阅读31分钟

涵盖 BFC、圣杯布局、双飞翼布局、三栏布局(5 种方案)、居中布局(8 种方案)、Flex 完整指南、Grid 完整指南、瀑布流、响应式。

一、BFC(Block Formatting Context)

1. 什么是 BFC

BFC(块级格式化上下文)是 CSS 渲染过程的一块独立区域,区域内的元素布局不会影响外部,外部也不会影响内部。

2. 触发 BFC

CSS
/* 以下方式都会创建 BFC */
.float { float: left; }                  /* 浮动 */
.ofh { overflow: hidden; }               /* overflow 不为 visible */
.abs { position: absolute; }             /* 绝对定位 */
.fix { position: fixed; }                /* 固定定位 */
.flex { display: flex; }                 /* flex 容器 */
.grid { display: grid; }                 /* grid 容器 */
.inline-block { display: inline-block; } /* 行内块 */
.table { display: table; }               /* 表格 */
.cell { display: table-cell; }           /* 表格单元格 */
.flow-root { display: flow-root; }      /* 显式 BFC(推荐) */
.html { html 本身; }                     /* html 根元素 */

3. BFC 的特性与作用

CSS
/* 特性 1:内部 box 在垂直方向一个接一个放置 */
.bfc {
  display: flow-root;  /* 创建 BFC */
  /* 子元素垂直排列 */
}

/* 特性 2:垂直方向的距离由 margin 决定,属于同一个 BFC 的相邻 box 的 margin 会重叠(margin 折叠) */

/* 特性 3:BFC 区域不会与浮动 box 重叠(实现两栏布局) */
.container {
  display: flow-root;
  /* 利用 BFC 不会与浮动元素重叠的特性 */
}

/* 特性 4:BFC 计算高度时包括浮动元素(清除浮动) */
.container {
  display: flow-root;
  /* 浮动的子元素会被计入高度 */
}

/* 特性 5:BFC 是独立的容器,内部元素不会影响外部 */

4. BFC 应用场景

HTML
<!-- 场景 1:清除浮动(父元素高度塌陷) -->
<style>
  .parent { display: flow-root; }
  .child { float: left; height: 100px; }
</style>
<div class="parent">
  <div class="child"></div>
</div>
<!-- 父元素高度 = 子元素高度,塌陷解决 -->

<!-- 场景 2:避免 margin 折叠 -->
<style>
  .box { margin: 20px 0; }
  .wrapper { display: flow-root; }
</style>
<div class="wrapper">
  <div class="box">上 margin 20</div>
</div>
<div class="wrapper">
  <div class="box">上 margin 20(不会与上一个叠加)</div>
</div>

<!-- 场景 3:实现两栏布局 -->
<style>
  .left { float: left; width: 200px; background: red; }
  .right { display: flow-root; background: blue; }
</style>
<div class="left"></div>
<div class="right">右栏</div>
<!-- right 是 BFC,不会被 left 覆盖 -->

二、常见布局方案

1. 居中布局

水平居中

CSS
/* 1. inline 元素:text-align */
.parent { text-align: center; }
.child { display: inline-block; }

/* 2. block 元素 + 定宽:margin auto */
.child { width: 200px; margin: 0 auto; }

/* 3. block 元素 + 不定宽:display flex(推荐) */
.parent { display: flex; justify-content: center; }

/* 4. 绝对定位 + transform(不需定宽) */
.child { position: absolute; left: 50%; transform: translateX(-50%); }

垂直居中

CSS
/* 1. 单行行内元素:line-height */
.parent { height: 100px; line-height: 100px; }
.child { display: inline-block; }

/* 2. 多行行内元素:display table-cell + vertical-align */
.parent { display: table-cell; vertical-align: middle; height: 100px; }

/* 3. block + 定高:绝对定位 + 负 margin */
.child {
  position: absolute;
  top: 50%;
  height: 50px;
  margin-top: -25px;
}

/* 4. block + 不定高:flex(推荐) */
.parent {
  display: flex;
  align-items: center;
  height: 100px;
}

/* 5. 绝对定位 + transform */
.child {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

水平垂直居中

CSS
/* 1. flex(最常用) */
.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 2. grid */
.parent {
  display: grid;
  place-items: center;
}

/* 3. 绝对定位 + transform */
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* 4. 绝对定位 + margin auto */
.child {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  margin: auto;
  width: 200px;
  height: 100px;
}

2. 三栏布局(5 种方案)

方案 1:float + margin(经典)

CSS
.left, .right { float: left; width: 200px; }
.center { margin: 0 200px; }
/* ⚠️ 问题:center 区域内容会被浮动遮挡,且需要清浮动 */

方案 2:float + BFC

CSS
.left { float: left; width: 200px; }
.right { float: right; width: 200px; }
.center { display: flow-root; margin: 0 200px; }
/* ✅ center 形成 BFC,不会被浮动遮挡 */

方案 3:position 绝对定位

CSS
.parent { position: relative; }
.left, .right { position: absolute; top: 0; width: 200px; }
.left { left: 0; }
.right { right: 0; }
.center { margin: 0 200px; }
/* ⚠️ 高度需要随中间内容自适应 */

方案 4:table 布局

CSS
.parent { display: table; width: 100%; }
.left, .center, .right { display: table-cell; }
.left, .right { width: 200px; }
/* ✅ 高度自动对齐,缺点是 table 语义差 */

方案 5:flex(推荐)

CSS
.parent { display: flex; }
.left, .right { width: 200px; flex: 0 0 200px; }
.center { flex: 1; }
/* ✅ 简单、灵活、自适应 */

方案 6:grid(最强大)

CSS
.parent {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
}
/* ✅ 代码最少,能力最强 */

3. 圣杯布局(Holy Grail Layout)

三栏布局的变种:左右固定宽度,中间先渲染(HTML 中位置在前)。

HTML
<div class="container">
  <div class="center">中间</div>
  <div class="left">左</div>
  <div class="right">右</div>
</div>
CSS
/* 关键思路:用 float + 负 margin 把左右栏拉到中间行 */
.container {
  padding: 0 200px;  /* 给左右栏留出空间 */
  overflow: hidden;
}

.center, .left, .right {
  float: left;
  position: relative;
}

.center { width: 100%; }
.left { width: 200px; margin-left: -100%; left: -200px; }
.right { width: 200px; margin-left: -200px; right: -200px; }

/* ⚠️ 问题:min-width 有限制(最小宽度 = 左 + 右 + 中间),窗口太小时会乱 */

4. 双飞翼布局

HTML
<div class="container">
  <div class="center-wrap">
    <div class="center">中间</div>
  </div>
  <div class="left">左</div>
  <div class="right">右</div>
</div>
CSS
.container { overflow: hidden; }

.center-wrap, .left, .right { float: left; }
.center-wrap { width: 100%; }
.center { margin: 0 200px; }
.left { width: 200px; margin-left: -100%; }
.right { width: 200px; margin-left: -200px; }

/* 优势:没有 min-width 问题,比圣杯更稳健 */

5. 瀑布流布局

CSS
/* 方法 1:CSS columns */
.waterfall {
  column-count: 3;
  column-gap: 16px;
}
.waterfall-item {
  break-inside: avoid;
  margin-bottom: 16px;
}

/* 方法 2:JS 计算定位(更精确) */
.waterfall-item {
  position: absolute;
}
/* JS:根据图片高度计算每列的位置 */

三、Flex 布局完整指南

1. 容器属性

CSS
.container {
  display: flex;                /* 启用 flex */

  /* 主轴方向 */
  flex-direction: row | row-reverse | column | column-reverse;

  /* 换行 */
  flex-wrap: nowrap | wrap | wrap-reverse;

  /* 主轴对齐 */
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;

  /* 交叉轴对齐(单行) */
  align-items: stretch | flex-start | flex-end | center | baseline;

  /* 多行对齐 */
  align-content: stretch | flex-start | flex-end | center | space-between | space-around;
}

2. 子项属性

CSS
.item {
  order: 0;                     /* 排序,数字小的在前 */
  flex-grow: 0;                 /* 放大比例,0 不放大 */
  flex-shrink: 1;               /* 缩小比例,1 可缩小 */
  flex-basis: auto;             /* 初始大小 */
  flex: 0 1 auto;               /* grow shrink basis 简写 */

  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

3. 常用布局

CSS
/* 1. 居中(最常用) */
.container { display: flex; justify-content: center; align-items: center; }

/* 2. 左右分布 */
.container { display: flex; justify-content: space-between; }

/* 3. 一行操作按钮 */
.toolbar { display: flex; gap: 8px; }

/* 4. 自适应中间 */
.left { flex: 0 0 200px; }
.center { flex: 1; }
.right { flex: 0 0 200px; }

/* 5. 垂直布局 */
.column { display: flex; flex-direction: column; }

/* 6. 文本溢出省略 */
.flex-ellipsis { display: flex; }
.flex-ellipsis .text {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

四、Grid 布局完整指南

1. 基础概念

CSS
.container {
  display: grid;

  /* 定义行高 */
  grid-template-rows: 100px 200px auto;

  /* 定义列宽 */
  grid-template-columns: 200px 1fr 200px;

  /* 间距 */
  gap: 16px;                     /* row-gap + column-gap */
  row-gap: 16px;
  column-gap: 16px;
}

2. 命名网格

CSS
.container {
  display: grid;
  grid-template-areas:
    "header header header"
    "sidebar main aside"
    "footer footer footer";
}

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

3. 函数式定义

CSS
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);     /* 3 列等宽 */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));  /* 自适应列数 */
  grid-template-columns: 200px 1fr 200px;    /* 显式三列 */
}

.item {
  grid-column: 1 / 3;      /* 跨第 1~3 列 */
  grid-row: 1 / 2;         /* 第 1 行 */

  /* 简写:grid-row-start / grid-row-end */
  grid-area: 1 / 1 / 2 / 3;  /* row-start / col-start / row-end / col-end */
}

4. 实用模板

CSS
/* 经典管理后台布局 */
.app-layout {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  grid-template-rows: 60px 1fr 40px;
  grid-template-columns: 200px 1fr;
  height: 100vh;
}

/* 自适应卡片 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
}

/* 等高布局(grid 天然支持) */
.row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* 子项高度自动相同 */
}

5. Flex vs Grid 选择

场景推荐
一维布局(一行或一列)Flex
二维布局(行列同时控制)Grid
内容驱动(项目大小决定布局)Flex
布局驱动(先有容器骨架)Grid
微调(间距、居中、对齐)Flex
复杂页面骨架Grid

五、响应式布局

1. 媒体查询

CSS
/* 移动优先写法 */
.container { font-size: 14px; }

@media (min-width: 768px) {
  .container { font-size: 16px; }
}

@media (min-width: 1024px) {
  .container { font-size: 18px; }
}

2. 响应式图片

CSS
img {
  max-width: 100%;
  height: auto;
}

/* art direction:不同屏幕用不同图片 */
@media (max-width: 600px) {
  .hero-img { content: url('mobile.jpg'); }
}
@media (min-width: 601px) {
  .hero-img { content: url('desktop.jpg'); }
}

3. 容器查询(Container Queries)

CSS
.card-container {
  container-type: inline-size;
  container-name: card;
}

@container card (min-width: 400px) {
  .card { display: flex; }
  .card-image { flex: 0 0 200px; }
}

@container card (max-width: 399px) {
  .card { display: block; }
}

4. 自适应单位

CSS
/* rem:相对 html 字号 */
html { font-size: 16px; }
.box { width: 10rem; }  /* 160px */

/* vw/vh:相对视口 */
.hero { width: 100vw; height: 100vh; }
.box { font-size: 4vw; }

/* clamp:响应式字号 */
.title {
  font-size: clamp(1rem, 2vw + 1rem, 3rem);
  /* 最小 1rem,最大 3rem,介于中间随视口缩放 */
}

六、面试高频问答

Q1: 什么是 BFC?有什么用?

:BFC(块级格式化上下文)是 CSS 渲染过程的一块独立区域。触发方式包括 float(除 none)、overflow(除 visible)、position(absolute/fixed)、display(flex/grid/inline-block/table-cell/flow-root)等。

BFC 的核心作用:

  1. 清除浮动:BFC 计算高度时包含浮动元素(解决父元素高度塌陷)
  2. 避免 margin 折叠:相邻元素不属于同一 BFC 时不会发生 margin 折叠
  3. 防止被浮动覆盖:BFC 区域不会与浮动 box 重叠(实现两栏布局)

Q2: 三栏布局有几种实现方式?优缺点?

:常见 5 种:

方案优点缺点
float + margin兼容性好需要清浮动,中间内容可能遮挡
float + BFC不被遮挡兼容性 OK
position 绝对简单高度不自适应
table 布局高度自动对齐table 语义差
flex简单灵活兼容性 IE 不支持
grid代码最少兼容性 IE 不支持

现代推荐 flex 或 grid

Q3: 圣杯布局和双飞翼布局的区别?

  • 圣杯:用一个 container 包三栏,container 加左右 padding,左右栏用相对定位 + 负 margin 把位置拉到 padding 处。中间内容不需要额外包裹
  • 双飞翼:中间内容多包一层 wrapper,wrapper 占 100%,左右栏用负 margin 拉到两侧。中间内容位置靠 wrapper 的 margin 调整

两者效果一致,都是三栏布局。双飞翼更稳健(不存在 min-width 问题),圣杯不需要嵌套

Q4: Flex 和 Grid 怎么选?

  • Flex:一维布局(控制单方向),内容驱动,适合组件内微调
  • Grid:二维布局(行列同时控制),布局驱动,适合页面整体骨架

实际项目通常组合使用:Grid 做页面骨架Flex 做组件内布局

Q5: 如何实现水平垂直居中?

:常见 4 种:

  1. Flex(最常用):display: flex; justify-content: center; align-items: center;
  2. Griddisplay: grid; place-items: center;
  3. 绝对定位 + transform(不需定宽):position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  4. 绝对定位 + margin auto(需定宽高):position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto;

七、关联文档