CSS布局


created: 2026-06-13

tags: css, 布局, 面试, 零基础

CSS 布局 ------ 把元素放到正确的位置

学习前提:你已经知道 CSS 基础(选择器、盒模型、display),现在要学的是------怎么把元素摆到页面上你想要的位置。


1. Flexbox(面试必考,最高优先级)

Flexbox 是啥?先打比方

类比 :想象你有一个托盘 (flex 容器),上面放了几个碗(flex 项目)。

复制代码
┌───┬───┬───┐
│ 碗1 │ 碗2 │ 碗3 │
└───┴───┴───┘

Flexbox 就是用来控制这些"碗"在"托盘"上怎么排列的:

  • 从左到右排?还是从上到下排?
  • 靠左?靠右?居中?
  • 空间不够了怎么办?缩小还是换行?
  • 某个碗特别大,怎么分配空间?

一句话总结 :Flexbox 是一种一维 布局系统,它只关心一行 或者一列(不能同时控制行和列)。

面试重点 :Flexbox 是前端面试最高频的 CSS 考点,几乎每一场面试都会问。


先看一个最简单的例子

html 复制代码
<div style="display: flex;">
  <div style="padding: 10px; background: red;">1</div>
  <div style="padding: 10px; background: green;">2</div>
  <div style="padding: 10px; background: blue;">3</div>
</div>

效果 :三个本来应该竖着堆叠的 div(因为 block 元素默认独占一行),现在横着排成了一行!

人话 :加了 display: flex 后,父元素就变成了"灵活容器",里面的子元素默认从左到右横着排列。


容器属性(写在父元素上)

flex-direction ------ 决定排列方向
css 复制代码
.container {
  display: flex;
  flex-direction: row;  /* 默认值:从左到右横着排 */
}
值 效果 人话
row(默认) → 从左到右 横着排
row-reverse ← 从右到左 横着反过来排
column ↓ 从上到下 竖着排
column-reverse ↑ 从下到上 竖着反过来排
css 复制代码
/* 竖着排列 */
.container {
  display: flex;
  flex-direction: column;
}
/* 效果:子元素从上到下排列,恢复成block的竖排效果 */

justify-content ------ 主轴方向的对齐(面试必考)

先搞懂"主轴"是哪个方向:

  • 当 flex-direction: row 时,主轴 = 水平方向(从左到右)
  • 当 flex-direction: column 时,主轴 = 垂直方向(从上到下)

justify-content 控制元素在主轴方向怎么排列。

css 复制代码
.container {
  display: flex;
  /* flex-direction: row 时,justify-content 控制水平排列 */
}
css 复制代码
/* 靠左排列(默认) */
.container { justify-content: flex-start; }
/* ┌──┬──┬──┐                */
/* │1 │2 │3 │                */
/* └──┴──┴──┘                */
css 复制代码
/* 靠右排列 */
.container { justify-content: flex-end; }
/*                 ┌──┬──┬──┐ */
/*                 │1 │2 │3 │ */
/*                 └──┴──┴──┘ */
css 复制代码
/* 居中排列 */
.container { justify-content: center; }
/*         ┌──┬──┬──┐          */
/*         │1 │2 │3 │          */
/*         └──┴──┴──┘          */
css 复制代码
/* 两端对齐:第一个靠左,最后一个靠右,中间均匀分布 */
.container { justify-content: space-between; }
/* ┌──┬──────┬──┬──────┬──┐       */
/* │1 │      │2 │      │3 │       */
/* └──┴──────┴──┴──────┴──┘       */
css 复制代码
/* 每个元素左右空间相等 */
.container { justify-content: space-around; }
/*   ┌──┬──┬──┬──┬──┬──┐           */
/*   │1 │  │2 │  │3 │  │           */
/*   └──┴──┴──┴──┴──┴──┘           */
css 复制代码
/* 完全等距 */
.container { justify-content: space-evenly; }
/*  ┌──┬──┬──┬──┬──┬──┐            */
/*  │1 │  │2 │  │3 │  │            */
/*  └──┴──┴──┴──┴──┴──┘            */

人话总结 :justify-content 就像在架子上摆碗 ------ 你想挤在左边、右边、中间,还是均匀散开。

面试重点 :justify-content: center 是实现水平居中的关键,要记住!


align-items ------ 交叉轴方向的对齐

交叉轴 = 和主轴垂直的方向:

  • 如果主轴是水平的(row),交叉轴就是垂直的
  • 如果主轴是垂直的(column),交叉轴就是水平的
