使用 Flexbox 构建音乐应用布局
运用 Flexbox 拆解并构建 Catty Music 音乐应用布局
在经历了一段枯燥而严谨的学习之后,是时候来点有趣的项目了。
现在,让我们通过一个实际案例,应用你刚刚掌握的 Flexbox 技能。
我花了好几天才想出一个合适的项目。由于缺乏创意,我设计了一个专为猫咪打造的音乐应用布局,命名为“Catty Music”。也许到2036年,我们真能在火星上看到猫咪组成摇滚乐队演唱呢——:-)
以下是最终布局的效果,整个页面完全使用 Flexbox 实现。

你可以在线查看这个项目 这里
如果你在移动设备上查看,界面会略有不同。这部分内容将在本文的响应式设计章节中进一步讲解。
不过,我得坦白一件事。
我做了一件很多人认为错误的事。
我完全用 Flexbox 构建了整个页面布局。
虽然从多个角度来看,这可能并非最佳实践,但在这个场景下,这是有意为之。我的目标是向你展示 Flexbox 能做到的所有事情,并将它们全部整合在一个项目中。
如果你好奇什么情况下使用 Flexbox 是合适的,什么时候不合适,可以参考我写的这篇文章:Flexbox 很棒,但它并不总是受欢迎
好了,我已经把心里话都说出来了。现在我相信,完成这门课程后,没人会再责怪我了。
Catty Music 中的每一部分都是用 Flexbox 布局实现的——这正是为了展示它的强大能力。
那么,让我们开始动手吧!
任何合理的项目,前期规划都能有效避免后续的低效问题。
接下来,我将带你一步步构建 Catty Music 的布局。
那么,从哪里开始?
当你使用 Flexbox 构建布局时,第一步是识别哪些区域可以作为 flex 容器。然后,你可以利用 Flexbox 提供的强大对齐属性。
布局拆解
再次观察一下最终效果。
你可以将整体容器设为 flex 容器(如图中红色边框所示),并将其他部分划分为 flex 项目(项目1 和 项目2)。

这非常合理,因为项目1 包含除“页脚”(即包含音乐控制按钮的部分)外的所有内容。
你可能还不知道:一个 flex 项目本身也可以被设置为 flex 容器。
没错,这是完全可行的!
你可以嵌套任意深度(尽管建议保持在合理范围内)。
因此,有了这个新发现:
项目1(第一个 flex 项目)也可以被设为 flex 容器。
此时,侧边栏(项目1b)和主内容区(项目1a)就成为其子 flex 项目。

你还在跟上吗?
这样拆解布局,能帮你建立清晰的思维模型。
当你将来构建更复杂的布局时,这种思维方式至关重要。
你不需要像上面那样精美的图片。一张简单的手绘草图就足够了。
还记得我说过你可以无限嵌套吗?其实这里还可以再嵌套一层。
看看上方的主内容区(项目1a)。
它也可以被设为 flex 容器,用来容纳下方标出的两个区域:“项目1a—A” 和 “项目1a—B”。

