第 5 章 · Flexbox 弹性布局
本章目标:掌握 Flexbox 一维布局模型,用 academy-demo 课程展示小站实现导航栏、课程卡片行与垂直居中,并理解主轴/交叉轴、伸缩与换行的工程化用法。
学时建议:2 小时(含 40 分钟跟练与自检)
前置:frontend-web ch01~04(HTML 语义、CSS 选择器与盒模型);能在 DevTools 中查看元素的 display 与盒模型。
5.1 Flexbox 在 academy-demo 中的位置
| 页面区域 | Flex 角色 | 典型属性 |
|---|---|---|
顶栏 .site-header | 横向工具栏 | justify-content: space-between |
主导航 .site-nav | 链接横排 | gap、align-items: center |
课程行 .course-row | 可换行卡片流 | flex-wrap: wrap |
单张卡片 .course-card | 内部纵向排版 | flex-direction: column |
Hero 区 .hero | 垂直水平居中 | justify-content + align-items |
专业原则:一维排列优先 Flexbox;整页二维分区见 ch06 Grid。样式写入 css/layout.css。
5.2 启用 Flex 与坐标系
在父元素(flex container)上设置 display: flex,直接子元素成为 flex item。
.container { display: flex; }
flex-direction | 主轴 | 交叉轴 |
|---|---|---|
row(默认) | 左 → 右 | 上 ↓ 下 |
column | 上 ↓ 下 | 左 → 右 |
记忆口诀:justify 管主轴,align 管交叉轴(row 时 justify 常管水平,align 管垂直)。
5.3 容器与子项属性速查
| 属性 | 常用值 | 作用 |
|---|---|---|
justify-content | flex-start / center / space-between | 主轴对齐 |
align-items | stretch / center / flex-start | 交叉轴单行对齐 |
flex-wrap | wrap | 换行 |
gap | 16px | 子项间距 |
子项 flex 简写(grow shrink basis):
| 写法 | academy-demo 场景 |
|---|---|
flex: 1 | 主内容区撑满剩余空间 |
flex: 0 0 240px | 固定宽侧栏 |
flex: 1 1 280px | 课程卡片:可伸缩,基础 280px |
.course-card {
flex: 1 1 280px;
max-width: 100%;
}
5.4 实战一:academy-demo 顶栏导航
<header class="site-header">
<a class="site-logo" href="/">
<img src="assets/logo.svg" alt="贤紫技术学院" width="32" height="32">
<span>academy-demo</span>
</a>
<nav class="site-nav" aria-label="主导航">
<a href="#courses" class="site-nav__link site-nav__link--active">课程</a>
<a href="#paths" class="site-nav__link">学习路径</a>
<a href="#about" class="site-nav__link">关于</a>
</nav>
<div class="site-actions">
<button type="button" class="btn btn-outline">登录</button>
<button type="button" class="btn btn-primary">免费试听</button>
</div>
</header>
/* layout.css */
.site-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
padding: 12px clamp(16px, 4vw, 32px);
border-bottom: 1px solid var(--color-border, #e2e8f0);
background: var(--color-surface, #fff);
flex-wrap: wrap;
}
.site-logo {
display: inline-flex;
align-items: center;
gap: 10px;
font-weight: 700;
text-decoration: none;
color: inherit;
flex-shrink: 0;
}
.site-nav {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
justify-content: center;
}
.site-nav__link {
padding: 8px 14px;
border-radius: 999px;
text-decoration: none;
color: var(--color-muted, #64748b);
}
.site-nav__link--active {
color: var(--color-primary, #e91e8c);
background: rgba(233, 30, 140, 0.08);
}
.site-actions {
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
}
@media (max-width: 720px) {
.site-header { justify-content: center; }
.site-nav {
order: 3;
flex-basis: 100%;
justify-content: center;
flex-wrap: wrap;
}
}