css 复制代码
.container {
  display: flex;
  height: 200px;  /* 给个高度才能看到效果 */
}
css 复制代码
/* 拉伸填满(默认)------ 子元素高度自动拉伸到和父容器一样高 */
.container { align-items: stretch; }
css 复制代码
/* 靠上对齐 */
.container { align-items: flex-start; }
css 复制代码
/* 靠下对齐 */
.container { align-items: flex-end; }
css 复制代码
/* 垂直居中(超重要!) */
.container { align-items: center; }

人话总结 :align-items 控制元素在垂直方向的位置(当 flex-direction 为 row 时)。

面试重点 :justify-content: center + align-items: center = 水平垂直居中,面试必考题!


flex-wrap ------ 换不换行
css 复制代码
.container {
  display: flex;
  flex-wrap: nowrap;  /* 默认:不换行,所有项目挤在一行 */
}

假设容器宽 300px,每个项目宽 100px,一共 4 个项目:

  • nowrap(默认):4 × 100 = 400 > 300,项目会被压缩到一行里
  • wrap:超出的项目会换到下一行,变成 3 个一行 + 1 个在第二行
  • wrap-reverse:换行,但新行在上方
css 复制代码
.container {
  display: flex;
  flex-wrap: wrap;  /* 自动换行 */
}
.item {
  width: 100px;
  height: 100px;
}

常见坑 :不加 flex-wrap: wrap,子元素会被压缩到一行,看着变形了。做了响应式布局一定要加 flex-wrap: wrap。


gap ------ 项目之间的间距
css 复制代码
.container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;        /* 项目之间上下左右都是 20px 间距 */
  /* row-gap: 20px; 只控制行的间距 */
  /* column-gap: 20px; 只控制列的间距 */
}

人话 :gap 就是在项目之间"插入"固定的空隙。和 margin 的区别是:gap 只在项目之间加,不在边缘加。

常见坑 :以前没有 gap 时,大家用 margin + 各种 hack。现在直接用 gap,干净利落。


项目属性(写在子元素上)

flex ------ 缩写(面试必考)

flex 是三个属性的缩写:flex-grow(放大) | flex-shrink(缩小) | flex-basis(初始大小)

最常见的用法:flex: 1
css 复制代码
.item {
  flex: 1;
}
/* 等价于:
   flex-grow: 1;
   flex-shrink: 1;
   flex-basis: 0%; */

人话 :flex: 1 的意思是"把剩下的空间都给我"。

举个栗子:

html 复制代码
<div style="display: flex; width: 600px;">
  <div style="flex: 1; background: red;">1</div>
  <div style="flex: 2; background: green;">2</div>
  <div style="flex: 1; background: blue;">3</div>
</div>

怎么分空间?

  • 3 个项目的 flex 分别是 1、2、1,总和 = 4
  • 600px 分成 4 份,每份 = 150px
  • 红 = 150px,绿 = 300px,蓝 = 150px

人话 :flex 的数字就像"分蛋糕的比例"。flex:1 分 1 份,flex:2 分 2 份。

等宽布局
css 复制代码
.item {
  flex: 1;  /* 所有 item 都写 flex:1,宽度就一样了 */
}
固定侧边栏 + 自适应内容
css 复制代码
.layout {
  display: flex;
}
.sidebar {
  width: 200px;
  flex-shrink: 0;     /* 禁止缩小 ------ 永远保持200px */
}
.main {
  flex: 1;            /* 占据剩下的所有空间 */
}

面试重点 :给一个容器,里面三个项目,flex: 1 / flex: 2 / flex: 1,问各占多少比例 ------ 常见面试题。


align-self ------ 单独"不听话"的项目
css 复制代码
.container {
  display: flex;
  height: 200px;
  align-items: flex-start;  /* 其他项目都靠上 */
}

.special {
  align-self: center;       /* 偏偏我要居中 */
}

人话 :align-items 是给所有项目设置的"统一规则",align-self 允许某个项目"不听话",单独给自己设置一个对齐方式。


order ------ 改变视觉顺序
css 复制代码
.item1 { order: 2; }
.item2 { order: 1; }  /* 这个反而排到前面去了 */
.item3 { order: 3; }

人话 :不改变 HTML 结构,只改变显示顺序。默认所有项目 order: 0,数字小的排前面。


Flexbox 经典布局(面试常考)

