普通视图

发现新文章,点击刷新页面。
昨天 — 2025年5月23日首页

🎯 《Flex布局奇妙历险:从菜鸟到面试王者!》

作者 MrSkye
2025年5月23日 17:22

前言

上一期我们学习了关于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>

效果如下:

image.png

(当然里面的文字不需要在意,我们的目的是使得中间橙色的box居中)

不使用flex布局,则我们选用position的relative和absolute,再利用top和left子元素左上角定位于距离父元素左上角的50%距离处,最后利用transform:translate(-50%,-50%) 将元素自身向左向上移动自身宽高的50%,达成了居中效果。

看到这你可能会说:主播主播!你的position定位实在是太吃操作了,有没有更简单更好的方法呢?

我只能回答:有的兄弟,有的!我们现在是有bear来!

微信图片_20250430194704.jpg

接下来请看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!!!!!!!!!!!!!

image.png 效果是不是和之前那一大堆一样了~~~

下面让我们来开始认识一下flex布局吧!

Flex布局是个什么东西?

其为CSS3的一种新的布局方式,弹性盒子主要由弹性容器(Flex-container)弹性子元素(Flex-item) 组成。

容器通过设置display属性的值为flex将其定义为弹性容器

默认在弹性容器中的内容都横向摆放,这也是我们利用Flex布局的主要目的!!!

<style>
.container{
display:flex;  /*这就是把container设置成了弹性容器
}
</style>

<div class='container'>

<div class='box'>

</div>

<div>

image-20250511110110761.png

注意:我们一定要分清楚容器属性元素属性,容器属性是在容器上使用的,元素属性是在元素上用的。

容器属性

总览:

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:规定容器内子元素的排列方向

image.png

2.flex-wrap

flex-wrap:决定元素放不下了是否换行

空间被挤压前: image.png空间被挤压后:

image.png 注意:wrap-reverse的挤压是会令元素逐个向上,空间缩小,先挤压 7,再是6,5,4.....依次向上挤压换行。

3.flex-flow

其用法非常简单

.container{
display:flex;
flex-flow: column wrap;
/* 第一个变量为排列方向,第二个变量为换行方式
}

4.justify-content

justify-content:定义了内部元素在主轴(main-axis) 上的对齐方式

image.png

image.png justify-content还有好多属性,这里就不一一列举了,因为常用的属性基本就这么多了。

5.align-items

align-items:定义属性项目在交叉轴(Cross axis)上如何对齐

(交叉轴与主轴垂直)

image.png 关于stretch:

交叉轴为y轴时,如果项目的高度没有设置,那么项目就会竖直拉伸铺满交叉轴。(如上)

交叉轴为x轴时,如果项目的宽度没有设置,那么项目就会水平拉伸铺满交叉轴。(如下)

image.png


image.png

💥 前方核能警告: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)中才会生效。

image.png

image.png

image.png

image.png

image.png 总结一下,这个属性就是沿着交叉轴来的,下面是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>
                &nbsp;&nbsp;display: flex;<br>
                &nbsp;&nbsp;flex-wrap: wrap;<br>
                &nbsp;&nbsp;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

image-20250511110110761.png 注意哦!我们这是元素属性!是写在 item上的,不是container 哈~

1.order

order决定了容器内部项目的排列顺序,数值越小,排列越靠前,默认为0 正常情况:

image.png 赋值后:

image.png 可以看到order=-1的box在最前面,后面依次按照数值排列。

使用场景:  当需要改变项目的视觉顺序而不修改DOM结构时非常有用。例如响应式布局中,不同屏幕尺寸下可能需要不同的项目顺序。

注意: 虽然order可以改变视觉顺序,但不会影响DOM顺序,因此对于屏幕阅读器和键盘导航的顺序不会改变,可能会导致可访问性问题。

关于DOM,我们会在以后的JavaScript中讲解~ 埋一个小坑啦(๑•̀ㅂ•́)و✧

2.flex-grow

flex-grow:定义了容器内部项目放大的能力(按剩余的空间比例分配),默认值为0,即如果存在剩余空间也不会放大

image.png 如果分别给这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:定义了项目的缩小能力,即在空间不足时该如何缩小

image.png 与上面的flex-grow同理,混合使用按比例缩小。

注意:  flex-shrink: 0的项目可能会超出容器,导致溢出,需要配合overflow属性使用。 比如利用overflow:hidden来隐藏溢出的部分~

4.flex-basis

flex-basis :属性定义了在分配多余空间之前的大小,和width的表现基本一致。

image.png

注意:

 1.如果同时使用widthflex-basis,则flex-basis的优先级更高一些

 2.flex-basis会覆盖width属性(如果主轴是水平的)。设置min-width或max-width可   以限制最终的弹性尺寸。

5.flex

flexflex-growflex-shrinkflex-basis的简写属性,推荐使用这个属性而不是单独写三个分离的属性。

image.png

6.align-self

align-self允许单独的对某个Flex项目进行交叉轴(纵轴)方向上的对齐方式设置,会覆盖align-items的属性, 默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

image.png

结语

今天我们通过面试官最最最最喜欢的元素居中的例子(其实一共有五种解法),引入了我们今天要讲的flex布局和flex弹性盒子模型,一起解开了Flex的魔法卷轴,利用

.container { 
display: flex; 
justify-content: center;
align-items: center; 
}

秒杀了一道经典面试题。现在猜猜我们下一章节要干嘛呢?

dk2.jpg 下一章我们将:

  • 💻 把设计图变成会呼吸的网页
  • 🧩 用Flex搭建俄罗斯方块般的组件
  • 🌈 让布局像乐高一样自由拼接
  • 📱 施展响应式魔法:让页面在手机和平板间自由变形!

我们将会手把手利用flex布局做出以下页面:

image.png 相信我,绝对是婴儿向教程,包教包会~
❌
❌