你可以选择不把主内容区(项目1a)设为 flex 容器,而是直接用两个 div 来分别容纳这两个区域。
这也是可行的,因为“项目1a—A”和“项目1a—B”是垂直堆叠的。
默认情况下,div 就是垂直堆叠的——这是盒模型的基本行为。
但如果你将其设为 flex 容器,就能随时获得强大的对齐控制能力。
“Flex”中的“flex”意味着灵活。
flex 容器默认就是灵活的,某种程度上具备响应式特性。
这也可能是使用 flex 容器而非普通 div 的另一个理由——当然,具体取决于实际场景。
随着项目推进,我会继续补充一些细节。现在,是时候写代码了。
我们从基础的 HTML 结构开始:
1<!DOCTYPE html> 2 <html> 3 <head> 4 <title>Catty Music</title> 5 </head> 6 <body> 7 8 9 <main></main> <!--用于容纳应用的主要内容--> 10 11 <footer></footer> <!--用于容纳音乐控制按钮和歌曲信息--> 12 13 14 </body> 15</html>
接下来进行样式设置:
1 html, 2 body { 3 height: 100%; /*显式设置高度非常重要*/ 4 } 5 6 body { 7 display: flex; /*激活 Flexbox 功能!*/ 8 flex-direction: column; /*将 flex 项目(main 和 footer)垂直排列,而不是水平排列*/ 9 }
使用 Flexbox 的第一步是创建一个 flex 容器。
上面的代码正是如此:将 body 元素的 display 属性设为 flex。
现在,body 成为一个 flex 容器。
其 flex 项目(即项目1 和 项目2)也已明确——正如前面拆解所示。
如果你对这个概念还感到模糊,请再次回顾我之前展示的示意图。
始终以最终效果为目标,确保你的 flex 项目正确工作。
让页脚固定在底部
页脚(包含音乐控制按钮)需要固定在页面底部,而主内容区则应自动填充剩余空间。
如何实现?
1 main { 2 flex: 1 0 auto; /*填充可用空间*/ 3 } 4 5 footer { 6 flex: 0 0 90px; /*不伸缩,固定高度为 90px*/ 7 }
得益于 flex-grow 属性,让主内容区填满空间变得非常简单。只需将 flex-grow 设为 1 即可。同时,你也应将 flex-shrink 设为 0。为什么?
原因在此刻可能还不明显,因为 flex-direction 已被改变。
但在某些浏览器中,存在一个 bug:flex 项目可能会缩小到小于其内容大小。这是一种奇怪的行为。
解决此问题的方法是:将 flex-shrink 保持为 0(而不是默认值 1),并设置 flex-basis 为 auto。
相当于说:“请根据内容大小确定初始宽度,但永远不要缩小。”
使用这种简写形式,你仍能保留 flex 项目的默认行为。
当浏览器窗口调整大小时,flex 项目会自动重新计算宽度,而不是依赖 shrink 属性。flex-basis: auto 确保 flex 项目至少与自身内容或声明的宽高一样大。
请务必记住我之前拆解的 flex 简写语法。后面还会频繁使用这些简写。
现在,布局逐渐成型,添加一些样式定义间距、颜色等。
1 body { 2 display: flex; 3 flex-direction: column; 4 background-color: #fff; 5 margin: 0; 6 font-family: Lato, sans-serif; 7 color: #222; 8 font-size: 0.9em; 9 } 10 footer { 11 flex: 0 0 90px; 12 padding: 10px; 13 color: #fff; 14 background-color: rgba(61, 100, 158, .9); 15 }
目前还没有什么特别之处。现在我们有:
No configuration found for ID: c98edc14da2862bb98aed87cbc9f89d380f929f33bc5573218d51f982647d3de
看到布局正在成形,我们可以让它变得更美观。
更新 HTML 文档:
1<main> 2 <aside> <!--代表侧边栏,内部包含 Font Awesome 图标--> 3 <i class="fa fa-bars"></i> 4 <i class="fa fa-home"></i> 5 <i class="fa fa-search"></i> 6 <i class="fa fa-volume-up"></i> 7 <i class="fa fa-user"></i> 8 <i class="fa fa-spotify"></i> 9 <i class="fa fa-cog"></i> 10 <i class="fa fa-soundcloud"></i> 11 </aside> 12 13 <section class="content"> <!--此部分容纳除侧边栏外的所有内容--> 14 </section> 15 16</main>
上面的代码已经很清晰。
图标使用的是流行的 Font Awesome 库。
只需添加对应的 CSS 类即可显示所需图标。这就是我在 aside 标签中所做的。
如前所述,上方的“main”部分也将设为 flex 容器。侧边栏(aside)和内容区(section)将成为其 flex 项目。
1 main { 2 flex: 1 0 auto; /*原本是 flex 项目*/ 3 display: flex; /*现在变成 flex 容器,包含侧边栏和内容区两个 flex 项目*/ 4 }
太棒了,越来越有趣了,对吧?
现在,主内容区已成为 flex 容器。接下来处理它的其中一个 flex 项目:侧边栏。
这里有个巧妙的设计。
侧边栏中的图标是垂直堆叠的。你可以将 aside 设为 flex 容器,设置 flex-direction 使其垂直排列并居中对齐。具体如下:
1 aside { 2 flex: 0 0 40px; /*作为 flex 项目:不伸缩,固定宽度 40px*/ 3 display: flex; /*现在是 flex 容器,可控制子元素布局*/ 4 flex-direction: column; /*让子元素垂直排列,覆盖默认方向*/ 5 justify-content: space-around; /*方向改变后,该属性作用于垂直方向*/ 6 align-items: center; /*方向改变后,影响水平方向对齐*/ 7 background-color: #f2f2f2; /*让外观更美观*/ 8 } 9 10 /*图标字体大小*/ 11 aside i.fa { 12 font-size: 0.9em; 13 }
我已在代码中做了详细注释,现在一切看起来都井然有序。
仅用几行代码,布局就变得整洁美观。
代码简洁,没有混乱的 hack。
No configuration found for ID: 67db4aa6cdaeb09ec096db792ccd7bbf4edd659598538c9e444380438af60523
为主内容区添加内容
主内容区目前为空,但别忘了它是第二个 flex 项目,侧边栏是第一个。
往里面加入一些内容。你觉得怎么样?可以再看一下最终项目的效果,以免偏离目标方向。更重要的是,这有助于理解接下来的代码。
1 2 3 4 5 6 7 8 9 CattyBoard 100单曲排行榜 (11.06.36) 10 未知艺术家 11 2016 . 排行榜 . 100首歌曲 12 13 14 15 播放全部 16 添加到 17 更多 18 19 20 21 22 23 24 25 1. One Dance 26 Crake feat CatKid & Cyla 27 2:54 28 CATTY CLOUD SYNC 29 30 31 32 2. Panda 33 Cattee 34 4:06 35 CATTY CLOUD SYNC 36 37 38 39 3. Can't Stop the Feeling! 40 Catin Cimberlake 41 3:56 42 CATTY CLOUD SYNC 43 44 45 46 4. Work From Home 47 Cat Harmony feat Colla 48 3:34 49 CATTY CLOUD SYNC 50 51 52
嗯,这次加的内容比上次多了一些,但结构依然简单。
我向空的内容区添加了一个 div,用于展示专辑封面和相关信息。至于无序列表呢?
ul 包含了专辑中的所有歌曲。每首歌的标题、歌手、时长和“Catty Cloud Sync”标签都放在独立的 <p> 标签中。
那么,接下来要做什么?看看我做了什么,你能猜到怎么实现吗?
首先,你应该将主内容区设为 flex 容器:
1.content { 2 display: flex; 3 flex: 1 0 auto; /*确保该区域能填满可用空间*/ 4 flex-direction: column; 5}
同时,处理它的 flex 项目:
1.music-head { 2 flex: 0 0 280px; /*同理:不伸缩,固定高度 280px*/ 3 display: flex; 4 padding: 40px; 5 background-color: #4e4e4e; 6} 7 8.music-list { 9 flex: 1 0 auto; 10 list-style-type: none; 11 padding: 5px 10px 0px; 12}
.music-head 包含专辑封面和其他专辑信息。
同样规则:不伸缩,固定高度 280px。
高度?不是宽度?是的!
因为父级容器的 flex-direction 已经改变。
哦,你稍后还需要把这个区域设为 flex 容器。所以记得加上 display: flex。
.music-list 包含歌曲列表,它将与 .music-head 共享剩余空间。
目前看起来还不够美观,但只要你还在坚持,就已经做得很好了。
给你点赞!
No configuration found for ID: 268918f323c4f6efaeb495d114996b852d8776843bd5d86b00c69c7eef78f6f2
现在有几个问题:
1. 歌曲列表看起来很糟糕。

2. 专辑信息区域的文字排版也很难看。

现在,我来一步步帮你解决这些问题。
以下是推荐的解决方案:
处理歌曲列表
每个歌曲列表包含四个 <p> 标签:歌曲名、歌手、时长、“Catty Cloud Sync”。
我们需要让这四个部分在同一行内均匀分布。
Flexbox 来救场!
原理与许多网格系统相同。
转换为代码:
1li { 2 display: flex; /*作用于每个包含文本的列表项*/ 3 padding: 0 20px; 4 min-height: 50px; 5} 6 7li p { 8 flex: 0 0 25%; /*这才是关键*/ 9}
你看到 <p> 标签的变化了吗?
flex: 0 0 25%
“不伸缩,每个 <p> 占据可用空间的 25%”。
空间被平均分配给每个段落。
No configuration found for ID: 5a1411bdce41cd9ca7814639c88fcfd1042cb5bd53a000a4cbd6110ba7d53e1e
再稍作美化,给列表添加交替背景色,并处理“Catty Cloud Sync”标签:
1li span.catty-cloud { 2 border: 1px solid black; 3 font-size: 0.6em; 4 padding: 3px; 5} 6 7li:nth-child(2n) { 8 background-color: #f2f2f2; 9}
太棒了!你正逐步掌握 Flexbox 的精髓!现在应该得到这样的效果:
No configuration found for ID: f457732b95bedce25fc3327d25b3383f2f88c7ed79cd2ce09fef9d372f95a646
这种技术的应用
这种技巧非常实用。你可以用它创建非均等区域,比如两列布局。
一列占 60% 空间,另一列占 40%。
.first-section: 0 0 60%;
.second-section: 0 0 40%;
你甚至可以用它来构建网格系统。
现在,解决第二个问题。
让专辑信息文字更美观
下面是一些简单的样式调整:
1.catty-music{ 2 flex: 1 0 auto; 3 display: flex; 4 flex-direction: column; 5 font-weight: 300; 6 color: #fff; 7 padding-left: 50px; 8} 9 10.catty-music div:nth-child(1){ 11 margin-bottom: auto; 12} 13 14.catty-music div:nth-child(2){ 15 margin-top: 0; 16} 17 18.catty-music div:nth-child(2) i.fa{ 19 font-size: 0.9em; 20 padding: 0 0.7em; 21 font-weight: 300; 22} 23.catty-music div:nth-child(1) p:first-child{ 24 font-size: 1.8em; 25 margin: 0 0 10px; 26} 27 28.catty-music div:nth-child(1) p:not(:first-child){ 29 font-size: 0.9em; 30 margin: 2px 0; 31}
搞定!
你基本完成了。
No configuration found for ID: 84a08715e884ce6808636e2f7197d38acd48ac6c49dc9a32bc64a9ab41eaf342
快速练习
我把页脚留给你作为练习。
试着自己修复页脚。只需运用同样的技巧。你一定能做到!
如果卡住了,可以查看 Catty Music 的完整源码(最后一课会有链接)。
你也可以将整个页脚拆分为多个 flex 项目,然后开始处理。

哇!真不敢相信你走到了这一步。太棒了!你现在已经是 Flexbox 小达人了。
接下来,你将看到 Flexbox 如何助力响应式设计。