编程语言研究书库

综合项目 — 一个作品集页、五个常见的坑、和一张下一步地图

综合项目 — 一个作品集页、五个常见的坑、和一张下一步地图

这一章讲三件事: 把前六章的所有工具倒进一个完整的页面,从头走一遍; 清点初学者最常踩的五个坑;给一份工具清单和下一步往哪走。 读完你能独立做出一个能在手机上看的个人作品集页,并知道继续学什么。 需要的基础:本拆解 01–06 章的全部内容——这一章没有新语法,只有组合。

1. 这一章讲什么

单项都练过了,最后的问题是:它们按什么次序合成一个真东西? 书里选的「真东西」是一个响应式个人作品集页:页头、导航、三个区块、页脚。 它在全书链条的位置:第 ⑦ 级台阶,也是终点——做完它,这本书的教学使命就完成了, 剩下的路靠工具清单和练习走下去。

2. 顶层全景:四步流水线

  ① 画结构    ── 不写代码,先列区块:页头/导航/关于我/项目/联系/页脚
  ② 写 HTML   ── 把结构落成标签;一个 viewport 声明 + 一个样式表 link + 一个字体 link
  ③ 写 CSS    ── 全局(body)→ 分区(header/section/页脚)→ 网格(项目卡)→ 细节(链接悬停)
  ④ 响应式收尾 ── @media:窄屏时导航链接改竖排

  图说:先骨架后皮肤、先整体后局部、桌面样式写完再用媒体查询往小屏收。
  四步的顺序比任何单条规则都重要。

3. 核心原理:主线例子,作品集页从头走一遍

这就是本章的主线例子——全书所有机制的汇合点。两个文件,我们按浏览器实际执行的顺序走。

第 ① 步:画结构。 原书要求先不写代码,列出页面要有哪些区块: 页头(放名字)、导航条、关于我、项目、联系、页脚1。 这个「先画后写」的顺序不是客套:结构列错了,后面全返工。

第 ② 步:HTML 骨架。 重点看 <head> 里的三行,每一行都在前面某章出现过:

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Portfolio</title>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet">
</head>
这一行它管什么哪章讲过
<meta name="viewport" content="width=device-width, initial-scale=1.0">告诉手机:「按你真实的宽度来渲染这页,别假装自己是宽屏」;缺了它,手机会用假想的宽屏布局再把页面缩小,所有媒体查询跟着失灵本章首次出现,是响应式生效的前提(06 章没提,如实标注)
<link rel="stylesheet" href="style.css">引入外部样式表01 章
Google Fonts 的 <link>引入 Poppins 字体03 章

<body> 里是每个区块一个语义标签(标签名本身说明里头装什么):<header> 装名字和导航,<section> 装三个内容区, <footer> 装版权行;导航链接用 #about 这种「页内锚点」跳到对应区块2。

第 ③ 步:CSS,从全局到局部。 原书的样式表按注释分成了几段,执行顺序反映优先级:

全局段——body 一口气定全站基调:字体 Poppins、上下外边距清零、行高 1.6、 浅灰底 #f5f5f5、深灰字 #3333。页头段——蓝底 #007acc、白字、20px 内边距、 文字居中;导航链接白字无下划线、间距 margin: 0 15px、加粗,悬停时挂回下划线4。 分区段——section 每区上下 40px、左右 20px 的内边距,max-width: 800px; margin: auto;—— 内容再宽也不超过 800px,并且在这一宽度内水平居中(04 章卡片练习里欠的原理,这里再次用上: auto 的外边距吃掉两侧剩余空间,盒子自然居中)5。

网格段——项目区是全书最讲究的一行:

.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}

repeat(3, 1fr) 的升级版:minmax(220px, 1fr) 念「每列至少 220px,有多余空间就按 1 份拉伸」, auto-fit 念「列数你浏览器自己定」—— 合起来的效果:桌面上一行尽量多塞卡片,塞不下 220px 了就把多的份额让给已有列; 窄屏时列自动减少到 2、1,不用写任何媒体查询6。 这一行是「响应式网格」的现成答案,前六章的 1fr、repeat、Grid 在这里合流。 卡片本身照搬 04 章的白底、细边、圆角、淡阴影四件套7。

