第八天:Flex 进阶 — 让每个项目有自己的"个性"
蜗牛往上爬 · 前端工业可视化学习笔记 第 8 篇
上一篇学会了用容器属性让所有项目"整齐排队"。今天学项目属性——让每个项目有自己的"个性":有的撑满剩余空间、有的固定宽度、有的单独控制对齐。这是 Flex 从"能用"到"好用"的关键一步。
目录
一、项目属性速查
容器属性控制"整体",项目属性控制"个别":
.item {
/* ① 放大比例:剩余空间怎么分 */
flex-grow: 0; /* 默认 0(不放大),设为 1 会均分剩余空间 */
/* ② 缩小比例:空间不足时谁先缩小 */
flex-shrink: 1; /* 默认 1(允许缩小),0 表示不缩小 */
/* ③ 基础大小:分配剩余空间前的初始尺寸 */
flex-basis: auto; /* 默认 auto(由内容决定),可设具体值如 200px */
/* ④ 简写(推荐!) */
flex: 0 1 auto; /* grow shrink basis */
/* ⑤ 单独控制自己的交叉轴对齐 */
align-self: auto; /* 覆盖容器的 align-items,只影响自己 */
/* ⑥ 排列顺序:数值越小越靠前 */
order: 0; /* 默认 0,可设负数 */
}
二、flex-grow:瓜分剩余空间
flex-grow 是 Flex 最常用的项目属性,它决定了"剩余空间怎么分"。
图解
容器宽 600px,三个项目内容各 100px,剩余空间 300px
不放大(flex-grow: 0):
[100px] [100px] [100px] ············300px 空白············
全部放大(flex-grow: 1):
[ 200px ] [ 200px ] [ 200px ] 剩余空间均分
第一项放大(flex-grow: 1),其余不放大:
[ 400px ] [100px] [100px] 第一项独占剩余空间
按比例放大(flex-grow: 2, 1, 1):
[ 250px ] [ 175px ] [ 175px ] 2:1:1 分配
代码示例
/* 三列等宽(最常用) */
.col { flex: 1; }
/* 第一列占 2 份,其余各占 1 份 */
.col-1 { flex: 2; }
.col-2 { flex: 1; }
.col-3 { flex: 1; }
三、flex 简写:四个常用组合
flex 是 flex-grow、flex-shrink、flex-basis 的简写,记住这四个组合就够用了:
flex: 1; /* = flex: 1 1 0% 均分剩余空间,最常用 */
flex: auto; /* = flex: 1 1 auto 根据内容比例均分 */
flex: none; /* = flex: 0 0 auto 不伸缩,保持内容大小 */
flex: initial; /* = flex: 0 1 auto 默认值 */
场景对照
经典组合:侧边栏 + 主内容
.container { display: flex; }
/* 侧边栏固定 240px,不伸缩 */
.sidebar { flex: 0 0 240px; }
/* 主内容区撑满剩余空间 */
.main { flex: 1; }
四、align-self 与 order
4.1 align-self:单独控制某个项目
/* 所有项目顶对齐,但第三个项目底对齐 */
.container { align-items: flex-start; }
.item-3 { align-self: flex-end; }
场景:导航栏中,Logo 垂直居中,但右侧的用户头像想顶部对齐。
4.2 order:调整排列顺序
/* 默认所有项目 order: 0,按 HTML 顺序排列 */
/* 第二个项目排到第一个 */
.item-2 { order: -1; }
/* 第一个项目排到最后 */
.item-1 { order: 1; }
场景:移动端侧边栏在下,桌面端侧边栏在左——用 order 调整,不改变 HTML。
五、动手练:顶部导航 + 内容区页面
用 Flex 做一个完整页面:顶部导航 + 下方(侧边栏 + 主内容 + 卡片列表)。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>顶部导航 + 内容区</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Microsoft YaHei", sans-serif;
display: flex;
flex-direction: column; /* 垂直排列:导航 → 内容 */
min-height: 100vh;
}
/* 顶部导航栏 */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background: #1a3a5c;
color: white;
padding: 0 40px;
height: 60px;
flex-shrink: 0; /* 不缩小 */
}
.navbar .logo {
font-size: 20px;
font-weight: bold;
}
.nav-menu {
display: flex;
list-style: none;
gap: 24px;
}
.nav-menu a {
color: #8ecae6;
text-decoration: none;
}
.nav-menu a:hover {
color: #ffb703;
}
/* 内容区 */
.content {
display: flex;
flex: 1; /* 撑满导航下方空间 */
}
/* 侧边栏:固定宽度 */
.sidebar {
flex: 0 0 220px; /* 不放大、不缩小、固定 220px */
background: #e9ecef;
padding: 20px;
}
.sidebar h3 {
color: #1a3a5c;
margin-bottom: 16px;
font-size: 16px;
}
.sidebar ul {
list-style: none;
}
.sidebar li {
padding: 8px 0;
color: #555;
cursor: pointer;
}
.sidebar li:hover {
color: #1a3a5c;
}
/* 主内容区:撑满剩余空间 */
.main-content {
flex: 1; /* 占据剩余空间 */
padding: 20px;
}
.main-content h2 {
color: #1a3a5c;
margin-bottom: 16px;
}
/* 卡片网格 */
.card-grid {
display: flex;
flex-wrap: wrap; /* 自动换行 */
gap: 16px;
}
.card {
width: 280px;
background: white;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.card h4 {
color: #1a3a5c;
margin-bottom: 8px;
}
.card p {
color: #555;
font-size: 14px;
line-height: 1.6;
}
</style>
</head>
<body>
<nav class="navbar">
<div class="logo">智慧工厂监控中心</div>
<ul class="nav-menu">
<li><a href="#">设备监控</a></li>
<li><a href="#">产量统计</a></li>
<li><a href="#">告警中心</a></li>
<li><a href="#">系统设置</a></li>
</ul>
</nav>
<div class="content">
<aside class="sidebar">
<h3>设备分类</h3>
<ul>
<li>压缩机</li>
<li>冷却泵</li>
<li>供料机</li>
<li>传送带</li>
<li>包装机</li>
</ul>
</aside>
<main class="main-content">
<h2>设备概览</h2>
<div class="card-grid">
<div class="card">
<h4>压缩机 A</h4>
<p>温度:58℃ | 状态:运行中</p>
</div>
<div class="card">
<h4>冷却泵 B</h4>
<p>温度:32℃ | 状态:待机</p>
</div>
<div class="card">
<h4>供料机 C</h4>
<p>温度:45℃ | 状态:运行中</p>
</div>
<div class="card">
<h4>传送带 D</h4>
<p>速度:2.1m/s | 状态:运行中</p>
</div>
</div>
</main>
</div>
</body>
</html>
Flex 属性分析:
练习:照敲 → 把侧边栏的 flex: 0 0 220px 改成 flex: 0 0 300px → 把卡片改成 flex: 1 均分 → 缩窄浏览器窗口观察换行。
六、常见坑点与最佳实践
坑 1:flex: 1 和 flex: auto 的区别
/* flex: 1 = flex: 1 1 0% —— 忽略内容,纯均分 */
.item-1 { flex: 1; }
/* flex: auto = flex: 1 1 auto —— 考虑内容宽度后均分 */
.item-2 { flex: auto; }
当内容宽度差异大时,flex: 1 严格均分,flex: auto 按内容比例分。
坑 2:设了 flex-grow 但没撑满
/* 原因:容器没有剩余空间 */
/* 检查:容器是否设了固定宽度?内容是否已经撑满? */
最佳实践清单
[x] 均分用
flex: 1,固定用flex: 0 0 XXXpx[x] 记住
flex: 1是grow: 1, shrink: 1, basis: 0%[x]
align-self只影响自己,order不改变 HTML
七、这些知识在工业可视化里用在哪?
大屏布局:导航 + 侧边栏 + 主内容
/* 大屏的标准布局就是 Flex 的经典组合 */
body { display: flex; flex-direction: column; height: 100vh; }
.header { flex-shrink: 0; height: 60px; }
.content { flex: 1; display: flex; }
.sidebar { flex: 0 0 200px; }
.main { flex: 1; display: flex; flex-wrap: wrap; gap: 12px; }
响应式面板:不同宽度用不同 flex
/* 大屏:4 列,均分 */
.panel { flex: 1; }
/* 中屏:2 列,每列 380px */
.panel { flex: 0 0 380px; }
八、自测挑战 10 题
flex-grow、flex-shrink、flex-basis分别控制什么?flex: 1等价于什么?flex: none等价于什么?侧边栏固定 200px,主内容区撑满剩余空间,怎么写?
align-self和align-items有什么区别?order改变的是什么?会改变 HTML 结构吗?写出
body用 Flex 实现"导航在上、内容在下"的代码。写出"侧边栏 + 主内容区"的 Flex 代码(含
flex值)。flex-wrap: wrap配合gap能实现什么布局效果?把卡片网格的
flex-wrap去掉,缩窄窗口,观察卡片是否被压缩。用 F12 把
.sidebar的flex值从0 0 220px改成1,观察宽度变化。
加分挑战:在页面中给侧边栏的某个菜单项设 align-self: flex-end,让它沉到底部。
九、总结
今天学完,你应该能做到:
[x] 解释
flex-grow、flex-shrink、flex-basis的作用[x] 使用
flex: 1、flex: none、flex: 0 0 XXXpx等常用组合[x] 实现"侧边栏固定 + 主内容撑满"的经典布局
[x] 使用
align-self和order单独控制项目[x] 独立做出"顶部导航 + 内容区"页面
一句话带走:flex: 1 均分,flex: 0 0 240px 固定,flex-shrink: 0 不缩小——记住这三个组合,覆盖 90% 的 Flex 布局场景。
📎 本文为"蜗牛往上爬"学习博客系列 · 阶段 0(HTML+CSS)第 3 周 · 第 2 篇