🌐 第四章 Web网站的运行原理
📄 一句话概括

网页的"长相"不由 HTML 管,而是交给样式表(CSS,层叠样式表)。一份样式表就是一堆规则,每条规则写清两件事:"管谁"(选择器)和"长什么样"(一串"属性: 值")。它的真正价值不是让页面好看,而是一次写、多处生效——一份 style.css 可以被几十个页面共用,改一行颜色全站跟着变;而当多条规则打架时,靠一套叫层叠的规矩定输赢(比来源、比权重、同权重后写的赢)。至于每个元素占多大地方,全看那只盒子:内容 + 内边距 + 边框 + 外边距。

📝 本节和 4.2 的分工

4.2 讲了 HTML 只管内容和结构("这里是一个标题、这里是一段话"),并明确说了 <font color="red"> 那套写法已经淘汰——因为"结构"和"表现"必须分开。

本节就是来履行那个承诺的:"表现"到底写在哪、怎么写、写多份时谁说了算。

一、样式表是什么

CSS = Cascading Style Sheets = 层叠样式表。 三个词:

词 意思
Style(样式) 只管"长什么样":颜色、字号、间距、位置——不含任何内容
Sheet(表) 它是一张清单:一行一条规矩
Cascading(层叠) 多条规矩打架时,有一套叠放的优先级规矩定输赢(第五节)

沿用 4.2 那个装修的类比:

📝 HTML 是毛坯,CSS 是装修图纸

4.2 说过 HTML 是骨架。那么 CSS 就是装修图纸——油漆什么色、地板什么材质、灯装哪里。

关键在这个比喻的后半段:同一张装修图纸,可以拿去给所有同户型的房子用。 图纸改了,所有房子一起变。

这正是 CSS 的立身之本,也是它比 <font color> 高明的地方(第八节)。

二、一条规则长什么样

样式表的本体就是一条条规则,每条规则只有两段:

h1 {
  color: #333333;
  font-size: 24px;
}
┌───────── 选择器(管谁)
│    ┌──── 声明块(长什么样)
h1 {
  color: #333333;   ← 一条"声明",由「属性: 值」组成
  font-size: 24px;  ← 每条声明以分号结尾
}
部分 名字 说明
h1 选择器 点名"这条规矩管哪些元素"
{ } 声明块 里面装着一串声明
color: #333333; 声明 一个「属性: 值」,结尾的分号别忘
/* 注释 */ 注释 写给自己看的说明

属性名基本都是英文的,很好猜:color(颜色)、font-size(字号)、background(背景)、margin(外边距)、padding(内边距)。

最容易犯的低级错误:忘了分号、忘了闭括号、属性名拼错(font-size 写成 fontsize)——CSS 不会报错给你,它只会默默忽略那一条(这一点和 4.2 讲的"浏览器容错"是同一种脾气)。

三、选择器:怎么"点中"那个元素

HTML 那边要配合挂"抓手",CSS 这边才能点中它:

选择器 写法 管谁 用得多不多
元素 p { } 页面上所有 <p> 常用来设全局默认样式
类 .note { } 挂了这个类的元素(<p class="note">) 最常用,强推
ID #header { } 挂了这个 id 的元素(<div id="header">) 少用(一页只能有一个)
后代 nav a { } <nav> 里面的所有链接 常见
伪类 a:hover { } 鼠标悬停时的链接 做交互反馈
通用 * { } 所有元素 慎用

几条实战要点:

四、三种写法:样式写在哪

写法 写在哪 能不能复用 优先级
外部样式表 单独一个 .css 文件,HTML 的 head 里用 <link> 引入 全站所有页面 最低
内部样式表 HTML 的 <head> 里用 <style> 包起来 只有本页 中
行内样式 直接写在标签上:<p style="color: red;"> 只此一个元素 最高

引入外部样式表的那一行(写在每个页面的 head 里):

<link rel="stylesheet" href="style.css">
❗ 优先级是"反着"的,这是有意的设计

写在外面的(外部)优先级最低,写在元素身上的(行内)优先级最高——为什么?

因为优先级低的范围大、难改动,优先级高的范围小、贴身。用"继承关系"理解最顺:越靠近元素本身的规矩,越该说了算。

但优先级高 ≠ 该用它:行内样式没法复用,你要是给 200 个段落都写 style="color:red",想改色的时候只能一个个翻(4.2 那个坑)。首选永远是外部样式表,行内只在"临时测试"或"脚本动态改"时用。

五、层叠:打架了谁说了算

同一元素可能被好几条规则管着,这时按三层顺序依次比:

比什么 规矩 例子
① 比来源 行内 > 内部 / 外部 style="..." 赢
② 比选择器权重 ID > 类 > 元素 .note 赢 p
③ 同权重 后写的赢 同样两个类,样式表里靠下的那条生效

第 ③ 条正是 Cascading(层叠)这个词的字面意思:规则像一张张贴纸一层层叠上去,后面的盖住前面的。

⚠️ `!important` 是核按钮

你可以写 color: red !important; 强行压过一切规则。但请当作不存在: 它会让"谁赢"彻底失去秩序,一旦用开,后面每改一处都得再加一个 !important,最后没人能说清页面为什么是这个颜色。

看到别人代码里满是 !important,基本可以判断:这份样式表已经失控了。

顺带说清"继承"

有些属性会自动往下传给子元素,有些不会:

会继承的 不会继承的
文字相关:color、font-size、font-family、line-height 盒子相关:border、margin、padding、background

为什么这样分? 因为文字的样式"设一次、全篇生效"是好事(所以 body { font-family: ... } 一设,整页字体统一);而盒子的样式要是也继承,内外边距会一层层叠加,页面直接崩掉。

📝 别把"继承"和"复用"搞混
  • 复用(.note 挂到 50 个元素上):是你手动一个个挂上去的,靠的是 class
  • 继承(body 上设的字体):是浏览器自动往下传的,靠的是元素父子关系

前者是"选择器命中",后者是"血缘传递"。两条路都能"一改多处生效",但机制完全不同。

六、盒模型:CSS 里的一切都是盒子

这是 CSS 最该先建立的心智模型:每个元素都在一个矩形盒子里,这个盒子从里到外有四层。

(对应上面第二张图)

层 名字 是什么 生活的类比(相框)
content 内容 文字、图片本身 那张照片
padding 内边距 内容与边框之间的空隙(在盒子内部) 照片与框之间的卡纸
border 边框 盒子的边线 相框的木条
margin 外边距 这个盒子与别的盒子之间的距离 墙上两个相框之间留的白
❗ 新手翻车第一名:`width: 200px` 却不等于 200px 宽

默认情况下,你设的 width 只管 content 那一层。也就是说:

width: 200px;  padding: 20px;  border: 5px;

这个盒子在页面上实际占的宽度是 200 + 20×2 + 5×2 = 250px。

所以常见抱怨是"我明明设了 200 宽,怎么撑破了?"——因为它从来没说过总共是 200。

一行万能解药(现代 CSS 几乎每个项目都先写上这句):

* { box-sizing: border-box; }

它的意思变成:"我说的 width 是连 padding 和 border 一起算的宽度",从此不用心算。

📝 两条附赠经验
  • padding 和 margin 怎么选:想让背景色/边框把空间包进去 → 用 padding(内边距在盒子内部);只想把两个盒子推开 → 用 margin
  • 相邻的 margin 会"折叠":上下相邻的两个盒子,间距不是 10 + 10 = 20,而是取大的那个(这叫外边距折叠)。第一次遇到会觉得"CSS 是不是坏了",其实是规范这么定的

七、跟着 4.1 的两条线走一遍

① 每份 CSS 都是一次请求(收 4.1)

<link rel="stylesheet" href="style.css">

页面里有这一行,浏览器就要多下载一个文件——这就是 4.1 说的"一次打开网页 = 几十上百次请求"里的一项。

但这个费用是一次性的:CSS 文件不常变,浏览器会把它缓存起来(收 4.1 的缓存命中)。第二次访问同一个网站,这个文件不用再下——所以"结构表现分离"的真实账本是:第一次多花一次请求,之后每次都省下重画的功夫。

② 浏览器拿到 CSS 之后干了什么

步骤 干什么
1 下载并解析 CSS 文件,得到一堆规则
2 把规则和 4.2 那棵 DOM 树对上——算出每个节点最终的样式(靠层叠 + 继承定输赢)
3 算位置和大小(盒模型、布局)
4 绘制到屏幕上

第 2 步就是"被划掉的规则"的来源:如果一条规则被更高优先级的盖住了,浏览器不是删掉它,而是记录下来但不用它——所以 F12 里你能看见它带一条删除线(第九节亲手看)。

八、为什么值得这么麻烦:复用

(对应上面第一张图)

混着写(<font color>) 分离写(外部样式表)
全站 200 个页面改个颜色 改 200 个文件,必然漏 CSS 里改 1 行
新增一种样式 每个页面重新抄一遍 加一条规则,全部页面即刻生效
代价 无 每个页面多一次请求(且能被缓存)
💡 收 4.2 的账

4.2 说"<font color="red"> 那套已经淘汰了,因为结构和表现必须分开"——现在能看到分开之后落到哪里了:

不是不要样式,而是把样式搬到了一个专门的、可复用的地方。 这就是"淘汰"的真正含义。

九、动手 Demo40:给 4.2 的网页穿上衣服

1. 在 mysite 里新建 style.css,抄进去:

body {
  font-family: sans-serif;
  max-width: 700px;
  margin: 0 auto;
  padding: 20px;
}
h1 { color: #333333; }
.note {
  background: #f5f5f0;
  border-left: 4px solid #999;
  padding: 12px;
}
a:hover { color: red; }

2. 在 index.html 的 <head> 里加上那一行(放在 <title> 下面):

<link rel="stylesheet" href="style.css">

3. 刷新页面——立刻变了样:内容居中、有了留白、标题颜色变深。 到 F12 → 网络(Network) 面板刷新一次:多了一条 style.css 的请求(这就是 4.1 说的那笔账,亲眼看一遍)。

4. 看"谁赢了"(本节第五节的可视化) F12 → 元素(Elements) 面板 → 点中 <h1> → 右侧 Styles 区会列出所有管着它的规则。 - 带删除线的 = 被更高优先级覆盖的规则(第五节第 ② ③ 条) - 从上往下读,最上面那条生效的就是赢家

5. 现场改,别改文件 在 Styles 面板里直接改颜色值 → 页面立刻变,但硬盘上的 style.css 一个字没变(刷新就还原)。 (这和 4.2 里"在元素面板改文字"是同一个道理:你在改浏览器内存里的那份结果,不是文件。)

6. 体验"复用" 在 index.html 的 body 里再加一段:<p class="note">这是一段提示文字。</p> 刷新——背景和左边框自动就有了。再回 style.css 把 .note 的背景色改一下,两处同时变。 这就是本节图一画的"一份样式表管多个页面"的最小版本。

7. 30 秒实验:亲手制造一场"打架" 在 style.css 里按顺序写下三条(.note 的要在后面):

p { color: red; }
.note { color: blue; }

现在给 <p class="note"> —— 蓝色赢(类 > 元素)。 再给那个 <p> 加上行内式 style="color: green;" —— 绿色赢(行内 > 全部)。 最后把 CSS 里的 .note 挪到 p 前面,行内式删掉 —— 红色赢(同权重,后写的赢)。

💡 一次实验把"层叠"的三条规矩全走一遍,比背十遍都管用。

十、常见误区

  1. ❌ "CSS 也是编程语言" → 它是声明式的样式描述:没有逻辑控制、不"执行"、不"算",只是列清单(现代 CSS 有变量与少量计算,但本质仍是"描述长什么样")
  2. ❌ "class 和 id 随便用哪个都行" → class 是共用款(可挂多个元素、可挂多个类),id 是身份证(一页只能一个)。样式首选 class,id 留给锚点和脚本
  3. ❌ "行内样式优先级高,所以最方便" → 它无法复用:200 个元素各写一遍,改色时得一个个翻(4.2 的老坑)。首选永远是外部样式表
  4. ❌ "样式没生效 = 我写错了" → 先查两件事:是不是被更高优先级盖住了(F12 里带删除线)、选择器有没有命中(类名拼错 / HTML 里忘写 class)
  5. ❌ "设了 width: 200px 就是 200px 宽" → 默认只算 content,还要加上 padding 与 border;用 box-sizing: border-box 一劳永逸
  6. ❌ "所有样式都会往下继承" → 只有文字类属性继承(颜色、字号、字体),边框、内外边距、背景不继承
  7. ❌ "CSS 分得越细越多文件越专业" → 每个文件都是一次请求(收 4.1);拆分要在"可维护"和"请求数"之间权衡
  8. ❌ "改了 CSS 刷新却没变" → 又是浏览器缓存(收 4.1 / 4.2),Ctrl + F5 强制刷新

十一、动手自测

❓ 自测一下
  1. CSS 三个字母分别是什么?"层叠"这个词指的是什么?
  2. 一条 CSS 规则由哪两部分组成?"color: red;"这一小段叫什么?漏掉末尾分号会怎样?
  3. 元素选择器、类选择器、ID 选择器分别长什么样?为什么样式首选类选择器?
  4. 样式表有哪三种写法?哪种优先级最高、哪种复用性最好?
  5. 层叠的三条比较规则是什么?"同权重时后写的赢"这句对应哪个词?
  6. 哪些 CSS 属性会继承?为什么"盒子类"属性故意不继承?
  7. 盒模型从里到外有哪四层?各自对应相框比喻里的什么?
  8. 为什么 width: 200px; padding: 20px; 的元素实际宽 240px?怎么让它就是 200px?
  9. 引一个外部 CSS 文件,对浏览器的请求数有什么影响?为什么这笔账其实很划算?
  10. 在 F12 的元素面板里看到一条带删除线的样式,说明什么?

答案: ① Cascading Style Sheets(层叠样式表)。"层叠"指多条规则打架时,规则像贴纸一样一层层叠上去,后面的盖住前面的——由此有了"来源 → 权重 → 书写顺序"这套定输赢的规矩。 ② 选择器(管谁)+ 声明块(长什么样)。color: red; 是一条声明,由「属性: 值」组成,末尾分号不能漏(漏了这条声明会被忽略,且不会报错)。 ③ p / .note / #header。样式首选类选择器,因为一个类可以挂在任意多个元素上、一个元素也能挂多个类,复用性最好;id 一页只能出现一次,留给锚点与脚本。 ④ 外部样式表(<link>,复用性最好、优先级最低)、内部样式表(<style>)、行内样式(style="...",优先级最高、完全不能复用)。 ⑤ ① 比来源:行内 > 内部/外部;② 比选择器权重:ID > 类 > 元素;③ 同权重:后写的赢。第 ③ 条对应的就是 Cascading(层叠)。 ⑥ 文字类继承(color、font-size、font-family、line-height);盒子类(border、margin、padding、background)不继承。因为盒子属性若也继承,边距会一层层叠加、布局立刻失控;而文字样式"设一次全篇生效"正是我们想要的。 ⑦ content 内容 / padding 内边距 / border 边框 / margin 外边距。相框比喻:照片 / 照片与框之间的卡纸 / 相框木条 / 墙上两个相框之间留的白。 ⑧ 因为默认 width 只算 content 那一层,实际占宽要再加左右 padding 与 border(200 + 20×2 = 240)。加一句 * { box-sizing: border-box; } 让 width 把 padding 和 border 一起算进去。 ⑨ 多一次请求。但这笔账很划算:① CSS 文件能被浏览器缓存,第二次访问不用再下;② 换来的是改一行全站生效,而不是改 200 个页面。 ⑩ 说明这条规则被更高优先级的规则覆盖了——浏览器没删它,只是"记下来但不用"。顺着列表从上往下读,最上面那条不带删除线的才是当前生效的赢家。

十二、下一步学什么

相关笔记