🎯 《Flex布局奇妙历险:从菜鸟到面试王者!》
前言
上一期我们学习了关于float的相关知识,其实本来这期要做position的,但是感觉没什么东西,我就直接把position放在了上一期的最后一部分(偷偷更新了一下),如果没有看,那么下面是传送门↓↓↓:
浮动:让元素学会“轻功”,让他们飞起来!!!(Chapter 2)
ok,话不多说,我们开始今天的弹性布局,这一期先给大家做一些基本的介绍,下一期将会带来弹性布局的实际应用
🌟 「弹性布局」揭秘:为什么这能拯救你的CSS人生?
——从“挤到怀疑人生”到“优雅排版”的魔法之路
如果你是 CSS 新手,是否经历过这些崩溃瞬间?👇
- 想让几个
div
水平排列?结果它们要么叠罗汉,要么撑爆容器… - 试图垂直居中一个按钮?写了 10 行代码,结果它在 IE 里离家出走…
- 用
float
做两栏布局?稍不留神,下一部分内容就莫名消失…
面试官最喜欢问的问题:如何使一个元素居中?
ok,这是我们常见的一个问题,能很好的说明我们为什么要学习flex布局。
常规做法:
如果不利用flex布局实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
position: relative; /* 父容器相对定位 */
width: 300px;
height: 200px;
border: 2px dashed #666;
}
.box {
position: absolute; /* 子元素绝对定位 */
top: 50%; /* 顶部定位到50% */
left: 50%; /* 左侧定位到50% */
transform: translate(-50%, -50%); /* 往回挪自身50% */
width: 100px;
height: 50px;
background: coral;
}
</style>
</head>
<body>
<div class="container">
<div class="box">我要居中!</div>
</div>
</body>
</html>
效果如下:
(当然里面的文字不需要在意,我们的目的是使得中间橙色的box居中)
不使用flex布局,则我们选用position的relative和absolute,再利用top和left将子元素左上角定位于距离父元素左上角的50%距离处,最后利用transform:translate(-50%,-50%) 将元素自身向左向上移动自身宽高的50%,达成了居中效果。
看到这你可能会说:主播主播!你的position定位实在是太吃操作了,有没有更简单更好的方法呢?
我只能回答:有的兄弟,有的!我们现在是有bear来!