1. 水平垂直居中(面试最爱,必须会!)
css 复制代码
.parent {
  display: flex;
  justify-content: center;  /* 水平居中 */
  align-items: center;      /* 垂直居中 */
  height: 300px;            /* 父容器要有高度才能垂直居中 */
}
html 复制代码
<div class="parent" style="border: 1px solid black;">
  <div style="background: red; padding: 20px;">我居中啦!</div>
</div>

效果:红色块在父容器正中央,不多不少刚刚好。

面试重点:几乎所有面试都会问"如何让一个元素水平垂直居中",flexbox 方案是第一回答。


2. 粘性底部(Sticky Footer)

需求:不管内容多还是少,footer 永远在页面底部。

html 复制代码
<body>
  <header>Header</header>
  <main>内容区域(内容少时,footer也在底部)</main>
  <footer>Footer</footer>
</body>
css 复制代码
body {
  display: flex;
  flex-direction: column;  /* 从上到下排列 */
  min-height: 100vh;       /* 至少占满整个屏幕高度 */
  margin: 0;               /* 去掉body默认的外边距 */
}

main {
  flex: 1;                 /* 自动撑满剩余空间,把footer推到底部 */
}

footer {
  height: 60px;
  background: #333;
  color: white;
  text-align: center;
}

人话 :main 区域的 flex: 1 就像一个可伸缩的弹簧 ------ 内容少时它就伸长撑满空间,内容多时它自动压缩。


3. 等距卡片(网格)
css 复制代码
.container {
  display: flex;
  flex-wrap: wrap;    /* 允许换行 */
  gap: 16px;          /* 卡片间距 */
}

.card {
  flex: 1 1 300px;    /* grow:1 shrink:1 basis:300px */
  /* 人话:每个卡片至少300px宽,空间多了就长大,空间少了就缩小,不够就换行 */
}

2. Grid(二维布局)

Flexbox vs Grid:一个经典类比

Flexbox Grid
维度 一维(行或列) 二维(行和列同时控制)
思路 内容优先 ------ "这些项目怎么排" 布局优先 ------ "我先画个网格,再把项目放进去"
最佳场景 导航栏、列表、居中、小部件排列 整个页面的骨架、复杂的二维排列

人话:

  • Flexbox:你有一排东西,告诉它们怎么在这一排 或这一列里排列
  • Grid:你画了一张表格 ,把东西方到对应的 格子 里

Grid 基础

css 复制代码
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;  /* 3列,每列等宽 */
  gap: 10px;
}
html 复制代码
<div class="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div>

效果:6 个项目排成 2 行 3 列,像表格一样整整齐齐。


fr ------ 分数单位

css 复制代码
/* 3列等宽 */
.container { grid-template-columns: 1fr 1fr 1fr; }
css 复制代码
/* 左侧200px,右侧占剩余空间 */
.container { grid-template-columns: 200px 1fr; }
css 复制代码
/* 三列,中间是内容区,左右固定 */
.container { grid-template-columns: 200px 1fr 200px; }

人话 :fr = fraction(分数),就像 flexbox 里的 flex: 1,按比例分配剩余空间。


repeat() ------ 重复简写

css 复制代码
/* 下面两种写法一样 */
.container { grid-template-columns: 1fr 1fr 1fr; }
.container { grid-template-columns: repeat(3, 1fr); }  /* 重复3次1fr */

Grid 区域命名 ------ 最直观的布局方式

css 复制代码
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;  /* 两列:左200px,右自适应 */
  grid-template-rows: auto 1fr auto;  /* 三行:头、内容、脚 */
  grid-template-areas:
    "header header"    /* 第一行:header占两列 */
    "sidebar main"     /* 第二行:sidebar左列,main右列 */
    "footer footer";   /* 第三行:footer占两列 */
  gap: 10px;
  min-height: 100vh;
}

/* 把对应的区域名字写在元素上 */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
html 复制代码
<div class="layout">
  <header class="header">Header</header>
  <aside class="sidebar">Sidebar</aside>
  <main class="main">Main Content</main>
  <footer class="footer">Footer</footer>
</div>

效果:

复制代码
┌──────────────────────────────┐
│          Header              │  ← 横跨两列
├─────────┬────────────────────┤
│ Sidebar │    Main Content    │
│ 200px   │                    │
├─────────┴────────────────────┤
│          Footer              │  ← 横跨两列
└──────────────────────────────┘

人话 :用 grid-template-areas 就像画座位表 ------ 你告诉 Grid "第一排两个位置给 header,第二排左边给 sidebar 右边给 main",然后每个元素报自己的名字就行。

面试重点:Grid 区域命名做页面骨架布局(圣杯布局),清晰直观,面试时能用上就是加分项。


3. 响应式设计

核心思想:同一个页面在不同屏幕上都好看

在手机上竖着排,在电脑上横着排 ------ 这就是响应式。

媒体查询(Media Query)

css 复制代码
/* 默认样式(桌面端优先) */
.container {
  display: flex;
  flex-direction: row;    /* 横着排 */
}

/* 当屏幕宽度小于等于 768px 时(平板、手机) */
@media (max-width: 768px) {
  .container {
    flex-direction: column;  /* 改为竖着排 */
  }
}

语法拆解:

css 复制代码
@media (max-width: 768px) {
  /* 条件:屏幕宽度 ≤ 768px 时,花括号里的CSS生效 */
  /* 这个就叫"断点"(breakpoint) */
}

常见断点:

css 复制代码
/* 手机:< 480px */
@media (max-width: 480px) { ... }

/* 平板:481px ~ 768px */
@media (max-width: 768px) { ... }

/* 小桌面:769px ~ 1024px */
@media (max-width: 1024px) { ... }

/* 大桌面:> 1024px ------ 默认样式 */

响应式单位

css 复制代码
.text {
  font-size: 16px;    /* 固定大小,不会随着屏幕变化 */
  font-size: 1rem;    /* 基于根元素字号,推荐 */
}

.box {
  width: 50%;         /* 父容器的一半宽 */
  height: 50vh;       /* 视口高度的一半 */
}

.full-screen {
  width: 100vw;       /* 铺满视口宽 */
  height: 100vh;      /* 铺满视口高 */
}

移动端必加的一行

html 复制代码
<meta name="viewport" content="width=device-width, initial-scale=1.0">

人话:这行代码告诉手机浏览器:"别自作主张缩放页面,按设备的真实宽度显示"。不加的话,手机浏览器会把 980px 宽的页面缩成手机屏幕大小,字就变得很小。


4. 面试经典布局题

题目 1:水平垂直居中(至少会 3 种方法!)

css 复制代码
/* 方法1:Flexbox(最推荐,一行搞定) */
.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}
css 复制代码
/* 方法2:absolute + transform(万能居中) */
.parent {
  position: relative;   /* 给子元素做参考 */
}
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);  /* 把自己往回挪一半 */
}
/* 人话:先让左上角在正中间,再把自己往左上方拽自身宽高的一半 */
css 复制代码
/* 方法3:Grid(最简洁) */
.parent {
  display: grid;
  place-items: center;  /* 一个属性搞定水平和垂直居中 */
}

面试重点:面试官问"如何居中",至少说出 flexbox 和 absolute+transform 两种。


题目 2:两栏布局(左侧固定,右侧自适应)

css 复制代码
/* Flexbox 方法 */
.container {
  display: flex;
}
.sidebar {
  width: 200px;
  flex-shrink: 0;     /* 禁止缩小 */
}
.main {
  flex: 1;            /* 占满剩余空间 */
}
html 复制代码
<div class="container">
  <aside class="sidebar">侧边栏 200px</aside>
  <main class="main">主内容区域,自动撑满</main>
</div>

效果:

复制代码
┌──────────┬────────────────────────────────┐
│ Sidebar  │          Main                  │
│ 200px    │         自适应                  │
└──────────┴────────────────────────────────┘

题目 3:圣杯布局(Header + 左右三栏 + Footer)

html 复制代码
<div class="layout">
  <header class="header">Header</header>
  <div class="main-content">
    <nav class="left">Left Sidebar</nav>
    <article class="center">Main Content</article>
    <aside class="right">Right Sidebar</aside>
  </div>
  <footer class="footer">Footer</footer>
</div>

Flexbox 方案:

css 复制代码
.layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.main-content {
  display: flex;
  flex: 1;                  /* 撑满中间区域 */
}

.left, .right {
  width: 200px;
  flex-shrink: 0;           /* 固定宽度不缩小 */
}

.center {
  flex: 1;                  /* 中间自适应 */
}

.footer {
  height: 60px;
}

效果:

复制代码
┌──────────────────────────────────┐
│             Header               │
├────────┬─────────────┬───────────┤
│  Left  │   Center    │   Right   │
│ 200px  │   自适应     │   200px   │
├────────┴─────────────┴───────────┤
│             Footer               │
└──────────────────────────────────┘

题目 4:等距卡片网格

css 复制代码
/* Flexbox 方案 */
.container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.card {
  flex: 1 1 300px;  /* 最小 300px,占1份,可缩小 */
  /* 或使用 calc */
  flex: 1 1 calc(33.33% - 16px);  /* 每行3列,减去gap */
}
css 复制代码
/* Grid 方案(更整齐!) */
.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
}