第 ④ 步:响应式收尾。 唯一一段媒体查询,门槛 600px:

@media (max-width: 600px) {
  header, nav { text-align: center; }
  nav a { display: block; margin: 10px 0; }
}

窄屏时导航链接从「同一行横排」改成 display: block 独占一行竖排,间距改成上下 10px8—— 06 章的「覆盖」机理在这里最后一次出现。

浏览器加载这页的完整时间线:

时刻发生的事全书哪章的机制
1读 HTML 头部,发现 viewport 声明 → 按设备真实宽度布局本章新前提
2读两个 <link> → 下载样式表和 Poppins 字体01、03 章
3按 CSS 顺序应用规则:全局 body → 页头 → 各 section 居中 → 网格摆三卡02、04、05 章
4视口宽 ≤ 600px → 媒体查询段覆盖导航规则,链接改竖排06 章
5渲染完成:宽屏是横排导航 + 三卡网格,窄屏是竖排导航 + 单卡一列全部

「Done! You now have a responsive, styled personal portfolio page.」——原书在这一步宣告全书教学完成9。

4. 五个常见的坑(作者的判断与证据)

这一节是全书的「错题本」,五条都是经验之谈——书里没有给数据来源, 但每一条都对应着一个可以当场验证的机制,我们逐条补上机理:

坑 1:到处写死宽度。 反面 width: 800px,正面 width: 80% 或 max-width: 800px。 机理:写死的像素无视容器,小屏上必然溢出——这正是 06 章相对单位存在的理由10。

坑 2:忘记统一盒模型口径。 修法是在样式表开头写:

* { box-sizing: border-box; }

* 是「所有元素」的通配选择器;box-sizing: border-box 把全站的 width 口径 从「只量内容」改成「量到边框为止」——05 章那个「设了 100px 实际占 164px」的坑, 这一行全站封死11。这就是我们在 05 章提前埋的那笔账的还款日: 原书把它放在「常见错误」里,其实它是专业项目的默认开场。

坑 3:滥用 ID 选择器写样式。 反面 #main { ... },正面 .main { ... }。 机理:02 章讲过的层叠——ID 比类更具体,样式钉死难复用难覆盖12。

坑 4:不在手机上测。 书里给的具体工具:Chrome 开发者工具 (按 F12 → Toggle Device Toolbar)可以模拟各种屏幕宽度13。 机理:06 章的核心立场——渲染发生在读者设备上,你的屏幕不作数。

坑 5:字体和颜色贪多。 书里给的量化上限:字体最多两款;颜色一个主色 + 一个强调色 + 一个中性底色14。 这是设计约束,不是技术约束——机理是人的注意力有限,变量越少越像「设计」。

判断(我们的,不是书里的): 这五条坑的共同结构值得点破—— 坑 1、2 是机制误用(不懂盒模型和相对单位),坑 3 是架构习惯(ID 当类用), 坑 4 是验证缺失(不测就上线),坑 5 是品味问题(没有约束)。 前两条读透本书就不会再犯;后三条是习惯,要刻意练。 如果错,会错在: 如果读者做的是一次性演示页而非持续维护的项目, 坑 3、5 的代价几乎为零——「错误」的强度随项目寿命增长,小项目里它们只是风格偏好。

5. 工具清单与下一步(边界与局限)

工具清单,书里分两类15:

工具干什么用
CodePen在线写 HTML/CSS,即时预览、分享——练手不用建文件
Google Fonts免费网页字体(03 章教过用法)
Color Hunt / Coolors现成的配色方案 / 配色生成器——坑 5 的解药
MDN Web Docs最权威的 CSS 参考文档,查任何属性与取值
CSS-Tricks进阶文章;Flexbox/Grid 图解名篇的出处
Flexbox Froggy / Grid Garden两个游戏,分别练 Flexbox 和 Grid——「玩着学」

下一步方向,原书结尾点了四个名:动画与过渡、SCSS(一种给 CSS 加变量的预处理工具)、 Tailwind/Bootstrap(别人写好的样式库)、JavaScript(让页面真的能交互)16。 本书都不展开——它们每一条都够再写一本书,如实标注为不覆盖。

