网页的"长相"不由 HTML 管,而是交给样式表(CSS,层叠样式表)。一份样式表就是一堆规则,每条规则写清两件事:"管谁"(选择器)和"长什么样"(一串"属性: 值")。它的真正价值不是让页面好看,而是一次写、多处生效——一份 style.css 可以被几十个页面共用,改一行颜色全站跟着变;而当多条规则打架时,靠一套叫层叠的规矩定输赢(比来源、比权重、同权重后写的赢)。至于每个元素占多大地方,全看那只盒子:内容 + 内边距 + 边框 + 外边距。
4.2 讲了 HTML 只管内容和结构("这里是一个标题、这里是一段话"),并明确说了 <font color="red"> 那套写法已经淘汰——因为"结构"和"表现"必须分开。
本节就是来履行那个承诺的:"表现"到底写在哪、怎么写、写多份时谁说了算。
一、样式表是什么
CSS = Cascading Style Sheets = 层叠样式表。 三个词:
| 词 | 意思 |
|---|---|
| Style(样式) | 只管"长什么样":颜色、字号、间距、位置——不含任何内容 |
| Sheet(表) | 它是一张清单:一行一条规矩 |
| Cascading(层叠) | 多条规矩打架时,有一套叠放的优先级规矩定输赢(第五节) |
沿用 4.2 那个装修的类比:
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 { } |
鼠标悬停时的链接 | 做交互反馈 |
| 通用 | * { } |
所有元素 | 慎用 |
几条实战要点:
- HTML 里的
class可以挂多个(空格分隔):<p class="note big">—— 这个段落同时享受.note和.big两套规矩 - class 是"共用款",id 是"身份证":同一个 class 可以挂在几十个元素上,同一个 id 一页只能出现一次。所以样式首选 class,id 主要用于"页面内的锚点跳转"和脚本定位
- 选择器写错,规则就静默失效——最常见的是"类名拼错"或"HTML 里忘了写
class"。这类问题的排查靠 F12(第九节)
四、三种写法:样式写在哪
| 写法 | 写在哪 | 能不能复用 | 优先级 |
|---|---|---|---|
| 外部样式表 | 单独一个 .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(层叠)这个词的字面意思:规则像一张张贴纸一层层叠上去,后面的盖住前面的。
你可以写 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 只管 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 说"<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 前面,行内式删掉 —— 红色赢(同权重,后写的赢)。
十、常见误区
- ❌ "CSS 也是编程语言" → 它是声明式的样式描述:没有逻辑控制、不"执行"、不"算",只是列清单(现代 CSS 有变量与少量计算,但本质仍是"描述长什么样")
- ❌ "
class和id随便用哪个都行" → class 是共用款(可挂多个元素、可挂多个类),id 是身份证(一页只能一个)。样式首选 class,id 留给锚点和脚本 - ❌ "行内样式优先级高,所以最方便" → 它无法复用:200 个元素各写一遍,改色时得一个个翻(4.2 的老坑)。首选永远是外部样式表
- ❌ "样式没生效 = 我写错了" → 先查两件事:是不是被更高优先级盖住了(F12 里带删除线)、选择器有没有命中(类名拼错 / HTML 里忘写
class) - ❌ "设了
width: 200px就是 200px 宽" → 默认只算 content,还要加上 padding 与 border;用box-sizing: border-box一劳永逸 - ❌ "所有样式都会往下继承" → 只有文字类属性继承(颜色、字号、字体),边框、内外边距、背景不继承
- ❌ "CSS 分得越细越多文件越专业" → 每个文件都是一次请求(收 4.1);拆分要在"可维护"和"请求数"之间权衡
- ❌ "改了 CSS 刷新却没变" → 又是浏览器缓存(收 4.1 / 4.2),
Ctrl + F5强制刷新
十一、动手自测
- CSS 三个字母分别是什么?"层叠"这个词指的是什么?
- 一条 CSS 规则由哪两部分组成?"
color: red;"这一小段叫什么?漏掉末尾分号会怎样? - 元素选择器、类选择器、ID 选择器分别长什么样?为什么样式首选类选择器?
- 样式表有哪三种写法?哪种优先级最高、哪种复用性最好?
- 层叠的三条比较规则是什么?"同权重时后写的赢"这句对应哪个词?
- 哪些 CSS 属性会继承?为什么"盒子类"属性故意不继承?
- 盒模型从里到外有哪四层?各自对应相框比喻里的什么?
- 为什么
width: 200px; padding: 20px;的元素实际宽 240px?怎么让它就是 200px? - 引一个外部 CSS 文件,对浏览器的请求数有什么影响?为什么这笔账其实很划算?
- 在 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 个页面。
⑩ 说明这条规则被更高优先级的规则覆盖了——浏览器没删它,只是"记下来但不用"。顺着列表从上往下读,最上面那条不带删除线的才是当前生效的赢家。
十二、下一步学什么
- ☑ Web网站的地址(URL) —— 本节把“外观”那一层讲完了(选择器 / 层叠 / 盒模型)。下一站:把地址这一层讲透——URL 的六段怎么拆、每段归谁管,以及那个最容易吃暗亏的点:"你写的和真正发出去的不是同一串字符"(百分号编码)。
相关笔记
- 制作Web网页(HTML) —— 上一节:HTML 只管内容与结构,"表现"交给谁?本节来接手
- Web网站是如何构建的(Web网站) —— "网页四件"里 CSS 那一格的展开;本节也印证了"每个文件都是一次请求"的账
- 用TCP对数据进行分割处理(序列号、ACK号) —— 一个 CSS 文件在网络里同样要被切段、传输、拼回
- 通信过程中所使用的语言(网络架构) —— 应用层对话的实物:HTTP 传 HTML,也传 CSS
- 网络的电话簿(域名解析、主机名、DNS) —— 缓存老账:改了 CSS 刷新没变,先怀疑缓存而不是自己的代码
- 运行和管理服务器(服务器、云服务、内部部署) —— 门房每次把 CSS 也当成一个普通文件发出去,它并不"懂"样式