/* 每一列最少250px,自动填满,最后一行不会留白 */

5. 练习:做一个响应式页面

要求:用 flexbox 实现以下布局,并在手机屏幕(< 768px)时变成上下排列。

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    /* 在这里写 CSS */
  </style>
</head>
<body>
  <header class="header">
    <h1>我的网站</h1>
    <nav>
      <a href="#">首页</a>
      <a href="#">关于</a>
      <a href="#">联系</a>
    </nav>
  </header>

  <main class="main">
    <aside class="sidebar">
      <h3>侧边栏</h3>
      <ul>
        <li>分类1</li>
        <li>分类2</li>
        <li>分类3</li>
      </ul>
    </aside>
    <article class="content">
      <h2>文章标题</h2>
      <p>这是文章内容。这是文章内容。这是文章内容。这是文章内容。</p>
      <p>更多内容......</p>
    </article>
  </main>

  <footer class="footer">
    <p>&copy; 2025 我的网站</p>
  </footer>
</body>
</html>

要求:

  1. header 和 footer 横跨全屏,有背景色,白色文字
  2. main 区域用 flexbox:左侧 sidebar 200px,右侧 content 自适应
  3. footer 固定在底部(sticky footer)
  4. 页面最小高度占满屏幕

提示:

css 复制代码
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header {
  display: flex;        /* 让标题和导航在一行 */
  justify-content: space-between;
  align-items: center;
  background: #333;
  color: white;
  padding: 16px;
}

.main {
  display: flex;
  flex: 1;              /* 撑满中间区域 */
}

.sidebar {
  width: 200px;
  flex-shrink: 0;
  background: #f0f0f0;
  padding: 16px;
}

.content {
  flex: 1;
  padding: 16px;
}

.footer {
  background: #333;
  color: white;
  text-align: center;
  padding: 16px;
}

/* 响应式:手机端变上下排列 */
@media (max-width: 768px) {
  .main {
    flex-direction: column;
  }
  .sidebar {
    width: 100%;          /* 侧边栏占满宽度 */
  }
}

预期效果(桌面端 > 768px):

复制代码
┌──────────────────────────────────────┐
│ 我的网站        首页  关于  联系      │
├────────────┬─────────────────────────┤
│ 侧边栏      │  文章标题               │
│ 分类1       │  文章内容......             │
│ 分类2       │                         │
│ 分类3       │                         │
├────────────┴─────────────────────────┤
│            &copy; 2025 我的网站        │
└──────────────────────────────────────┘

预期效果(移动端 < 768px):

复制代码
┌──────────────────┐
│ 我的网站          │
│ 首页 关于 联系    │
├──────────────────┤
│ 文章标题          │
│ 文章内容......        │
├──────────────────┤
│ 侧边栏            │
│ 分类1  分类2  分类3│
├──────────────────┤
│ &copy; 2025 我的网站│
└──────────────────┘

完成了这个练习,你就掌握了前端面试中最核心的布局技能。

相关推荐
天天代码码天天20 分钟前
照片和视频之外,微信里的声音也值得好好保存
人工智能
IT_陈寒43 分钟前
Java开发实战:从入门到精通
前端·人工智能·后端
lucas_AI1 小时前
560B 只激活 25B:蚂蚁百灵 Ling-3.2-flash 把原生多模态 API 卷到 2 块钱一百万 token
人工智能
lucas_AI1 小时前
OpenAI 融资缩水、Anthropic IPO 被压价:AI 的钱,突然不好融了
人工智能
无忧_wy1 小时前
MoneyPrinterTurbo 自动化视频生成实战指南
运维·人工智能·自动化·音视频
深蓝AI1 小时前
Agent 查数据库先问口径再动手:NVIDIA 开源语义层 Auto Ontology,连续两天登顶 GitHub Python 趋势榜
人工智能·程序员
段一凡-华北理工大学10 小时前
工业智能体:从Codex/Claude到项目实战~系列文章05:从“AI助手“到“工业智能体“:能力跃迁与落地范式
人工智能·python·claude·codex·工业智能体·高炉炼铁智能化
岁月宁静11 小时前
什么是 Agent:从"会聊天"到"会做事"
人工智能·python
岁月宁静12 小时前
AI 应用开发工程师简历怎么写:HR 初筛、技术复筛、面试追问,三道关卡各看什么?
人工智能·python·面试