本章自身的局限也说清: 项目里的导航只是页内跳转(刷新即复位), 没有多页面;没有表单;图片目录标注为「可选」。它是「能展示」的页面, 还不是「能办事」的页面——后者需要 JavaScript。

6. 可带走的

本章主线例子,一行写完: 画六个区块 → HTML 头部三行(viewport + 样式表 + 字体) → CSS 从 body 全局到 Grid 项目卡(auto-fit minmax 自动收列)→ 一段 600px 媒体查询收导航 → 宽屏横排三卡、窄屏竖排单卡的作品集页。

  1. 做页面的顺序:先画结构、再写骨架、再上样式、最后响应式收尾——顺序错比语法错更贵;
  2. <meta name="viewport" ...> 是响应式的前提,缺了它手机按假宽屏渲染,媒体查询全失灵;
  3. max-width + margin: auto = 内容限宽居中,全站 section 通用;
  4. repeat(auto-fit, minmax(220px, 1fr)) = 不写媒体查询的响应式网格,列数浏览器自己算;
  5. 样式表开头写 * { box-sizing: border-box; },05 章的尺寸账从此不用算;
  6. 五个坑按性质分:机制误用(死宽度、盒模型)、架构习惯(滥用 ID)、验证缺失(不测手机)、品味(贪多);
  7. 出问题了先查 MDN;练手用 CodePen;配色没思路去 Color Hunt;布局手生去玩 Froggy 和 Garden;
  8. 下一步四方向:动画、SCSS、Tailwind/Bootstrap、JavaScript——本书只指路,不陪同。

7. 原文地图

主题原书章原文位置
先画结构(六区块)Chapter 7: Bringing It All Togethertext/08-ch07-chapter-7-bringing-it-all-together.txt:17(搜「sketch out」)
HTML 骨架与 head 三行同上text/08-ch07-chapter-7-bringing-it-all-together.txt:38(搜「viewport」) · text/08-ch07-chapter-7-bringing-it-all-together.txt:40(搜「family=Poppins」)
全局 body 样式同上text/08-ch07-chapter-7-bringing-it-all-together.txt:80(搜「Global Styles」)
导航链接与悬停同上text/08-ch07-chapter-7-bringing-it-all-together.txt:105(搜「margin: 0 15px」) · text/08-ch07-chapter-7-bringing-it-all-together.txt:113(搜「underline」)
section 限宽居中同上text/08-ch07-chapter-7-bringing-it-all-together.txt:118(搜「max-width: 800px」)
响应式网格 auto-fit minmax同上text/08-ch07-chapter-7-bringing-it-all-together.txt:136(搜「auto-fit」)
媒体查询收尾(600px)同上text/08-ch07-chapter-7-bringing-it-all-together.txt:164(搜「600px」)
项目完成宣告同上text/08-ch07-chapter-7-bringing-it-all-together.txt:179(搜「portfolio page」)
坑 1 写死宽度同上text/08-ch07-chapter-7-bringing-it-all-together.txt:189(搜「break your layout」)
坑 2 box-sizing同上text/08-ch07-chapter-7-bringing-it-all-together.txt:199(搜「box-sizing」)
坑 3 滥用 ID同上text/08-ch07-chapter-7-bringing-it-all-together.txt:208(搜「classes are flexible」)
坑 4 DevTools 设备模拟同上text/08-ch07-chapter-7-bringing-it-all-together.txt:212(搜「Toggle Device Toolbar」)
坑 5 字体颜色上限同上text/08-ch07-chapter-7-bringing-it-all-together.txt:219(搜「Max 2 fonts」)
工具清单(八件)同上text/08-ch07-chapter-7-bringing-it-all-together.txt:226(搜「CodePen」) · text/08-ch07-chapter-7-bringing-it-all-together.txt:235(搜「MDN」)
下一步四方向同上text/08-ch07-chapter-7-bringing-it-all-together.txt:293(搜「Tailwind」)

Footnotes

  1. 出处:「Chapter 7: Bringing It All Together」第 16–28 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:17,搜「sketch out」)。原文:「Before writing any code, sketch out your page layout.」列出的六件:Header、Navigation bar、About Me、Projects、Contact、Footer。 ↩

  2. 出处:「Chapter 7: Bringing It All Together」第 30–70 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:36,搜「DOCTYPE」;:48,搜「#about」)。导航三个链接:<a href="#about">、<a href="#projects">、<a href="#contact">——# 开头的页内锚点跳转到同 id 的 section。 ↩

  3. 出处:「Chapter 7: Bringing It All Together」第 80–91 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:80,搜「Global Styles」;:87,搜「line-height」)。原文 body:「font-family: 'Poppins', sans-serif; margin: 0; padding: 0; line-height: 1.6; background-color: #f5f5f5; color: #333」。 ↩

  4. 出处:「Chapter 7: Bringing It All Together」第 93–113 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:105,搜「margin: 0 15px」)。原文:「nav a { color: white; text-decoration: none; margin: 0 15px; font-weight: bold; }」;悬停挂下划线见第 113 段(搜「underline」)。 ↩

  5. 出处:「Chapter 7: Bringing It All Together」第 115–128 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:118,搜「max-width: 800px」;:120,搜「margin: auto」)。原文:「section { padding: 40px 20px; max-width: 800px; margin: auto; }」auto 外边距吃掉两侧剩余、盒子水平居中的机理,是 04 章练习悬置、本章再次使用、我们当场补的解释。 ↩

  6. 出处:「Chapter 7: Bringing It All Together」第 130–140 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:136,搜「auto-fit」)。原文:「grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px;」auto-fit/minmax 的逐词解读(列数自适应、每列至少 220px)是按定义展开的,效果是「桌面多列、窄屏自动减列、无需媒体查询」。 ↩

  7. 出处:「Chapter 7: Bringing It All Together」第 142–148 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:147,搜「box-shadow」)。原文项目卡:「background: white; padding: 20px; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.05); text-align: center」——与 04 章卡片同配方。 ↩

  8. 出处:「Chapter 7: Bringing It All Together」第 162–177 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:164,搜「600px」;:172,搜「display: block」)。原文:「@media (max-width: 600px)」「nav a { display: block; margin: 10px 0; }」。 ↩

  9. 出处:「Chapter 7: Bringing It All Together」第 179 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:179,搜「portfolio page」)。原文:「Done! You now have a responsive, styled personal portfolio page.」 ↩

  10. 出处:「Chapter 7: Bringing It All Together」第 183–189 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:189,搜「break your layout」)。原文:反面「width: 800px」,正面「width: 80% or max-width: 800px」;「Fixed widths break your layout on smaller screens.」 ↩

  11. 出处:「Chapter 7: Bringing It All Together」第 191–201 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:199,搜「box-sizing」;:201,搜「easier to manage」)。原文:「* { box-sizing: border-box; }」「This makes padding and borders easier to manage in layouts.」通配符 * 选中所有元素。 ↩

  12. 出处:「Chapter 7: Bringing It All Together」第 203–208 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:208,搜「classes are flexible」)。原文:「IDs are specific and hard to reuse; classes are flexible.」 ↩

  13. 出处:「Chapter 7: Bringing It All Together」第 210–213 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:212,搜「Toggle Device Toolbar」)。原文:「Use Chrome DevTools (F12 → Toggle Device Toolbar) to test screen sizes.」 ↩

  14. 出处:「Chapter 7: Bringing It All Together」第 215–221 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:219,搜「Max 2 fonts」)。原文:「Max 2 fonts」「A main color, accent color, and neutral base」。 ↩

  15. 出处:「Chapter 7: Bringing It All Together」第 223–241 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:226,搜「CodePen」;:235,搜「MDN」;:239,搜「Flexbox Froggy」;:241,搜「Grid Garden」)。原文列出的八个:CodePen.io、Google Fonts、Color Hunt、Coolors、MDN Web Docs、CSS Tricks、Flexbox Froggy、Grid Garden。 ↩

  16. 出处:「Chapter 7: Bringing It All Together」第 288–295 段(text/08-ch07-chapter-7-bringing-it-all-together.txt:293,搜「Tailwind」)。原文:「From here, you can explore animations, transitions, SCSS, frameworks like Tailwind or Bootstrap, and even JavaScript to add interactivity.」 ↩

On this page