接下来请看flex布局做法:
Flex布局做法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
display: flex;
width: 300px;
height: 200px;
border: 2px dashed #666;
justify-content: center;
align-items: center;
}
.box {
width: 100px;
height: 50px;
background: coral;
}
</style>
</head>
<body>
<div class="container">
<div class="box">我要居中!</div>
</div>
</body>
</html>
OK,除去没用的宽高等一系列东西,我们实现元素居中只需要三行代码:
.container{
display:flex;
justify-content: center;
align-items: center;
}
And.......Boom!!!!!!!!!!!!!
效果是不是和之前那一大堆一样了~~~
下面让我们来开始认识一下flex布局吧!
Flex布局是个什么东西?
其为CSS3的一种新的布局方式,弹性盒子主要由弹性容器(Flex-container) 和 弹性子元素(Flex-item) 组成。
容器通过设置display属性的值为flex将其定义为弹性容器
默认在弹性容器中的内容都横向摆放,这也是我们利用Flex布局的主要目的!!!
<style>
.container{
display:flex; /*这就是把container设置成了弹性容器
}
</style>
<div class='container'>
<div class='box'>
</div>
<div>
注意:我们一定要分清楚容器属性和元素属性,容器属性是在容器上使用的,元素属性是在元素上用的。
容器属性
总览:
1.flex-direction
2.flex-wrap
3.flex-flow (1,2的简写形式)
4.justify-content
5.align-items
6.align-content
1.flex-direction
flex-direction:规定容器内子元素的排列方向
2.flex-wrap
flex-wrap:决定元素放不下了是否换行
空间被挤压前:
空间被挤压后:
注意:wrap-reverse的挤压是会令元素逐个向上,空间缩小,先挤压 7,再是6,5,4.....依次向上挤压换行。
3.flex-flow
其用法非常简单
.container{
display:flex;
flex-flow: column wrap;
/* 第一个变量为排列方向,第二个变量为换行方式
}
4.justify-content
justify-content:定义了内部元素在主轴(main-axis) 上的对齐方式
justify-content还有好多属性,这里就不一一列举了,因为常用的属性基本就这么多了。
5.align-items
align-items:定义属性项目在交叉轴(Cross axis)上如何对齐
(交叉轴与主轴垂直)
关于stretch:
当交叉轴为y轴时,如果项目的高度没有设置,那么项目就会竖直拉伸铺满交叉轴。(如上)
当交叉轴为x轴时,如果项目的宽度没有设置,那么项目就会水平拉伸铺满交叉轴。(如下)
💥 前方核能警告:Flexbox 主轴/交叉轴大逃杀!新手必看!
🚨 Alert! Alert! 🚨
你以为 justify-content
永远只管“横着排”,align-items
只管“竖着排”?Too young, too simple!
Flexbox 其实是个“魔法转盘”,它的主轴方向会被 flex-direction
一键反转!如果你搞不清主次,你的布局就会像没放盐的泡面——毫无味道,还很难受!
如果你仔细观察一下,你会发现我对于justify-content和align-items的描述是主轴和交叉轴,而不是x轴和y轴,这是因为不同的排列方式会造成主轴和交叉轴的不同,也就是说flex-direction会改变主轴和交叉轴,使得justify-content和align-items效果不同。
🧠 生存指南:1 秒搞懂主轴 vs. 交叉轴
设置 flex-direction | 主轴方向 | justify-content 管谁? | align-items 管谁? |
---|---|---|---|
row (默认) |
→ 横的 | 水平排列 | 垂直对齐 |
column |
↓ 竖的 | 垂直排列 | 水平对齐 |
🎮 终极试炼(测测你的 Flexbox 求生技能)
.container {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
}
问题: 这些container中的子元素会怎么排?
- A. 水平拉伸 + 垂直贴底 ✅(恭喜,你活下来了!)
- B. 垂直拉伸 + 水平贴右 ❌(抱歉,你已被 Flexbox 吞噬…)
6.align-content
align-content
属性定义了浏览器如何沿着Flexbox容器的交叉轴分配多行Flex项目之间的空间。该属性在多行Flex容器(设置了flex-wrap: wrap
)中才会生效。
总结一下,这个属性就是沿着交叉轴来的,下面是Html的代码,大家可以自行去CV观察一下具体的效果。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flexbox align-content属性详解</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
max-width: 1000px;
margin: 0 auto;
padding: 20px;
background-color: #f9f9f9;
}
h1, h2 {
color: #2c3e50;
}
h1 {
border-bottom: 2px solid #3498db;
padding-bottom: 10px;
}
.property-card {
background: white;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
padding: 20px;
margin-bottom: 30px;
}
.demo-container {
border: 2px dashed #7f8c8d;
height: 200px;
display: flex;
flex-wrap: wrap;
margin: 20px 0;
background-color: #f1f1f1;
}
.demo-item {
width: 80px;
height: 50px;
background-color: #3498db;
color: white;
display: flex;
align-items: center;
justify-content: center;
margin: 5px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.code {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
font-family: 'Courier New', Courier, monospace;
overflow-x: auto;
margin: 10px 0;
}
.note {
background-color: #fffde7;
padding: 15px;
border-left: 4px solid #ffd600;
margin: 15px 0;
}
.warning {
background-color: #ffebee;
padding: 15px;
border-left: 4px solid #f44336;
margin: 15px 0;
}
.property-description {
margin-bottom: 20px;
}
.property-values {
margin-top: 20px;
}
.value-item {
margin-bottom: 40px;
}
.flex-direction-info {
background-color: #e3f2fd;
padding: 15px;
border-left: 4px solid #2196f3;
margin: 15px 0;
}
</style>
</head>
<body>
<h1>Flexbox中的align-content属性详解</h1>
<div class="property-card">
<h2>align-content属性介绍</h2>
<div class="property-description">
<p><code>align-content</code>属性定义了浏览器如何沿着Flexbox容器的交叉轴分配多行Flex项目之间的空间。该属性在多行Flex容器(设置了<code>flex-wrap: wrap</code>)中才会生效。</p>
<div class="code">
.container {<br>
display: flex;<br>
flex-wrap: wrap;<br>
align-content: stretch; /* 默认值 */<br>
}
</div>
<div class="note">
<strong>注意:</strong> <code>align-content</code>与<code>align-items</code>不同:
<ul>
<li><code>align-items</code>控制单行内项目在交叉轴上的对齐</li>
<li><code>align-content</code>控制多行之间在交叉轴上的空间分布</li>
</ul>
</div>
<div class="flex-direction-info">
<p><strong>主轴与交叉轴的关系:</strong></p>
<ul>
<li>当<code>flex-direction: row</code>(默认)时,主轴是水平的,交叉轴是垂直的</li>
<li>当<code>flex-direction: column</code>时,主轴是垂直的,交叉轴是水平的</li>
</ul>
<p>这意味着<code>align-content</code>的效果会根据Flexbox的方向而变化!</p>
</div>
</div>
<div class="property-values">
<h3>align-content的可取值</h3>
<!-- stretch -->
<div class="value-item">
<h4>1. stretch (默认值)</h4>
<p>项目被拉伸以填满容器。没有指定交叉轴尺寸的项目将被拉伸以占据剩余空间。</p>
<div class="code">align-content: stretch;</div>
<div class="demo-container" style="align-content: stretch;">
<div class="demo-item">1</div>
<div class="demo-item">2</div>
<div class="demo-item">3</div>
<div class="demo-item">4</div>
<div class="demo-item">5</div>
<div class="demo-item">6</div>
</div>
<div class="warning">
<strong>注意:</strong> 如果项目设置了交叉轴尺寸(如height或width,取决于主轴方向),stretch将不生效。
</div>
</div>
<!-- flex-start -->
<div class="value-item">
<h4>2. flex-start</h4>
<p>项目在交叉轴起点对齐。第一行紧贴容器边缘,后续每行在前一行下方排列。</p>
<div class="code">align-content: flex-start;</div>
<div class="demo-container" style="align-content: flex-start;">
<div class="demo-item">1</div>
<div class="demo-item">2</div>
<div class="demo-item">3</div>
<div class="demo-item">4</div>
<div class="demo-item">5</div>
<div class="demo-item">6</div>
</div>
<p>这种对齐方式在垂直方向上不会有多行之间额外间距的分配。</p>
</div>
<!-- flex-end -->
<div class="value-item">
<h4>3. flex-end</h4>
<p>项目在交叉轴终点对齐。第一行放在容器底部,其他行在上面排列。</p>
<div class="code">align-content: flex-end;</div>
<div class="demo-container" style="align-content: flex-end;">
<div class="demo-item">1</div>
<div class="demo-item">2</div>
<div class="demo-item">3</div>
<div class="demo-item">4</div>
<div class="demo-item">5</div>
<div class="demo-item">6</div>
</div>
<p>适用于需要内容在底部对齐的情况。</p>
</div>
<!-- center -->
<div class="value-item">
<h4>4. center</h4>
<p>项目在交叉轴中间对齐。所有行作为一组居中,容器会在上方和下方有相同的间距。</p>
<div class="code">align-content: center;</div>
<div class="demo-container" style="align-content: center;">
<div class="demo-item">1</div>
<div class="demo-item">2</div>
<div class="demo-item">3</div>
<div class="demo-item">4</div>
<div class="demo-item">5</div>
<div class="demo-item">6</div>
</div>
<p>这是实现垂直居中的有效方法。</p>
</div>
<!-- space-between -->
<div class="value-item">
<h4>5. space-between</h4>
<p>项目在交叉轴上均匀分布,第一行在起点,最后一行在终点,其余行之间距离相等。</p>
<div class="code">align-content: space-between;</div>
<div class="demo-container" style="align-content: space-between;">
<div class="demo-item">1</div>
<div class="demo-item">2</div>
<div class="demo-item">3</div>
<div class="demo-item">4</div>
<div class="demo-item">5</div>
<div class="demo-item">6</div>
</div>
<div class="note">
<strong>注意:</strong> 如果只有一行,效果和flex-start相同。
</div>
</div>
<!-- space-around -->
<div class="value-item">
<h4>6. space-around</h4>
<p>项目在交叉轴上均匀分布,每行周围分配相等的空间,因此行与行之间的空间是行与边缘空间的两倍。</p>
<div class="code">align-content: space-around;</div>
<div class="demo-container" style="align-content: space-around;">
<div class="demo-item">1</div>
<div class="demo-item">2</div>
<div class="demo-item">3</div>
<div class="demo-item">4</div>
<div class="demo-item">5</div>
<div class="demo-item">6</div>
</div>
<p>适合需要均衡空间分布的情况。</p>
</div>
<!-- space-evenly -->
<div class="value-item">
<h4>7. space-evenly</h4>
<p>项目在交叉轴上均匀分布,所有空间(包括边缘)的大小相等。</p>
<div class="code">align-content: space-evenly;</div>
<div class="demo-container" style="align-content: space-evenly;">
<div class="demo-item">1</div>
<div class="demo-item">2</div>
<div class="demo-item">3</div>
<div class="demo-item">4</div>
<div class="demo-item">5</div>
<div class="demo-item">6</div>
</div>
<p>创建完全对称的空间分布,各间距完全一致。</p>
</div>
</div>
<div class="note">
<h3>浏览器支持情况</h3>
<p><code>align-content</code>在所有现代浏览器中都有很好的支持:</p>
<ul>
<li>Chrome 57+ (完全支持)</li>
<li>Firefox 52+ (完全支持)</li>
<li>Safari 10.1+ (完全支持)</li>
<li>Edge 16+ (完全支持)</li>
<li>Opera 44+ (完全支持)</li>
</ul>
<p>对于旧版浏览器,可能需要添加浏览器前缀。</p>
</div>
<div class="warning">
<h3>常见错误</h3>
<p>使用<code>align-content</code>时常犯的错误:</p>
<ol>
<li>忘记设置<code>flex-wrap: wrap</code> - 没有多行时<code>align-content</code>不会生效</li>
<li>没有设置容器高度 - 交叉轴方向没有限制时,效果不明显</li>
<li>混淆<code>align-content</code>和<code>align-items</code></li>
</ol>
</div>
<div class="note">
<h3>最佳实践</h3>
<ul>
<li>明确设置<code>flex-wrap</code>属性</li>
<li>为容器设置明确的交叉轴尺寸(高度或宽度,取决于方向)</li>
<li>考虑使用<code>gap</code>属性来增加行与行之间的间距(现代浏览器支持)</li>
<li>在需要特殊对齐效果时才使用<code>align-content</code>,默认值(stretch)通常就有良好的表现</li>
</ul>
</div>
</div>
</body>
</html>
元素属性
1.order
2.flex-grow
3.flex-shrink
4.flex-basis
5.flex(2,3,4的简写形式)
6.align-self
注意哦!我们这是元素属性!是写在 item上的,不是container
哈~
1.order
order决定了容器内部项目的排列顺序,数值越小,排列越靠前,默认为0 正常情况:
赋值后:
可以看到order=-1的box在最前面,后面依次按照数值排列。
使用场景: 当需要改变项目的视觉顺序而不修改DOM结构时非常有用。例如响应式布局中,不同屏幕尺寸下可能需要不同的项目顺序。
注意: 虽然order可以改变视觉顺序,但不会影响DOM顺序,因此对于屏幕阅读器和键盘导航的顺序不会改变,可能会导致可访问性问题。
关于DOM,我们会在以后的JavaScript中讲解~ 埋一个小坑啦(๑•̀ㅂ•́)و✧
2.flex-grow
flex-grow:定义了容器内部项目放大的能力(按剩余的空间比例分配),默认值为0,即如果存在剩余空间也不会放大。
如果分别给这3个box设置flex-grow:0,则这3个box都不会放大,
如果分别给这几个box设置不同的数字,比如: flex-grow:1 , flex-grow:2, flex-grow:3,
那么这3个box将会根据剩余空间大小,按照1:2:3的比例来分配空间。
3.flex-shrink
flex-shrink:定义了项目的缩小能力,即在空间不足时该如何缩小
与上面的flex-grow同理,混合使用按比例缩小。
注意: flex-shrink: 0的项目可能会超出容器,导致溢出,需要配合overflow属性使用。 比如利用
overflow:hidden
来隐藏溢出的部分~
4.flex-basis
flex-basis :属性定义了在分配多余空间之前的大小,和width的表现基本一致。
注意:
1.如果同时使用
width
和flex-basis
,则flex-basis
的优先级更高一些2.flex-basis会覆盖width属性(如果主轴是水平的)。设置min-width或max-width可 以限制最终的弹性尺寸。
5.flex
flex
是flex-grow
、flex-shrink
和flex-basis
的简写属性,推荐使用这个属性而不是单独写三个分离的属性。
6.align-self
align-self
允许单独的对某个Flex项目进行交叉轴(纵轴)方向上的对齐方式设置,会覆盖align-items
的属性,
默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
结语
今天我们通过面试官最最最最喜欢的元素居中的例子(其实一共有五种解法),引入了我们今天要讲的flex布局和flex弹性盒子模型,一起解开了Flex的魔法卷轴,利用
.container {
display: flex;
justify-content: center;
align-items: center;
}
秒杀了一道经典面试题。现在猜猜我们下一章节要干嘛呢?
下一章我们将:
- 💻 把设计图变成会呼吸的网页
- 🧩 用Flex搭建俄罗斯方块般的组件
- 🌈 让布局像乐高一样自由拼接
- 📱 施展响应式魔法:让页面在手机和平板间自由变形!
我们将会手把手利用flex布局做出以下页面:
