目录
[1. 标准流布局(Normal Flow)](#1. 标准流布局(Normal Flow))
[2. 浮动布局(Float)](#2. 浮动布局(Float))
[3. 定位布局(Position)](#3. 定位布局(Position))
[4. Flex 布局(最常用)](#4. Flex 布局(最常用))
[5. Grid 布局](#5. Grid 布局)
[三、Flex vs Grid 对比(面试必问)](#三、Flex vs Grid 对比(面试必问))
[四、圣杯布局 vs 双飞翼布局](#四、圣杯布局 vs 双飞翼布局)
[现代写法(Flex 一行搞定)](#现代写法(Flex 一行搞定))
一、五种布局方式总览
| 布局方式 | 核心特点 | 适用场景 | 是否脱离文档流 |
|---|---|---|---|
| 标准流 | 浏览器默认排版 | 文章、文字内容 | ❌ |
| 浮动布局 | 元素横排,需清浮动 | 文字环绕、早期多栏 | ✅ 脱离 |
| 定位布局 | 精确控制位置 | 角标、弹窗、固定栏 | ✅ 脱离 |
| Flex布局 | 一维弹性布局 | 导航栏、居中、自适应 | ❌ |
| Grid布局 | 二维网格布局 | 复杂版面、整页布局 | ❌ |
二、详细解析
1. 标准流布局(Normal Flow)
浏览器默认的排版规则,也叫普通文档流/正常流。
css
/* 块级元素:独占一行,从上到下 */
div, p, h1-h6, ul, li {
display: block;
}
/* 行内元素:从左到右,一行排不下换行 */
span, a, img, input {
display: inline;
}
特点:
-
块级元素:独占一行,可设宽高
-
行内元素:并排显示,宽高无效
适用场景: 文章段落、文字排版、基础内容展示
2. 浮动布局(Float)
让块级元素脱离标准流,横着排列,不再独占一行。
css
/* 基本用法 */
.box {
float: left; /* 左浮动 */
float: right; /* 右浮动 */
}
/* 清除浮动 */
.clearfix::after {
content: '';
display: table;
clear: both;
}
/* 或简单粗暴 */
.parent {
overflow: hidden;
}
核心特点:
-
浮动元素脱离文档流,不占位置
-
父元素高度塌陷(子元素都浮动后父高度为0)
-
必须清除浮动,否则布局乱
适用场景:
-
多个 div 并排显示(早年布局)
-
横向导航栏
-
文字环绕图片
html
<!-- 文字环绕图片 -->
<div class="article">
<img src="image.jpg" style="float: left; margin-right: 10px;">
<p>文字内容会环绕在图片周围...</p>
</div>
3. 定位布局(Position)
通过设置位置坐标,把元素精确放在页面任意位置。
| 定位类型 | 参照物 | 是否脱离文档流 | 常用场景 |
|---|---|---|---|
static |
无 | ❌ | 默认值 |
relative |
自己原来位置 | ❌ | 微调、绝对定位的父容器 |
absolute |
最近的非 static 父级 | ✅ | 角标、弹窗 |
fixed |
浏览器视口 | ✅ | 固定导航、回到顶部 |
sticky |
父容器 | ❌ | 吸顶效果 |
css
/* 相对定位 */
.relative-box {
position: relative;
top: 10px;
left: 20px; /* 相对自己原来位置移动 */
}
/* 绝对定位:子绝父相 */
.parent {
position: relative;
}
.child {
position: absolute;
top: 0;
right: 0; /* 相对父容器右上角 */
}
/* 固定定位 */
.back-to-top {
position: fixed;
bottom: 20px;
right: 20px;
}
/* 粘性定位(吸顶) */
.nav {
position: sticky;
top: 0;
}
最常用场景:
-
商品角标(新品、热卖)
-
登录弹窗(居中)
-
回到顶部按钮
-
固定导航栏
4. Flex 布局(最常用)
一维弹性布局,给父元素设置 display: flex,轻松控制子元素的排列、对齐、换行。
父容器属性
| 属性 | 可选值 | 作用 |
|---|---|---|
flex-direction |
row / column / row-reverse / column-reverse | 排列方向 |
justify-content |
center / space-between / space-around / space-evenly | 主轴对齐 |
align-items |
center / flex-start / flex-end / stretch | 交叉轴对齐 |
flex-wrap |
wrap / nowrap | 是否换行 |
align-content |
center / space-between | 多行对齐 |
子元素属性
| 属性 | 作用 |
|---|---|
flex: 1 |
占满剩余空间 |
align-self |
覆盖父级 align-items |
css
/* 水平垂直居中(经典) */
.parent {
display: flex;
justify-content: center;
align-items: center;
}
/* 两栏自适应:左边固定,右边自适应 */
.left {
width: 200px;
}
.right {
flex: 1;
}
/* 导航栏 */
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}
/* 等宽卡片列表 */
.card-list {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 1;
min-width: 250px;
}
面试一句话:
Flex 是一维弹性布局,通过给父元素设置
display: flex,控制子元素排列、对齐与分配空间,可轻松实现居中、自适应、横向/纵向排列,是目前前端开发最主流的布局方案。
5. Grid 布局
二维网格布局,可以同时控制行和列,适合复杂版面。
css
/* 基本用法 */
.container {
display: grid;
grid-template-columns: 200px 1fr 200px; /* 三列:固定 自适应 固定 */
grid-template-rows: auto 1fr auto; /* 三行:头部 内容 底部 */
gap: 10px;
}
/* 常见模式 */
.grid-3 {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 三等分 */
gap: 20px;
}
/* 响应式网格 */
.grid-responsive {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
/* 整页布局 */
.app-layout {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
gap: 10px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
适用场景:
-
整页后台布局(上、左、右、下)
-
卡片瀑布流、相册宫格
-
复杂响应式版面
三、Flex vs Grid 对比(面试必问)
| 对比维度 | Flex | Grid |
|---|---|---|
| 维度 | 一维(行或列) | 二维(行和列) |
| 控制方式 | 控制子元素排列 | 控制网格布局 |
| 适用场景 | 导航栏、列表、居中 | 整页布局、复杂网格 |
| 内容驱动 | ✅ 内容决定尺寸 | ⚠️ 容器决定尺寸 |
| 浏览器兼容 | 更好 | 略差 |
css
/* Flex:适合内容不确定的列表 */
.card-list {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
/* Grid:适合结构固定的网格 */
.photo-gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
四、圣杯布局 vs 双飞翼布局
| 对比 | 圣杯布局 | 双飞翼布局 |
|---|---|---|
| 实现方式 | 浮动 + 负边距 + 相对定位 | 浮动 + 负边距 + 内边距 |
| DOM 结构 | 中间栏在最前面 | 中间栏在最前面 |
| 保护中间内容 | 用父容器的 padding | 中间栏内部再套一层 div |
| 优缺点 | 结构稍复杂 | 结构更清晰,多一层 DOM |
| 现在还用吗 | ❌ 已被 Flex 替代 | ❌ 已被 Flex 替代 |
圣杯布局(传统写法)
html
<style>
.container {
padding: 0 200px; /* 给左右栏留出位置 */
overflow: hidden; /* 清除浮动 */
}
.main {
float: left;
width: 100%; /* 占满整个宽度 */
background: #3498db;
}
.left {
float: left;
width: 200px;
margin-left: -100%; /* 拉到最左边 */
position: relative;
right: 200px; /* 往左移动200px */
background: #e74c3c;
}
.right {
float: left;
width: 200px;
margin-left: -200px; /* 拉到最右边 */
position: relative;
left: 200px; /* 往右移动200px */
background: #2ecc71;
}
</style>
<div class="container">
<div class="main">中间内容(优先渲染)</div>
<div class="left">左侧栏</div>
<div class="right">右侧栏</div>
</div>
原理:
-
三栏都设置
float: left -
中间栏
width: 100%占满父容器 -
左侧栏
margin-left: -100%拉到左边 -
右侧栏
margin-left: -200px拉到右边 -
父容器
padding给左右留空间 -
左右栏用
relative偏移到正确位置
双飞翼布局(传统写法)
<style>
.container {
overflow: hidden; /* 清除浮动 */
}
.main {
float: left;
width: 100%;
}
.main-content {
margin: 0 200px; /* 给左右栏留空间 */
background: #3498db;
}
.left {
float: left;
width: 200px;
margin-left: -100%; /* 拉到左边 */
background: #e74c3c;
}
.right {
float: left;
width: 200px;
margin-left: -200px; /* 拉到右边 */
background: #2ecc71;
}
</style>
<div class="container">
<div class="main">
<div class="main-content">中间内容(优先渲染)</div>
</div>
<div class="left">左侧栏</div>
<div class="right">右侧栏</div>
</div>
与圣杯的区别:
-
圣杯:用父容器的
padding保护中间内容 -
双飞翼:中间栏内部再套一层
div,用margin保护
现代写法(Flex 一行搞定)
html
<style>
.container {
display: flex; /* 关键 */
}
.left {
width: 200px;
background: #e74c3c;
}
.main {
flex: 1; /* 占满剩余空间 */
background: #3498db;
}
.right {
width: 200px;
background: #2ecc71;
}
</style>
<div class="container">
<div class="left">左侧栏</div>
<div class="main">中间内容(自适应)</div>
<div class="right">右侧栏</div>
</div>
问:圣杯布局和双飞翼布局的区别?
答:
圣杯布局和双飞翼布局都是传统的三栏布局方案,实现左右固定、中间自适应 ,且中间栏优先渲染。
实现原理:
都使用
float+负 margin让三栏并排中间栏
width: 100%占满父容器左右栏用
margin-left: -100%和margin-left: -宽度拉到两侧区别:
圣杯布局:用父容器的
padding给左右留空间,左右栏用relative偏移双飞翼布局:中间栏内部再套一层 div,用
margin给左右留空间现在:
这两种布局已经被更简洁的 Flex 布局取代,实际开发中直接用
display: flex+flex: 1即可实现,不需要了解这些老式写法。