【全篇高达13万字】CSS 深度修炼:从基础到进阶,成为网页样式设计大师的独家笔记
【全篇高达13万字】CSS 深度修炼:从基础到进阶,成为网页样式设计大师的独家笔记
Prorise序章:掌握 CSS,构建专业网页外观
摘要: 本笔记将直面初学者在学习和使用 CSS 时普遍感到的困惑与挫败感,特别是在与 AI 工具协作时,样式代码的维护性问题尤为突出。我们将深入分析编写混乱的 CSS 代码所带来的具体痛点,并由此引出本系列教程的核心主张:通过系统学习 CSS 的核心基础,从第一天起就建立编写专业、可扩展、易维护样式代码的思维模式与工程能力。
在本章中,我们将循序渐进,清晰地剖析问题的根源,并为您铺平学习 CSS 的道路:
- 首先,我们将深入 痛点分析,复现那些令初学者头疼的真实场景,让您感同身受。
- 接着,我们将明确 学习路径,告诉您掌握 CSS 的关键在于理解其内在的核心法则。
- 然后,我们将手把手指导您完成 环境搭建,一个代码编辑器和一个浏览器足矣。
- 最后,我们将通过 首次实践,让您亲手链接第一张样式表,看到代码生效的即时反馈。
0.1. 痛点分析:为何传统 CSS 难以维护?
业务背景: 假设你是一位刚掌握 HTML 的前端新人,正尝试独立或在 AI 的辅助下,为一个个人信息卡片编写样式。卡片结构很简单,包含头像、姓名、职位和社交链接。
你的第一个版本的样式代码可能是这样的:
1 | /* style.css */ |
这段代码能够正常工作,但随着项目变得复杂,或者当你需要修改 AI 生成的类似代码时,以下几个核心痛点会逐渐暴露:
为什么 AI 生成的一大段 CSS,我只想改个主题色和圆角大小,却要改好几个地方?
这是因为代码中缺少对“设计规范”的抽象。颜色值、尺寸值等“魔术数字”被硬编码在各处,缺乏统一管理的入口。
为什么我的样式越写越多,不同组件的样式会互相“打架”?比如我在别处定义的 .title
样式影响到了卡片里的标题。
这是因为对 CSS 选择器的 全局作用域和优先级机制 理解不足,导致了样式污染和意料之外的覆盖。
为什么我想复用一个居中布局的样式,却只能到处复制粘贴相同的几行代码?
这是因为没有运用 CSS 的 组合和复用能力,例如通过创建通用的工具类来封装常用样式。
HTML 结构是层层嵌套的,为什么我的 CSS 却要写一长串的选择器,看起来非常扁平,无法体现结构?
这是因为未能有效利用 组合选择器 来表达 DOM 结构,导致选择器变得冗长且脆弱。
核心问题: CSS 本身是一门强大而灵活的语言,但若缺乏对其核心规则(如选择器、层叠、盒模型)的深刻理解,代码将不可避免地走向混乱。解决方案并非逃避 CSS,而是掌握它。
0.2. 解决方案:回归基础,掌握 CSS 核心
要解决上述所有痛点,我们无需学习额外的工具,只需回归 CSS 本身,系统地掌握其内在的几大核心支柱。本教程将围绕这些支柱展开:
- 选择器: 这是与 HTML “对话”的基础。我们将学习如何精准地选中任何你想要添加样式的元素。
- 层叠与优先级: 这是解决样式冲突的关键。我们将学习浏览器如何决定哪条规则最终生效。
- 盒模型: 这是所有网页布局的原子。我们将学习元素如何由内容、内边距、边框和外边距构成。
- 显示与布局: 这是控制元素排列的艺术。我们将掌握从传统的
display
属性到现代的 Flexbox 和 Grid 布局。
与时俱进: 值得一提的是,现代 CSS 自身也在不断进化。例如,现在 CSS 已经原生支持 变量,可以直接解决“硬编码”的问题。我们会在后续章节中学习这些现代特性。
0.3. 环境搭建:一个编辑器,一个浏览器
学习 CSS 的美妙之处在于其 极低的入门门槛。你不需要安装任何复杂的编译器或工具链,只需两个核心软件:
2025
第一步
安装代码编辑器: Visual Studio Code
这是我们编写 HTML 和 CSS 代码的地方。它免费、强大,并拥有丰富的插件生态。
第二步
安装效率插件: Live Server (可选,但强烈推荐)
这个 VS Code 插件能启动一个本地开发服务器,并在你保存文件时自动刷新浏览器,极大地提升开发效率。
- 打开 VS Code
- 点击扩展图标 (或按 Ctrl+Shift+X)
- 搜索并安装由
Ritwick Dey
发布的 Live Server
创建你的第一个项目结构
现在,让我们创建一个用于练习的简单项目文件夹。
1 | my-first-css-project/ |
0.4. 初试牛刀:链接你的第一张样式表
现在,让我们完成从编写 CSS 到在浏览器中看到效果的完整流程。
1. 编写 HTML 和 CSS 代码
文件路径: my-first-css-project/index.html
1 |
|
文件路径: my-first-css-project/css/style.css
1 | /* 这是一个 CSS 注释 */ |
2. 在浏览器中查看结果
- 如果安装了 Live Server: 右键点击
index.html
文件,选择Open with Live Server
。 - 如果未安装插件: 直接在文件浏览器中右键点击
index.html
,选择“在默认浏览器中打开”。
你将会看到一个拥有淡蓝色背景和居中蓝色标题的页面。
工作流已建立: 恭喜!你已经成功建立了最基础的前端开发工作流。从现在开始,你只需修改 css/style.css
文件并保存,然后刷新浏览器(如果使用 Live Server 则会自动刷新),即可看到最新的样式效果。
第一章:CSS 基础核心
摘要: 本章将系统讲解构成 CSS 的三大基石:引入方式、继承规则 与 尺寸单位。我们将学习如何将样式代码应用到 HTML 中,理解样式是如何在元素间传递的,并掌握用于精确控制布局和字体的各种单位。本章所有知识点均为后续学习 SCSS 高级特性打下坚实基础。
在本章中,我们将像搭建建筑一样,从最基础的材料和规则开始:
- 首先,我们将 认识 CSS,了解它的全称和作为网页“造型师”的核心职责。
- 接着,我们将学习 CSS 的三种引入方式,并从工程化的角度确立最佳实践。
- 然后,我们将掌握它的一个核心规则——样式的继承性,理解样式的传递机制。
- 最后,我们将深入 尺寸单位 的世界,学会如何用代码精确度量页面上的一切。
1.1. CSS 简介:认识层叠样式表
CSS (Cascading Style Sheets) 是“层叠样式表”的缩写。如果说 HTML 是网页的骨架,那么 CSS 就是网页的皮肤和服装。它是一种专门用于定义 HTML 元素视觉表现的语言,负责控制页面的布局、颜色、字体、间距等一切外观相关的样式。“层叠”(Cascading)的含义: 这个词是 CSS 的核心之一。它意味着样式规则可以从多个来源层层叠加,并且存在一套明确的优先级规则来解决冲突。例如,一个你亲自设置的样式,可以覆盖掉浏览器的默认样式。我们将在后续章节深入学习这套规则。
1.2. CSS 的三种引入方式:行内、内嵌与外链
将 CSS 应用于 HTML 共有三种方式。了解它们的区别并选择正确的方式,是编写可维护代码的第一步。
使用场景
只想给某个唯一元素快速加一条简单样式。
1 | <p style="color: blue; font-size: 20px;"> |
不推荐:结构与表现混杂,难以维护。仅作临时调试。
使用场景
样式只服务于当前页面,不对外复用。
1 |
|
使用场景
多页面共享统一视觉风格,实现完全复用。
css/main.css
1 | h1 { |
index.html
1 |
|
工程化视角:外链样式是现代 Web 的唯一标准。我们写的 .scss
最终会被编译成 .css
,再由 <link>
引入,彻底分离结构、表现与行为。
优劣势对比总结
样式表 | 优点 | 缺点 | 使用情况 |
---|---|---|---|
行内样式 | 书写方便,权重高 | 没有实现结构与样式分离,无法复用 | 极少,仅用于调试 |
内嵌样式 | 部分分离,仅作用于当前页 | 无法在多页面间复用 | 一般,用于单页应用或特定页面样式 |
外链样式 | (推荐) 完全分离,易于维护,可复用 | 需额外维护 .css 文件 | 最多,所有项目的标准实践 |
1.3. 核心规则:样式的继承性
定义: 继承性是 CSS 的一个基本特性,指的是应用在父元素上的某些 CSS 属性会自动被其内部的子元素所继承,从而无需为每个子元素重复设置相同的样式。
范围: 并非所有属性都可以被继承。
- 可继承的: 通常是与 文字排版相关的属性,例如:
color
,font-family
,font-size
,font-weight
,line-height
,text-align
等。 - 不可继承的: 通常是与 元素尺寸、布局和背景相关的属性,例如:
width
,height
,padding
,margin
,border
,background-color
等。
痛点背景: 你希望整个页面的基础字体和颜色保持统一,只需在顶层元素设置一次即可,而不必为每个段落、列表都单独指定。
解决方案: 在 body
标签上设置通用文字样式,利用继承性将其传递给页面内的所有子元素。同时,可以为特定元素(如 h1
)设置更具体的样式来覆盖继承值。
1 |
|
1.4. 尺寸单位:绝对单位与相对单位
在 CSS 中,单位是用来精确度量长度、尺寸和间距的标尺。它们主要分为两大类。
绝对长度单位
绝对单位的长度是固定的,不会因为其他元素的变化而改变。
- `px` (像素): Pixel,像素。它是屏幕显示的基本单位,也是 Web 开发中最常用、最基础的绝对单位。对于需要精确控制尺寸的场景非常有用。
- 其他:
cm
(厘米),mm
(毫米),in
(英寸) 等,这些多用于打印样式,在网页开发中极少使用。
相对长度单位 (Relative Length Units)
相对单位的长度不是固定的,它会根据其他元素的尺寸(例如父元素的字体大小或视口宽度)进行计算。这是实现响应式设计的核心。
%
: 百分比。相对于其父元素的同一属性的值。例如,width: 50%
表示宽度是其父元素宽度的一半。em
: 相对于 当前元素 的字体大小 (font-size
)。如果当前元素未设置,则相对于 父元素 的字体大小。rem
: (重点推荐) Root EM。这是 CSS3 新增的单位,它只相对于 根元素 (<html>
) 的字体大小进行计算。这使得它成为构建可伸缩、响应式布局的理想选择,因为我们只需改变根元素的字体大小,就能等比例地缩放整个页面的尺寸。vw
: 视口宽度的 1%。10vw
等于视口宽度的 10%。vh
: 视口高度的 1%。10vh
等于视口高度的 10%。
痛点背景: 你需要创建一个元素,它的尺寸能始终根据用户浏览器窗口的大小变化而自适应,例如,一个宽度永远是屏幕宽度一半的盒子。
解决方案: 使用 vw
和 vh
单位。
1 |
|
1.5. 本章核心速查总结
分类 | 关键项 | 核心描述 |
---|---|---|
核心定义 | CSS | 层叠样式表,负责定义 HTML 的视觉表现。 |
引入方式 | 行内样式 (style="") | (不推荐) 破坏结构与表现分离,仅用于调试。 |
内嵌样式 (<style>) | 适用于单页面特定样式。 | |
外链样式 (<link>) | (推荐) 项目开发标准,实现完全分离和复用。 | |
核心规则 | 继承性 | 子元素会自动继承父元素与 文字排版相关 的属性。 |
核心单位 | px | (绝对单位) 像素,最基础的单位,用于精确尺寸。 |
% | (相对单位) 相对于父元素。 | |
rem | (推荐) 相对于根元素(<html> )字体大小,响应式布局利器。 | |
vw / vh | (相对单位) 相对于视口宽/高,适用于全屏或自适应布局。 |
第二章:精准定位与布局基石
摘要: 本章将全面解析 CSS 选择器的运作机制,从基础的标签选择器到复杂的组合选择器,让您能够像外科医生一样精准地定位到任何 HTML 元素。随后,我们将深入探索 CSS 布局的原子单位——盒模型,理解其内容、内边距、边框和外边距的构成。最后,我们会讲解元素的显示模式,并结合所有知识点,确立样式初始化等工程化最佳实践。
在本章中,我们将分层递进,构建起您对 CSS 布局的完整认知:
- 首先,我们将学习 CSS 选择器,这是我们与页面元素进行“对话”的语言。
- 接着,我们将探讨 层叠与优先级,理解当多条样式规则作用于同一元素时,浏览器是如何决策的。
- 然后,我们将深入研究 盒模型,这是构成所有网页布局的基本单元。
- 之后,我们将辨析 元素的显示模式,了解不同元素(如
div
和span
)在布局中的天然差异。 - 最后,我们将学习 样式初始化 的最佳实践,为所有项目打下一个干净、统一的起点。
2.1. CSS 选择器:与元素对话的语言
选择器是 CSS 的核心,它定义了我们的样式规则将应用于哪些 HTML 元素。我们将从最基础的选择器开始,逐步学习如何将它们组合,以实现更精确的定位。
2.1.1. 基础选择器
这是我们工具箱里最基本的四种工具。
1. 标签选择器
- 用途: 通过 HTML 标签名来匹配文档中所有同名标签。通常用于进行全局的、基础的样式重置。
- 示例: 统一清除所有
<a>
标签的默认下划线。1
2
3a {
text-decoration: none;
}
2. 类选择器
- 用途: (最常用) 通过标签的
class
属性来匹配元素。它非常灵活,一个类可以被多个元素使用,一个元素也可以拥有多个类。类选择器以.
开头。 - 示例: 创建可复用的颜色和尺寸类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<style>
.box {
width: 100px;
height: 100px;
border: 1px solid #ccc;
text-align: center;
line-height: 100px;
}
.bg-red {
background-color: #e74c3c;
}
.bg-green {
background-color: #2ecc71;
}
</style>
<div class="box bg-red">红色</div>
<div class="box bg-green">绿色</div>
<div class="box bg-red">红色</div>
3. ID 选择器)
用途: 通过标签的
id
属性匹配 唯一 的元素。id
在整个 HTML 文档中必须是唯一的。ID 选择器以#
开头。示例: 定位页面主导航栏。
1
2
3#main-nav {
background-color: #333;
}注意: 由于
id
的唯一性和高优先级特性,它在 CSS 中应谨慎使用,以避免产生难以覆盖的样式。它的主要应用场景是配合 JavaScript 来操作特定的 DOM 元素。在样式编写中,我们应优先使用类选择器。
4. 通配符选择器
- 用途: 匹配页面上的 所有 元素。主要用于进行最彻底的样式清除。
- 示例: 清除所有元素的默认内外边距。
1
2
3
4* {
margin: 0;
padding: 0;
}性能警告: 通配符选择器会遍历页面上的每一个元素,对浏览器性能有一定影响。在大型项目中,更推荐使用针对性的 Reset CSS 方案,而非粗暴地使用
*
。
2.1.2. 组合选择器:更精准的定位
当基础选择器不足以精确描述我们想要选择的元素时,就需要将它们组合起来。
后代选择器 (Descendant Selector - 空格
)
- 含义: 选中
选择器1
内部的 所有 满足选择器2
的后代元素(儿子、孙子等)。1
2
3
4
5
6
7
8
9
10
11
12
13<style>
/* 只选中 nav 元素内部的 a 标签 */
nav a {
color: #e74c3c;
margin: 0 10px;
}
</style>
<nav>
<a href="#">首页</a>
<a href="#">产品</a>
<div><a href="#">关于我们 (我也是后代)</a></div>
</nav>
<a href="#">我是外部链接</a>
子代选择器 (Child Selector - >
)
- 含义: 仅选中
选择器1
内部的 直接 满足选择器2
的子元素(仅儿子)。1
2
3
4
5
6
7
8
9
10
11
12<style>
/* 只选中 nav 元素的直接子元素 a 标签 */
nav > a {
color: #3498db;
margin: 0 10px;
}
</style>
<nav>
<a href="#">首页 (我是直接子元素)</a>
<a href="#">产品 (我也是)</a>
<div><a href="#">关于我们 (我不是)</a></div>
</nav>
相邻兄弟选择器 (Adjacent Sibling Selector - +
)
- 含义: 选中紧跟在
选择器1
后面的 那一个 满足选择器2
的兄弟元素。1
2
3
4
5
6
7
8
9
10<style>
/* 选中 h1 后面紧邻的那个 p 标签 */
h1 + p {
color: #9b59b6;
font-weight: bold;
}
</style>
<h1>这是一个标题</h1>
<p>我是紧跟在 h1 后面的段落。</p>
<p>我不是紧邻的段落。</p>
通用兄弟选择器 (General Sibling Selector - ~
)
- 含义: 选中在
选择器1
后面的 所有 满足选择器2
的兄弟元素。1
2
3
4
5
6
7
8
9
10<style>
/* 选中 h1 后面所有的兄弟 p 标签 */
h1 ~ p {
color: #16a085;
}
</style>
<h1>这是一个标题</h1>
<div>我不是p标签</div>
<p>我是 h1 后面的兄弟段落。</p>
<p>我也是 h1 后面的兄弟段落。</p>
2.1.3. 分组与交集
并集选择器 (Grouping Selector - ,
)
- 含义: 同时选中满足
选择器1
和 满足选择器2
的所有元素,为它们应用相同的样式。1
2
3
4
5
6
7
8
9
10<style>
/* 同时为 h1, h2, p 设置相同的颜色 */
h1, h2, p {
color: red;
}
</style>
<h1>主标题</h1>
<h2>副标题</h2>
<p>这是一个段落。</p>
<span>我不会被选中。</span>
交集选择器
- 含义: 选中 同时 满足
选择器1
和选择器2
的那一个元素。选择器之间无分隔符,最常见的用法是标签.类名
。1
2
3
4
5
6
7
8
9
10<style>
/* 选中既是 p 标签,又拥有 .important 类的元素 */
p.important {
color: #c0392b;
font-size: 18px;
}
</style>
<p class="important">我是重要的段落。</p>
<div class="important">我不是 p 标签,不会被选中。</div>
<p>我没有 important 类,不会被选中。</p>
2.2. 层叠与优先级:当规则发生冲突
层叠性: 指的是样式的叠加。多个来源的样式规则(如浏览器默认样式、用户自定义样式、开发者样式)可以共同作用于一个元素。
优先级: 当多个选择器选中同一个元素,并对同一个属性设置了不同的值时,就会发生冲突。此时,浏览器会根据选择器的 优先级 来决定最终应用哪个样式。
优先级的基本规则可以概括为一条链:!important
> 行内样式 > ID 选择器 > 类/属性/伪类选择器 > 标签/伪元素选择器 > 通配符选择器 > 继承的样式
计算规则:
- 先比较级别: ID 选择器的优先级永远高于 100 个类选择器。
- 级别相同时,比较数量:
.nav .link
(2 个类) 的优先级高于.nav
(1 个类)。 - 权重完全相同时,后来者居上: 在样式表中,写在后面的规则会覆盖前面的规则。
1 | <style> |
🤔 思考一下:
在上面的例子中,<p>
标签的最终颜色是什么?
2.3. 盒模型:网页布局的原子
在 CSS 的世界里,每一个 HTML 元素都可以看作一个矩形的盒子。这个“盒子”由四个部分组成:内容区 (content)、内边距 (padding)、边框 (border) 和 外边距 (margin)。对网页进行布局,本质上就是排列这些盒子。
2.3.1. 内容区
盒子的核心,用于显示文本、图片等实际内容。
width
: 设置内容区的宽度。height
: 设置内容区的高度。overflow
: 当内容超出width
和height
范围时,定义如何处理。常用值有hidden
(隐藏),scroll
(显示滚动条),auto
(自动)。
1 |
|
2.3.2. 边框
包裹在内边距之外的线条。
border-width
: 边框粗细。border-style
: 边框样式,如solid
(实线),dashed
(虚线),dotted
(点线)。此为必需属性。border-color
: 边框颜色。- 简写属性:
border: 1px solid black;
- 单边设置:
border-top
,border-right
,border-bottom
,border-left
。
1 |
|
2.3.3. 内边距
内容区与边框之间的空间,会撑大盒子的可见尺寸。
- 简写属性:
padding
可以接受 1 到 4 个值,遵循 上、右、下、左 的顺时针规则。padding: 10px;
(四边都是 10px)padding: 10px 20px;
(上下 10px, 左右 20px)padding: 10px 20px 30px;
(上 10px, 左右 20px, 下 30px)padding: 10px 20px 30px 40px;
(上 10px, 右 20px, 下 30px, 左 40px)
1 |
|
2.3.4. 外边距
边框以外的区域,用于控制盒子与盒子之间的距离,是透明的。
- 简写属性:
margin
的赋值规则与padding
完全相同。 - 特殊应用:
margin: 0 auto;
可以使一个具有固定宽度的块级元素水平居中。
1 |
|
2.3.5. 深度解析:外边距合并
这是一个初学者常见的陷阱。在某些情况下,相邻的垂直外边距会发生“合并”(或称“塌陷”),取其中较大的值作为最终的外边距,而不是简单相加。
场景一:相邻兄弟元素
1 | <style> |
场景二:父子元素(嵌套)
当父元素没有边框或内边距时,子元素的 margin-top
会“塌陷”并作用于父元素。
简单说,就是如果父元素没边框和内边距,子元素设置的 margin - top
,看起来就像是给父元素设置的,会让父元素整体下移。比如图中,给子元素 .child
设 margin - top: 50px
,结果父元素 .parent
也跟着下移了。
1 | <style> |
解决方法: 加 overflow: hidden
是因为它能触发父元素形成 BFC(块级格式化上下文),BFC 内部元素布局独立,可阻止外边距合并;加 border
(比如 border: 1px solid transparent
),是因为它在父子元素间形成了分隔,使子元素的 margin
不再直接作用于父元素,避免了塌陷 。
2.3.6. 现代布局基石:box-sizing
痛点背景: 默认情况下,你给一个盒子设置的 width
和 height
只作用于 内容区。当你再添加 padding
和 border
时,盒子的实际可见宽度会变大 (width
+ padding
*2 + border
*2),这给精确计算布局带来了很大麻烦。
解决方案: 使用 box-sizing
属性改变盒子尺寸的计算方式。
content-box
(默认值):width
和height
只包含 content。border-box
(强烈推荐):width
和height
包含了 content、padding 和 border。这意味着,你设置的width: 200px;
就是这个盒子最终的可见宽度,即使你再添加 padding 和 border,浏览器会自动向内压缩 content 的空间,而保持总宽度不变。
1 | <style> |
最佳实践: 在项目的一开始,就使用通配符选择器为所有元素设置 box-sizing: border-box;
,这将极大简化你的布局计算。
1 | *, |
2.4. 元素显示模式:块、行内与行内块
HTML 元素根据其默认的显示特性,主要分为三种类型。这是一个非常适合进行强对比的场景。
代表: <div>
, <p>
, <h1>-<h6>
, <ul>
, <li>
, <form>
等。
特性:
- 独占一行: 无论内容多少,总会新起一行。
- 可设宽高: 可以自由设置
width
和height
。 - 内外边距:
margin
和padding
的四个方向都有效。 - 默认宽度: 宽度默认为父元素的 100%。
- 容器: 通常作为容器,可以包裹任何其他类型的元素(
<p>
除外)。
因为 DTD 规定块级元素不能放在 <p>
里,当 <p>
没结束时遇到下一个块元素,浏览器会自动结束当前 <p>
,导致无法正常包裹,所以 <p>
一般只包裹行内元素
代表: <span>
, <a>
, <strong>
, <em>
等。
特性:
- 同行显示: 可以在一行内与其他行内元素共存。
- 宽高无效: 设置
width
和height
无效,其尺寸由内容撑开。 - 垂直边距无效:
margin-top/bottom
和padding-top/bottom
无效,不会影响布局。水平方向的内外边距有效。 - 包裹内容: 主要用于包裹文字或小图标。
代表: <img>
, <input>
, <button>
。或者任何通过 CSS 设置了 display: inline-block;
的元素。
特性: 它是块元素和行内元素的结合体。
- 同行显示 (行内特性): 可以在一行内共存。
- 可设宽高 (块特性): 可以自由设置
width
和height
。 - 内外边距有效 (块特性):
margin
和padding
的四个方向都有效。
2.4.1. 模式转换:display 属性
我们可以使用 display
属性来改变元素天生的显示模式,以满足不同的布局需求。
属性值 | 效果 |
---|---|
block | 将元素转换为块元素。 |
inline | 将元素转换为行内元素。 |
inline-block | 将元素转换为行内块元素。 |
none | 隐藏元素,并且不占据任何空间。 |
flex | (现代布局) 启用 Flexbox 弹性布局。 |
常见的有:制作导航菜单时,用 display 属性控制子菜单显示隐藏;将行内元素(如)转换为块级元素,方便设置宽高;使用 display: flex 创建弹性布局,适配不同屏幕尺寸(我们后面会详细讲 Flex 布局)
1 |
|
2.5. 最佳实践:样式初始化 (CSS Reset)
痛点背景: 不同浏览器为 HTML 元素设置的默认样式存在微小差异,导致页面在不同浏览器上显示效果不一致。
解决方案: 在编写我们自己的样式之前,首先用一段标准化的代码来清除或统一所有元素的默认样式,这就是 CSS Reset。
1 | /* case 1: 最省事,但性能差且过于粗暴 */ |
这种方式会重置所有元素,包括那些我们可能不希望重置的(如表单元素),并且使用通配符选择器效率较低。
1 | /* case 2: 相对繁琐,但是是较好选择 */ |
这种方式更有针对性,只重置了我们关心的块级元素和列表。
在大型项目中,最佳实践是引入一个社区公认的、经过大量测试的 Reset 库。最著名的之一是 Eric Meyer’s “Reset CSS”。
只需将这个库的内容复制到你的主样式文件(或 SCSS 主文件)的最顶端,就能确保你的项目在一个干净、统一的样式基线上开始。
2.6. 本章核心速查总结
分类 | 关键项 | 核心描述 |
---|---|---|
基础选择器 | . (类), # (ID) | (推荐) .class 用于样式,#id 用于 JS。 |
组合选择器 | A B , A > B | 后代(空格): 选中内部所有;子代(>): 仅选中直接子元素。 |
优先级 | !important > 行内 > ID > 类 > 标签 | 比较时先看级别,再看数量,最后看顺序。 |
盒模型 | content, padding, border, margin | 构成元素布局的四个区域,由内到外。 |
盒模型计算 | box-sizing: border-box; | (推荐) 使 width 和 height 包含 padding 和 border,极大简化布局。 |
外边距合并 | margin-top/bottom 合并 | 相邻兄弟或嵌套父子元素的垂直外边距会取最大值,而非相加。 |
显示模式 | block | 独占一行,可设宽高。 |
inline | 同行显示,宽高无效,垂直边距无效。 | |
inline-block | 同行显示,可设宽高。 | |
模式转换 | display | 用于在 block , inline , inline-block , none 等模式间切换。 |
第三章:精准定位:从基础到高级选择器
摘要: 本章将是 CSS 选择器的完全指南。我们将从回顾基础选择器开始,深入学习如何通过组合、属性、状态和结构来构建强大的选择器,实现对任何元素的精准定位。本章的重点是伪类和伪元素,它们是实现交互效果和高级 UI 设计的关键。最后,我们将通过一个实战案例,将所学知识融会贯通。
在本章中,我们将解锁 CSS 的“精确制导”能力:
- 首先,我们将快速 回顾基础与组合选择器,巩固已有知识。
- 接着,我们将学习 属性选择器,根据元素的“身份证”信息来定位它。
- 然后,我们将深入本章的第一个核心——伪类选择器,让页面能够响应用户的交互和状态。
- 之后,我们将掌握第二个核心——伪元素选择器,学会在不改变 HTML 的情况下创建和装饰虚拟元素。
- 最后,我们将进入 实战环节,综合运用所学知识,构建一个带分隔线的导航菜单效果。
3.1. 基础与组合选择器回顾
上一章我们对核心选择器有了一定认识,现在来快速回顾。
基础选择器:
- 标签选择器:如
p
,能选中页面中所有<p>
标签元素,方便统一设置某类标签样式。 - 类选择器:像
.container
,可选中所有 class 属性值为“container”的元素,在日常样式设置中使用频率高,能对不同标签应用相同样式。 - ID 选择器:
#main
,用于选中唯一 ID 为“main”的元素,一个页面中 ID 应唯一,常配合 JavaScript 操作特定元素。 - 通配符选择器:
*
,会选中页面所有元素,不过使用时要谨慎,以免影响性能。
组合选择器:
- 后代选择器:
nav a
,能选中<nav>
元素内部所有<a>
元素,不管嵌套多深,方便对特定容器内元素设置样式。 - 子元素选择器:
ul > li
,仅选中<ul>
元素的直接子元素<li>
,不会选中更深层级的<li>
,精准控制直接子元素。 - 相邻兄弟选择器:
h1 + p
,选中紧跟在<h1>
元素后的第一个<p>
元素,当需要为特定元素后的紧邻元素设置样式时很有用。 - 通用兄弟选择器:
h1 ~ p
,选中在<h1>
元素之后的所有<p>
元素,只要在源文档顺序上在<h1>
之后即可,不要求紧邻 。
3.2. 属性选择器:根据标签属性定位
属性选择器允许我们根据 HTML 元素的属性(如 href
, target
, type
)及其值来应用样式,这在处理表单或特定链接时非常有用,如果这里您学过正则表达式,那么理解起来会十分轻松,我们只需要记住 ^
代表开头,$
代表全选,*
代表包含即可
写法 | 说明 | 示例 |
---|---|---|
[attr] | 选中拥有 attr 属性的元素 | a[title] |
[attr=val] | 选中 attr 属性值 完全等于 val 的元素 | a[target=_blank] |
[attr^=val] | 选中 attr 属性值以 val 开头 的元素 | a[href^="https"] |
[attr$=val] | 选中 attr 属性值以 val 结尾 的元素 | a[href$=".pdf"] |
[attr*=val] | 选中 attr 属性值 包含 val 的元素 | a[href*="google"] |
痛点背景: 你希望为网站上所有指向外部网站的链接(在新窗口打开)和所有指向 PDF 文件的链接自动添加一个特殊的小图标,以提示用户。
解决方案: 我们可以完美地利用属性选择器来实现这个需求,而无需手动为这些链接添加特定的类。
1 | <style> |
3.3. 伪类选择器:响应用户交互与状态
伪类是 CSS 的一大特色,它允许我们为元素的某些 特殊状态(如鼠标悬停、链接被访问)或 特殊位置(如第一个子元素)应用样式。伪类以单个冒号 :
开头。
3.3.1. 动态与链接伪类
这些伪类与用户的行为和浏览历史相关,是实现 UI 交互效果的基础。
伪类 | 描述 |
---|---|
:hover | (最常用) 鼠标指针悬停在元素上时。 |
:active | 元素被用户激活时(如鼠标按下未松开)。 |
:focus | 元素获得焦点时(如通过 Tab 键选中的输入框)。 |
:link | 特指 <a> 标签,匹配未被访问过的链接。 |
:visited | 特指 <a> 标签,匹配已被访问过的链接。 |
LVHA 顺序: 在为链接定义样式时,建议遵循 :link
-> :visited
-> :hover
-> :active
的书写顺序。这是一个经典的记忆法则 “LoVe HAte”,可以确保 :hover
和 :active
的效果不会被 :link
或 :visited
覆盖掉。
1 | <style> |
3.3.2. 结构性伪类
这类伪类根据元素在 DOM 树中的位置或结构关系来选择元素,非常强大。
伪类 | 描述 |
---|---|
:first-child | 匹配作为其父元素的 第一个 子元素的元素。 |
:last-child | 匹配作为其父元素的 最后一个 子元素的元素。 |
:nth-child(n) | 匹配作为其父元素的 第 n 个 子元素的元素。 |
:nth-of-type(n) | 匹配作为其父元素的 第 n 个同类型 的元素。 |
:not(selector) | 匹配不符合 selector 的所有元素。 |
n
可以是数字、关键字 (odd(奇数)
, even(偶数)
) 或公式 (3n+1
)。
1 |
|
li:nth-child(2)
和 li:nth-of-type(2)
有什么区别?它们看起来很像。
这是一个非常关键的区别!
li:nth-child(2)
的意思是:“找到一个元素,它必须是其父元素的 第 2 个 孩子,并且它自己 恰好 还是一个 <li>
元素”。如果第 2 个孩子是 <div>
,那么这个选择器就什么也选不中。
而 li:nth-of-type(2)
的意思是:“在其父元素的所有 <li>
孩子中,找到 第 2 个 <li>
”。它会忽略其他类型的兄弟元素。
简单说,nth-child
是“先定位,再看类型”,而 nth-of-type
是“先按类型分组,再定位”。在有混合类型兄弟元素的场景下,nth-of-type
通常更可靠。
示例: 实现一个“斑马条纹”表格,并为第一行和最后一行添加特殊样式。
1 | <style> |
3.4. 伪元素选择器:创建虚拟元素
伪元素与伪类不同,它不是为已有元素添加特殊状态,而是 创建出一个在 DOM 树中不存在的虚拟元素,并为其添加样式。伪元素在现代 CSS 中以双冒号 ::
开头,以区别于伪类。
伪元素 | 描述 |
---|---|
::before | 在选中元素内容的 前面 插入一个虚拟元素。 |
::after | 在选中元素内容的 后面 插入一个虚拟元素。 |
::first-letter(少用) | 选中块级元素内容的第一个字母。 |
::first-line(少用) | 选中块级元素内容的第一行。 |
::selection(少用) | 匹配用户鼠标选中的文本部分。 |
::placeholder(少用) | 匹配输入框的占位提示文本。 |
关键规则: ::before
和 ::after
创建的虚拟元素默认是 行内元素。它们必须包含 content
属性(即使是 content: '';
)才能生效。
示例: 使用 ::before
和 ::after
为引用文本添加装饰性的引号,并自定义选中文本的样式。
1 | <style> |
3.5. 实战应用:构建一个带分隔线的导航菜单 (修正版)
目标: 创建一个如下图所示的,干净、稳定、带分隔线的水平导航菜单。
动手思路
- HTML 结构: 使用
<ul>
和<li>
构建导航的语义化骨架。 - 水平布局: 为
<li>
设置display: inline-block;
实现水平排列,并移除<ul>
的默认列表样式。 - 交互样式: 为
<li>
添加:hover
伪类以改变背景色,并为<a>
设置padding
和基础样式。 - 添加分隔线: 为每个
<li>
添加border-right
来创建分隔线,这比使用伪元素更稳定。 - 移除末尾分隔线: 使用
:last-child
伪类,选中最后一个<li>
,并将其border-right
移除。
Html 结构如下:
1 | <nav class="main-nav"> |
3.6. 本章核心速查总结
分类 | 关键项 | 核心描述 |
---|---|---|
属性选择器 | [attr^=val] , [attr$=val] | 根据属性值的 开头 或 结尾 进行匹配,常用于链接样式。 |
动态伪类 | :hover , :focus , :active | 实现 UI 交互效果的三剑客。 |
结构性伪类 | :nth-child(n) | 先找第 n 个孩子,再判断类型是否匹配。 |
p:nth-of-type(n) | (推荐) 先按 p 类型分组,再找该类型的第 n 个。 | |
:not(selector) | 排除特定元素,非常实用。 | |
伪元素 | ::before , ::after | (核心) 创建虚拟的行内元素,必须包含 content 属性。 |
::selection | 自定义用户用鼠标选中文本时的背景和颜色。 | |
::placeholder | 自定义输入框占位文本的样式。 |
第四章:精通文本样式:字体、排版与装饰
摘要: 在之前的章节中,我们已经为了完成布局和交互案例,初步使用了一些基础的文本与字体属性。本章将对这些属性进行一次系统性的、深入的讲解。我们将从基础的 font-family
、font-size
开始,学习如何为网页设定统一且美观的视觉基调;然后,我们会掌握 text-align
、line-height
等排版工具,优化用户的阅读体验。最重要的是,本章将引入实战模块,指导您将在第三章学到的高级选择器知识,应用于构建自定义按钮、美化文章列表等常见网页组件。
在本章的学习地图中,我们将:
- 首先,深入 字体属性 (
font
),掌握设定网页视觉基调的工具。 - 接着,探索 文本属性 (
text
),学会精细化地优化段落的阅读体验。 - 然后,学习一些 进阶文本控制 技巧,解决文本溢出和垂直对齐等常见问题。
- 最后,在 实战环节 中,将所有理论知识融会贯通,亲手打造实用的网页组件。
4.1. 字体属性 (font):奠定视觉基调
字体是网页设计的灵魂。合适的字体属性不仅关乎美观,更直接影响内容的可读性和用户体验。
4.1.1. font-family:指定字体
font-family
属性用于设置文本的字体。由于我们无法保证用户的电脑上安装了我们想要的所有字体,最佳实践是提供一个备选列表,也就是“字体栈”。
痛点背景: 你精心设计了一个使用小众字体的网站,但在用户的电脑上却因为缺少该字体而显示为普通的宋体,完全破坏了设计感。
解决方案: 提供一个优雅降级的字体列表。浏览器会从左到右依次尝试,直到找到第一个可用的字体。列表最后通常会以一个通用的字体族(如 sans-serif
)结尾,确保最坏情况下也能显示正确的字体风格。
1 | .serif-text { |
当字体名称包含空格时(如 “Times New Roman”),必须用引号将其包裹起来。
4.1.2. font-size:控制大小
font-size
用于设置字体大小。在第一章我们已经接触过单位,这里我们重点对比其实际应用。
px
: 像素,绝对单位,大小固定,适合需要精确控制的场景。em
: 相对单位,相对于 父元素 的字体大小。1.2em
表示父元素字体大小的 1.2 倍。rem
: (推荐) 相对单位,只相对于 根元素 (<html>
) 的字体大小。这使得它在响应式设计中极易管理,只需调整根字号,整个页面的元素就能等比缩放。
比如在做网页适配不同屏幕大小时,用 rem
就很方便。假设在 html
根元素设置 font-size: 16px
,那么页面中 1rem
就相当于 16px
,2rem
就是 32px
。如果要做一个适配手机和平板的网页,当平板屏幕更宽时,把 html
的 font-size
调整为 20px
,那么原本设置为 1rem
的元素尺寸就会从 16px
变为 20px
,其他以 rem
为单位的元素也会相应等比例变化,这样就能快速实现整体布局和字体大小的响应式调整。
4.1.3. font-weight:控制粗细
font-weight
用于设置字体的粗细。可以使用关键字或数字值。
- 关键字:
normal
(默认值,等同于400
),bold
(粗体,等同于700
)。 - 数字值: 从
100
(最细) 到900
(最粗),以 100 为步长。
1 |
|
4.1.4. font-style:控制样式
font-style
主要用于设置文本是否倾斜。
normal
: 正常显示。italic
: 以斜体显示。
1 | <p style="font-style:normal;">Font Style Normal</p> |
4.1.5. line-height:控制行高
line-height
定义了每行文本所占据的垂直空间,是排版中至关重要的属性。文字在行高所定义的空间内是 垂直居中 的。
经典技巧:单行文本垂直居中
当一个块级元素的 height
和 line-height
设置为相同的值时,其中的单行文本就能实现完美的垂直居中。
1 | <style> |
4.1.6. font (简写属性)
为了简化代码,我们可以使用 font
简写属性。顺序非常重要,至少需要指定 font-size
和 font-family
。
这个在开发中会比较少用一点,且阅读性较差,毕竟 font-weight 类似于这样的属性他的语义化更为清晰
语法: font: font-style font-weight font-size/line-height font-family;
1 | p { |
4.2. 文本属性 (text):优化阅读体验
这类属性用于控制文本段落的整体外观和布局。
color
: 设置文字颜色。text-align
: 设置块内文本的 水平对齐 方式。可选值有left
,right
,center
,justify
(两端对齐)。text-decoration
: 添加或移除文本装饰。none
(无装饰) 常用于移除<a>
标签的默认下划线;underline
(下划线);line-through
(删除线)。text-indent
: 设置块内文本的 首行缩进。text-indent: 2em;
是一个经典设置,表示缩进两个当前字体的宽度。letter-spacing
/word-spacing
: 分别用于微调 字符之间 和 单词之间 的间距。
没指定单位时,line-height
默认是以当前元素 font-size
为基准的倍数,1.6 就表示行高是字体大小的 1.6 倍。这样设置在继承时更灵活,子元素会用自身字体大小乘以这个倍数来计算行高。
1 | <style> |
4.3. 进阶文本控制
4.3.1. 文本溢出处理
痛点背景: 当一段很长的文本(如文章标题)被放进一个固定宽度的容器时,如果文本不换行,就会溢出容器,破坏布局。
解决方案: 使用“三件套”实现经典的“文本溢出显示省略号 (...
)”效果。
white-space: nowrap;
: 强制文本在同一行显示,不自动换行。overflow: hidden;
: 隐藏超出容器宽度的部分。text-overflow: ellipsis;
: 将被隐藏的部分用省略号代替。
1 | <style> |
4.3.2. vertical-align:垂直对齐
这是一个非常容易被误解的属性。
核心要点: vertical-align
只作用于 行内元素 (inline) 和行内块元素 (inline-block)。它控制的是一个元素相对于它所在的 那一行 的基线 (baseline) 的对齐方式,而不是用于块级元素的垂直居中。
痛点背景: 你想让一张小图标和旁边的文字在垂直方向上对齐。
解决方案: 使用 vertical-align: middle;
。
1 | <style> |
4.4. 实战:样式化常见元素
现在,我们将综合运用本章以及第三章的知识,完成两个常见的实战任务。
4.4.1. 实战一:从链接到按钮
任务: 将一个普通的 <a>
标签,通过 CSS 样式化为一个具有背景色、圆角、悬停效果的现代化按钮。
1 | <style> |
4.4.2. 实战二:美化文章列表
任务: 去除 <ul>
的默认项目符号,并为其添加自定义的图标作为新的项目符号。
1 | <style> |
4.5. 本章核心速查总结
分类 | 关键项 | 核心描述 |
---|---|---|
字体 | font-family | 设置字体栈,以通用字体族结尾,如 sans-serif 。 |
font-size | (推荐) 使用 rem 单位,便于实现整站响应式缩放。 | |
line-height | 控制行高,可通过 height: value; line-height: value; 实现单行垂直居中。 | |
font | 简写属性,顺序: style weight size/line-height family 。 | |
文本 | text-align | 控制块内文本 水平 对齐。 |
text-decoration | none 常用于移除链接下划线。 | |
text-overflow | ellipsis 配合 overflow:hidden 和 white-space:nowrap 实现溢出省略号。 | |
对齐 | vertical-align | (仅限行内/行内块) 控制元素在 行内 的垂直对齐。 |
4.6. 疑难解答
Prorise,我有点搞不懂 em
和 rem
,它们好像都是相对单位,什么时候该用哪个呢?
问得好!这是初学者最容易混淆的地方。em
是相对于它的父元素,如果层层嵌套,计算起来就会像套娃一样,很麻烦。
而 rem
只跟根元素 <html>
挂钩。所以你只要改一个地方,整个页面的元素大小都能“听话”地一起缩放,做响应式设计时特别方便。所以,记住一句话:做项目,优先用 rem
。
我看到一个技巧说把 height
和 line-height
设置成一样的值,文字就垂直居中了,这是什么原理?
对的,这是个很经典的方法。你可以把 line-height
想象成每一行文字被包裹在一个“隐形”的盒子里,文字本身在这个盒子里面是垂直居中的。当你把这个“隐形盒子”的高度(line-height
)撑得和外部容器的 height
一样高时,文字自然也就居中了。不过要记住,这个方法只对单行文本有效。
那 vertical-align
呢?我试了 vertical-align: middle
想让一个 div 居中,但完全没反应。
这是另一个常见陷阱!vertical-align
是个“内联世界的规则”,它只对 inline
或 inline-block
元素起作用,用来调整它们在同一行文字里的对齐位置。而 div
默认是块级元素,自己就占了一整行,没有可以相对齐的“邻居”,所以 vertical-align
对它无效。要让块级元素垂直居中,我们需要动用更强大的布局工具,比如我们后面要学的 Flexbox。
第五章:精通视觉表现:背景、列表与装饰
摘要: 本章我们将专注于提升页面的视觉表现力。您将系统学习如何使用强大的 background
属性为元素添加颜色、渐变、图片等丰富的背景效果,此外,我们还将深入探讨列表、轮廓的自定义样式,以及如何利用 z-index
控制元素的层叠顺序,为您的网页增添更多精致的细节。
在本章的学习地图中,我们将:
- 首先,深入探索 背景 (
background
) 属性全家桶,学习如何为元素打造丰富的视觉层次。 - 接着,我们将学习如何通过 列表样式 (
list-style
) 来自定义项目符号。 - 然后,我们将辨析 轮廓 (
outline
) 与边框的区别,并学习如何控制元素的 层叠顺序 (z-index
)。 - 最后,我们将通过 核心速查总结 来巩固本章所有知识点。
5.1. 背景 (background):网页的“皮肤”
背景是元素内容之下的“画布”,通过一系列 background-*
属性,我们可以精确地控制这个画布的外观。
5.1.1. 核心背景属性
属性 | 说明 | 常用值举例 |
---|---|---|
background-color | 设置纯色背景 | #FFF , rgb(0,0,0) , transparent |
background-image | 设置背景图片 | url('path/to/image.jpg') |
background-repeat | 控制图片平铺方式 | no-repeat (不平铺, 只显示一次), repeat (平铺) |
background-position | 设置图片位置 | center , top right , 50% 50% |
background-size | 控制图片尺寸 | cover (铺满), contain (完整显示) |
background-attachment | 背景是否随页面滚动 | scroll (滚动), fixed (固定) |
background (简写) | 将以上属性写在一行 | blue url(...) no-repeat center / cover |
简写属性 background
顺序提示:
color
image
repeat
attachment
position
/ size
(注意 size
前必须有 /
)
5.1.2. 核心实战技巧
除了基础属性的设置,background
属性的真正威力体现在其组合应用上。以下是三个在开发中几乎必然会遇到的实战技巧。
技巧一:实现半透明背景 (rgba vs opacity)
- 场景: 需要一个半透明的叠加层,但又不希望层内的文字也变透明。
- 方案: 使用
background-color: rgba(...)
而非opacity
。
1 | <style> |
技巧二:全屏背景图 (Full-Screen Background)
- 场景: 网站的首页、登录页或活动页,需要一张高清大图作为背景,铺满整个浏览器视口。
- 方案: 将背景图应用到
html
或body
标签,并结合background-size: cover
和background-attachment: fixed
。
1 |
|
技巧三:用背景图优雅填充盒子)
- 场景: 卡片列表、相册或用户头像展示。容器尺寸是固定的,但内部的图片高宽比各不相同,需要让图片填满容器且不被拉伸变形。
- 方案: 不要使用
<img>
标签,而是用一个<div>
作为容器,并将图片设为其background-image
,再利用background-size
控制填充方式。
1 | <style> |
5.2. 列表样式 (list-style)
在第四章的实战中我们学习了使用伪元素 ::before
来创建更灵活的自定义列表符号,对于 list-style 我们最常用的仅仅只是将它设置为 none 即无符号
list-style-type
: 改变项目符号的类型,例如square
(方块),circle
(空心圆),upper-roman
(大写罗马数字),none
(无符号)。list-style-position
:outside
(默认,符号在列表项外) 或inside
(符号在列表项内,会随文本缩进)。list-style-image
: 使用url()
指定一张图片作为项目符号。list-style
(简写属性):list-style: type position image;
。
1 | <style> |
5.3. 轮廓 (outline) 与层叠 (z-index)
5.3.1. 轮廓 (outline):不占空间的“高亮框”
outline
是绘制于元素 border
之外的一条线,它与 border
最大的区别在于:
核心区别: outline
不属于 盒模型的一部分,它不占据任何布局空间,不会把其他元素推开。而 border
会增加元素的实际尺寸,影响布局。
outline
常用于调试或在元素获得焦点时(:focus
)提供视觉反馈,在开发中我们也并不是很常用,简单了解即可
outline-style
:solid
,dashed
,dotted
等。outline-width
: 轮廓宽度。outline-color
: 轮廓颜色。outline-offset
: 轮廓与边框之间的距离。
1 | <style> |
5.3.2. z-index:控制元素的堆叠顺序
网页是三维的,除了 X 轴和 Y 轴,还存在一个垂直于屏幕的 Z 轴。z-index
属性就用于控制元素在 Z 轴上的堆叠顺序。
前置条件: z-index
属性 仅在 元素定义了 position
属性(且值不为 static
)时才有效。我们将在下一章详细学习 position
,这里先作初步了解。
z-index
的值是一个整数,可以是正数、负数或 0。- 值越大的元素,层级越高,会显示在值小的元素的上方。
- 如果没有设置
z-index
,则在 HTML 中后出现的元素会叠在先出现的元素之上。
1 | <style> |
5.4. 本章核心速查总结
分类 | 关键项 | 核心描述 |
---|---|---|
背景 | background-color | 使用 rgba() 实现仅背景半透明,是最佳实践。 |
background-size | cover (裁剪铺满) 和 contain (完整显示) 是响应式背景的关键。 | |
background-position | 配合精灵图(Sprites)使用负值来定位图标,是性能优化技巧。 | |
background | 简写属性,顺序: color image repeat attachment position / size 。 | |
列表 | list-style-type | 设置项目符号样式,可用 none 去除。 |
list-style-position | inside (内) 或 outside (外)。 | |
轮廓 | outline | 不占据布局空间,不影响周围元素,常用于 :focus 状态。 |
层叠 | z-index | 必须配合 position (非 static ) 使用。数值越大,层级越高。 |
第六章:CSS 布局:从 Flexbox 到 Grid 的布局之道
摘要: 欢迎来到 CSS 世界的“终局之战”——布局。可以毫不夸张地说,掌握了布局,就等于掌握了 99% 的 CSS。本章是一个内容极其丰富的“大章节”,我们将系统性地学习从一维的 Flexbox 到二维的 Grid 这两大现代布局利器,并掌握 Position 定位的精准微操与 Multi-column 的巧妙应用。更重要的是,我们会将所有这些技术融合进“响应式设计”的思维框架中,让您有能力构建适应任何屏幕尺寸的现代化网页。请务必多加练习,本章的知识将是您未来前端生涯中最宝贵的财富。
学习路径说明: 您会注意到,本章我们将重点讲解 Flexbox 和 Grid,而对 float
(浮动) 等传统技术则一笔带过。这是因为,float
最初是为“图文环绕”而设计的,用它来做全局布局是一种“滥用”,会带来层叠塌陷、需要清除浮动等无穷的副作用,在 2025 年的今天,它已被现代布局方案完全取代。我们的目标是直接学习当前业界的最佳实践,而非背负历史包袱。
在本章的学习地图中,我们将一步步成为布局大师:
- 首先,我们将掌握 一维布局的王者——Flexbox,完美解决组件内的对齐问题。
- 接着,我们将学习 二维布局的终极方案——Grid,随心所欲地绘制整个页面蓝图。
- 然后,我们会探索 多列布局 (Multi-column) 的妙用,用最简单的代码实现瀑布流。
- 之后,我们将学习 Position 定位,掌握脱离常规文档流的“魔法”。
- 最后,我们将所有知识融会贯通,学习 响应式设计的核心,让我们的页面在手机、平板和桌面端都能完美呈现。
6.1. Flexbox 弹性布局:一维空间的统治者
Flexbox 是为 一维布局 而生的。无论是水平行内还是垂直列内,只要你需要在一条轴线上对齐、分布、排序一组元素,Flexbox 就是最简单、最强大的工具。
6.1.1. 核心概念:主轴与交叉轴
一旦为一个元素设置了 display: flex;
,它就成为了一个 Flex 容器 (flex container),其所有直接子元素都自动成为 Flex 项目 (flex item)。
容器内部存在两根无形的轴:
- 主轴 (main axis): 所有项目默认沿着主轴排列。默认是水平方向。
- 交叉轴 (cross axis): 与主轴垂直的轴。默认是垂直方向。
6.1.2. 容器属性 (Flex Container)
这些属性写在 父元素 上,用于指挥所有子元素的整体排列。我们将逐一深入讲解。
1. flex-direction
:定义主轴方向
此属性决定了项目排列的 方向,即主轴是水平还是垂直。
值 | 描述 |
---|---|
row | 默认值。主轴为水平方向,起点在左端。 |
row-reverse | 主轴为水平方向,起点在右端。 |
column | 主轴为垂直方向,起点在上沿。 |
column-reverse | 主轴为垂直方向,起点在下沿。 |
1 | <style> |
2. flex-wrap
:定义是否换行
此属性决定了当一条轴线排不下所有项目时,项目是否换行。
值 | 描述 |
---|---|
nowrap | 默认值。不换行,所有项目会被压缩以适应单行。 |
wrap | 换行,第一个项目在新行的上方。 |
wrap-reverse | 换行,第一个项目在新行的下方。 |
1 | <style> |
3. justify-content
:定义主轴对齐方式
这是最常用的容器属性之一,它定义了项目在 主轴 上的对齐和分布方式。
值 | 描述 |
---|---|
flex-start | 默认值。项目向主轴起点对齐。 |
flex-end | 项目向主轴终点对齐。 |
center | 项目在主轴上居中。 |
space-between | 两端对齐,项目之间的间隔都相等。 |
space-around | 每个项目两侧的间隔相等。项目之间的间隔比项目与边框的间隔大一倍。 |
space-evenly | 所有间隔完全相等,包括项目与边框之间。 |
1 | <style> |
4. align-items
:定义交叉轴对齐方式 (单行)
它定义了项目在 交叉轴(默认是垂直方向)上的对齐方式。
值 | 描述 |
---|---|
stretch | 默认值。如果项目未设置高度或设为 auto,将占满整个容器的高度。 |
flex-start | 交叉轴的起点对齐。 |
flex-end | 交叉轴的终点对齐。 |
center | 交叉轴的中点对齐。 |
1 |
|
5. align-content
:定义多行内容的对齐方式
注意: 此属性仅在项目 换行 后(即 flex-wrap: wrap;
且有多行内容时)才生效。它控制的是 多根轴线 作为一个整体,在交叉轴上的对齐方式。
值 | 描述 |
---|---|
stretch | 默认值。轴线占满整个交叉轴。 |
flex-start | 与交叉轴的起点对齐。 |
flex-end | 与交叉轴的终点对齐。 |
center | 与交叉轴的中点对齐。 |
space-between | 与交叉轴两端对齐,轴线之间的间隔平均分布。 |
space-around | 每根轴线两侧的间隔都相等。 |
1 | <style> |
6. flex-flow
:方向与换行的简写
flex-flow
是 flex-direction
和 flex-wrap
两个属性的简写形式,用的很少,知道就可以了
1 | .container { |
6.1.3. 项目属性 (Flex Item)
这些属性写在 子元素(项目) 上,用于定义单个项目的特殊行为。
属性 | 核心描述 |
---|---|
order | 改变项目排列顺序 (数值越小越靠前) |
flex-grow | 定义项目的放大比例 (分配剩余空间) |
flex-shrink | 定义项目的缩小比例 (处理空间不足) |
flex-basis | 定义项目的基础尺寸 |
flex | (核心) 上面三者的简写,如 flex: 1 1 0 ,代表着 |
align-self | 允许单个项目覆盖容器的 align-items |
1 | <style> |
6.1.4. 实战:通过游戏学习布局
任务: 通关 24 关 flexboxfroggy,通过我们学习的知识
6.2. Grid 网格布局:二维平面的上帝视角
如果说 Flexbox 是一维的专家,那么 Grid 就是二维布局的上帝。它将容器划分为行和列,允许我们将项目精确地放置在任意单元格中,是构建整个页面宏观布局的终极方案。
6.2.1. 核心概念
- Grid 容器 (grid container): 应用
display: grid
的元素。 - Grid 项目 (grid item): 容器的直接子元素``。
- Grid 线 (grid line): 划分网格的水平和垂直线。
- Grid 轨道 (grid track): 两条相邻网格线之间的空间(即一行或一列)。
- Grid 单元格 (grid cell): 四条网格线包围的最小单位。
- Grid 区域 (grid area): 一个或多个单元格组成的矩形区域。
6.2.2. 容器属性
这些属性写在父元素上,用于定义整个网格的结构和对齐方式。
1.定义网格轨道
- grid-template-columns
- grid-template-rows
这两个核心属性分别用于定义网格的列和行。
值 | 描述 |
---|---|
<length> | 使用 px , em 等固定单位。 |
<percentage> | 使用相对于容器尺寸的百分比。 |
fr | (核心) "分数"单位,用于按比例分配可用空间。 |
repeat() | 用于创建重复的轨道模式,如 repeat(3, 1fr) 表示创建3个等宽的列。 |
minmax() | 定义一个尺寸范围,如 minmax(100px, 1fr) 表示最小100px,最大占一份。 |
auto | 由浏览器根据内容决定尺寸。 |
1 |
|
2.定义网格区域
- grid-template-areas
这是一个极具表现力的属性,允许你通过“画出”区域名称来定义布局。
值 | 描述 |
---|---|
字符串 | 每个字符串代表一行,字符串内的名称定义了该行的列区域。 |
. | 一个点号 (. ) 代表一个空的单元格。 |
1 |
|
grid-area
是一个功能非常强大的属性,它既可以用于将项目放置到命名区域,也可以作为基于网格线定位的终极简写形式。
方式一:分配到命名区域
这是 grid-area
与 grid-template-areas
配合使用的场景,用法非常直观,也如上述示例一样
方式二:作为网格线定位的简写grid-area
也是 grid-row-start
/ grid-column-start
/ grid-row-end
/ grid-column-end
四个属性的简写。
语法: grid-area: <row-start> / <col-start> / <row-end> / <col-end>;
1 |
|
3. gap
:定义网格间距
用于设置行与行、列与列之间的间距。
值 | 描述 |
---|---|
gap: <row-gap> <column-gap>; | 分别设置行间距和列间距。 |
gap: <value>; | 行间距和列间距都设为同一个值。 |
4. 单元格内容对齐
这两个属性用于控制项目内容在其所在的单元格内部的对齐方式。可以把单元格想象成一个小房间,而项目内容(文字、图片等)就是房间里的家具,*-items
决定了家具如何在这个房间里摆放。
属性 | 核心描述 |
---|---|
justify-items | 单元格内容的水平对齐 |
align-items | 单元格内容的垂直对齐 |
start
: 对齐到单元格的起始边(左/上)。end
: 对齐到单元格的结束边(右/下)。center
: 在单元格内居中。stretch
: (默认值) 将项目内容拉伸,填满整个单元格空间。
1 |
|
5. 网格整体对齐
核心前提:这两个属性只有在网格的总尺寸小于其容器尺寸时才会生效。它们控制的是整个网格(所有单元格作为一个整体),在容器这个“大画框”里的对齐和分布方式。
属性 | 核心描述 |
---|---|
justify-content | 整个网格作为一个整体的水平对齐与分布 |
align-content | 整个网格作为一个整体的垂直对齐与分布 |
start
: 整体网格靠向容器的起始边(左/上)。end
: 整体网格靠向容器的结束边(右/下)。center
: 整体网格在容器内居中。space-between
/space-around
/space-evenly
: 控制网格轨道之间的分布方式。
1 |
|
6.2.3. 项目属性 (Grid Item)
这些属性写在**子元素(项目)**上,用于定义单个项目在网格中的位置和行为。
1. 基于网格线定位
通过指定项目从哪条网格线开始、到哪条网格线结束,来放置项目。
属性 | 描述 |
---|---|
grid-column-start / end | 定义项目占据的列范围。 |
grid-row-start / end | 定义项目占据的行范围。 |
grid-column / grid-row | 上述属性的简写,如 1 / 3 或 1 / span 2 。 |
1 |
|
2. justify-self
和 align-self
允许单个项目覆盖容器定义的 justify-items
和 align-items
,实现独立对齐。
属性 | 描述 |
---|---|
justify-self | 单个项目内容的水平对齐 |
align-self | 单个项目内容的垂直对齐 |
1 |
|
6.2.4. 实战:通过游戏学习布局
任务: 通关 28 关 Grid Garden,通过我们学习的知识,将萝卜种到它们该去的地方。
6.3. Position 定位:脱离常规的精准微操
摘要: 本节我们将学习一种全新的布局维度——定位 (Positioning)。您将学习如何使用 position
属性,让元素“脱离”常规的文档流,实现覆盖、固定、粘滞等高级效果。这是实现模态框、下拉菜单、固定导航栏等复杂 UI 组件的必备知识。
6.3.1. 核心前提:理解文档流
在学习定位之前,我们必须先清晰地理解什么是“常规文档流”。在默认状态下,页面元素会遵循一套既定的排列规则:
- 块级元素 (Block): 从上到下垂直排列,每个元素独占一行。
- 行内元素 (Inline): 在水平方向上从左到右依次排列,遇到行尾会自动换行。
这套规则就是文档流。而 position
属性,就是赋予我们打破这套常规规则,让元素“飞”出常规队列的能力。
1 | <style> |
6.3.2. 定位五模式核心对比
position
属性共有五个值,下表可以帮助我们从宏观上快速把握它们的核心区别。
模式 | 脱离文档流 | 定位参照物 | 核心应用场景 |
---|---|---|---|
static | 否 | 无 | 默认状态,无定位 |
relative | 否 (仍占原始空间) | 自身原始位置 | 作为 absolute 的参照物 |
absolute | 是 | 最近的非 static 祖先 | 弹窗、角标、覆盖层 |
fixed | 是 | 浏览器视口 | 固定导航、返回顶部 |
sticky | 滚动到阈值后 | 最近的滚动父级 | 吸顶导航、表格标题 |
6.3.3. 核心模式详解与实战
相对定位 (relative
)
相对定位非常特殊,它遵循“身在曹营心在汉”的原则:
- 它在文档流中依然占据着原来的空间,不会影响其他元素的布局。
- 它可以使用
top
,right
,bottom
,left
属性,相对于自己的原始位置进行偏移。
1 | <style> |
绝对定位 (absolute
) 与 “父相子绝”
这是定位中最核心、最重要的应用模式。
position: absolute;
会让元素完全脱离文档流。- 它会向上寻找所有祖先元素,以第一个
position
值不为static
的祖先元素作为自己的定位参照物。 - 如果找不到这样的祖先,它最终会相对于
<body>
定位。
为了将一个绝对定位元素限制在其直接父元素内部,我们诞生了黄金组合——“父相子绝”:
- 父级:
position: relative;
(让父级成为定位参照物,但自身不脱离文档流) - 子级:
position: absolute;
(让子级脱离文档流,并相对于父级定位)
实战: 在卡片右上角添加“Hot”徽章。
1 | <style> |
固定定位 (fixed
)
position: fixed;
会让元素脱离文档流,并相对于浏览器视口进行定位。这意味着即使用户滚动页面,该元素的位置也永远不会改变。
实战: “返回顶部”按钮
1 |
|
6.3.4. 综合实战:创建一个居中模态框 (Modal)
任务: 综合运用 position: fixed
和 z-index
,创建一个覆盖全屏的半透明遮罩层,并在其上居中显示一个模态框。
1 |
|
6.4. 多列布局 (Multi-column):优雅实现内容分栏与瀑布流
摘要: 本节我们将学习一个巧妙而高效的布局工具——多列布局。您将学习如何像排版报纸和杂志一样,轻松地将大段文本内容分割成多列以提升可读性。更重要的是,我们将通过一个实战案例,向您展示如何仅用三行核心 CSS 代码就实现一个完美的、响应式的图片瀑布流布局,这是一个在现代网页设计中非常流行且实用的技巧。
6.4.1. 核心属性详解
多列布局的所有属性都应用于容器元素,它会将容器内的所有子元素(无论块级还是行内)自动分配到各列中。
属性 | 核心描述 |
---|---|
column-count | 固定列的数量。 |
column-width | 定义每列的理想宽度,浏览器会据此自动调整列数,实现响应式。 |
columns | count 和 width 的简写属性。 |
column-gap | 定义列与列之间的间距。 |
column-rule | 定义列与列之间的分隔线样式,语法与 border 类似。 |
column-span:all | 让标题横跨所有列 |
break-inside:avoid | 避免在元素内部断开换行,让元素尽量完整显示在同一列。 |
深入讲解 column-count
与 column-width
这两个属性是多列布局的核心,通常我们只使用其中一个来驱动布局:
column-count
(固定列数): 当你希望布局始终保持特定数量的列(例如,一个三栏文章),无论容器宽度如何变化时,使用此属性。column-width
(自适应列数): 当你希望布局响应式地变化时,使用此属性。你只需定义一个“理想”的列宽(例如200px
),浏览器会自动计算在当前容器宽度下,能容纳多少个这样的列。当容器变宽,列数会自动增加;容器变窄,列数会自动减少。这是实现响应式瀑布流的关键。
6.4.2. 实战应用
实战一:报纸式文章排版
任务: 将一段长文本自动格式化为三列,并在列与列之间添加一条浅灰色分隔线,同时让文章标题横跨所有列。
1 | <style> |
实战二:纯 CSS 图片瀑布流
任务: 创建一个响应式的图片瀑布流布局。图片会根据浏览器窗口宽度自动重新排列成不同的列数,并且每张图片都保持完整,不会被列分割。
1 |
|
请尝试在此将代码复制到Vs Code中,启用 F12 浏览器 拉动浏览器窗口查看效果
6.5. 响应式设计:让布局适应万千屏幕
摘要: 本节我们将学习现代网页开发的基石——响应式设计。这并非一种新的布局技术,而是一种设计思想与方法论。我们将学习其三大核心支柱:流式网格、弹性图片和媒体查询。通过掌握这些,您将能够让一套代码在手机、平板和桌面电脑上呈现出截然不同却都同样完美的布局效果,为所有用户提供最佳的浏览体验。
6.5.1. 核心概念与基石
响应式设计的实现依赖于几项关键的 CSS 技术和开发思想。
视口 (Viewport) 元标签
这是开启移动端适配的必备第一步,是响应式设计的“准生证”。这行代码必须被添加到 HTML 文件的 <head>
标签中。
1 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
它告诉移动端浏览器:
width=device-width
: 将视口的宽度设置为设备的屏幕宽度。initial-scale=1.0
: 页面的初始缩放比例为 1.0,即不缩放。
如果没有这行代码,移动端浏览器会默认使用一个桌面宽度的“虚拟视口”(通常是 980px)来渲染页面,然后将整个页面缩小,导致文字变得极小,布局混乱。
媒体查询 (Media Queries)
媒体查询是响应式设计的技术核心,它像一个 CSS 的 if
语句,允许我们为满足特定条件的设备应用特定的样式。
语法: @media (媒体特性) { /* 在此条件满足时应用的 CSS 规则 */ }
常用媒体特性 | 描述 | 示例 |
---|---|---|
min-width | 当视口宽度 大于或等于 指定值时应用样式。 | @media (min-width: 768px) |
max-width | 当视口宽度 小于或等于 指定值时应用样式。 | @media (max-width: 767px) |
orientation | portrait (竖屏) 或 landscape (横屏)。 | @media (orientation: landscape) |
设计思想:移动优先
这是一种重要的现代响应式设计策略。我们不再先为大屏幕设计,再去“修补”小屏幕的样式。而是反过来:
- 先编写基础样式: 这些样式服务于最小的设备(手机),保证核心功能和内容的完美呈现。这些代码写在所有
@media
规则之外。 - 逐步增强: 使用
min-width
媒体查询,为更大的屏幕(如平板、桌面)追加更复杂的样式和布局。
“移动优先”的优势:
- 性能更佳: 移动设备只需加载最核心、最轻量的 CSS。
- 代码更清晰: 避免了在媒体查询中大量重置和覆盖桌面端样式,代码逻辑是不断“增加”而非“修改”。
- 体验更专注: 强迫我们优先考虑移动端用户的核心体验。
6.5.2. 断点的选择
“断点”是指布局发生显著变化的屏幕宽度临界点。选择哪些断点并没有绝对的标准,最佳实践是根据你的内容来决定在何时需要改变布局。不过,业界通常会参考一些主流 UI 框架(如 Bootstrap)的约定,这有助于团队协作。
一套常用的断点参考:
设备类型 | 断点 | 描述 |
---|---|---|
手机 (Mobile) | < 768px | 默认样式,通常为单列布局。 |
平板 (Tablet) | ≥ 768px | 布局开始变为多列,空间更宽裕。 |
桌面 (Desktop) | ≥ 992px | 经典的桌面端宽屏布局。 |
大桌面 (Large Desktop) | ≥ 1200px | 为超宽屏幕提供更丰富的布局。 |
6.5.3. 实战:将 Grid 首页布局改造为响应式
任务: 我们将以 6.2.3
节中创建的经典网站布局为基础,采用“移动优先”的策略,为其添加响应式能力。
1 |
|
请尝试在此将代码复制到Vs Code中,启用 F12 浏览器 拉动浏览器窗口查看效果
6.6. 最后的拼图:理解 Float
摘要: 在本章的最后,我们将回顾一个在 CSS 历史上扮演过重要角色、但如今已回归其本职的属性——float
。本节的目标不是让您用它来构建复杂的布局,恰恰相反,是让您理解它的唯一正确应用场景(图文环绕),并能看懂和维护那些使用浮动布局的“历史遗留”代码。我们将重点讲解浮动带来的“高度塌陷”问题以及经典的“清除浮动”解决方案。
6.6.1. Float 的唯一正确用途:图文环绕
float
属性最初被设计出来的唯一目的,就是为了实现类似报纸、杂志中的图文环绕排版效果。通过设置 float: left;
或 float: right;
,可以让一个元素(通常是图片)脱离正常的文档流,移动到其容器的左侧或右侧,其后的文本内容则会环绕在该元素的周围。
1 | <style> |
6.6.2. 历史遗留问题与解决方案:清除浮动
问题:高度塌陷 (Height Collapse)
痛点背景:当一个父元素内部的所有子元素都设置了浮动时,这些子元素会完全脱离常规文档流。对于父元素来说,它会认为自己“内部没有任何内容”,因此它的高度就会“塌陷”为 0。这将彻底打乱后续元素的布局。
直观演示:
1 | <style> |
解决方案:清除浮动 (Clearfix)
为了解决高度塌陷问题,开发者们创造了多种“清除浮动”的方法。在 2025 年的今天,最常用且最标准的方法是 Clearfix Hack。
它的原理是:利用 ::after
伪元素,在父元素的内容之后添加一个看不见的、块级的、并且设置了 clear: both;
的虚拟元素。clear: both;
这条规则会命令这个虚拟元素“移动到所有浮动元素的下方”,从而迫使父元素必须将高度延伸到这个虚拟元素所在的位置,也就奇迹般地“撑开”了父元素。
标准 Clearfix 代码:
1 | .clearfix::after { |
修复后的代码:
1 | <style> |
现代视角: Clearfix 的整个概念虽然巧妙,但也体现了使用 float
进行布局的复杂性和脆弱性。这正是我们现在拥抱 Flexbox 和 Grid 的根本原因——它们从设计上就避免了这类问题,让布局变得简单、直观和健壮。
第七章:CSS 视觉魔法:从阴影、渐变到滤镜
摘要: 恭喜您已经掌握了 CSS 布局!在本章中,我们将开启一段充满创造力的旅程,深入探索 CSS 提供的丰富视觉效果。您将学习如何控制元素的可见性与透明度,如何使用阴影为页面增添立体感,如何用渐变创造绚丽的背景,以及如何像使用 Photoshop 一样,通过滤镜 (filter
) 实时处理元素的视觉表现。本章将是您从“结构工程师”向“视觉设计师”转变的关键一步。
在本章的学习地图中,我们将:
- 首先,学习如何控制元素的显隐与透明,这是实现动态 UI 的基础。
- 接着,我们将掌握阴影效果,为元素和文本赋予深度和立体感。
- 然后,我们将深入探索渐变背景,创造出比单色背景更丰富、更具吸引力的视觉效果。
- 之后,我们将解锁强大的
filter
(滤镜) 属性,实现以往需要制图软件才能完成的特效。 - 最后,我们会学习一些其他实用的 UI 属性,并用一个综合实战案例来巩固所有知识。
7.1. 显隐与透明:控制元素状态
7.1.1. visibility
属性
visibility
属性用于设置元素是否可见。它与 display: none;
的核心区别在于:
visibility: hidden;
: 元素被隐藏,但在页面布局中依然占据着它原来的空间,就像一个“隐形”的占位符。display: none;
: 元素被彻底隐藏,并且从文档流中移除,不占据任何空间。
值 | 描述 |
---|---|
visible | 默认值,元素可见。 |
hidden | 元素不可见,但仍占据空间。 |
collapse | 主要用于表格行/列,效果类似 hidden 。 |
1 |
|
7.1.2. opacity
属性
opacity
属性用于设置一个元素的透明度,值从 0.0
(完全透明) 到 1.0
(完全不透明)。
重要: opacity
会影响元素本身及其所有子元素。如果你只想让背景半透明而文字保持清晰,应该在第五章学过的 background-color: rgba(...)
。
1 | <style> |
7.2. 阴影效果:box-shadow
与 text-shadow
7.2.1. 盒子阴影 (box-shadow
)
为元素添加阴影是增加页面深度感和层次感最有效的方式之一。
语法: box-shadow: <h-offset> <v-offset> <blur> <spread> <color> <inset>;
- h-offset: 水平偏移量 (正值向右)。
- v-offset: 垂直偏移量 (正值向下)。
- blur: 模糊半径 (值越大越模糊)。
- spread: 扩散半径 (正值使阴影扩大)。
- color: 阴影颜色。
- inset: 将外部阴影变为内部阴影。
1 | <style> |
7.2.2. 文本阴影 (text-shadow
)
text-shadow
的语法更简单,但通过叠加多层阴影,可以创造出惊艳的效果。
语法: text-shadow: <h-offset> <v-offset> <blur> <color>;
1 | <style> |
7.3. 渐变背景 (Gradients)
使用 CSS 渐变可以创建平滑的颜色过渡,替代过去需要用图片才能实现的背景效果。
7.3.1. 线性渐变 (linear-gradient
)
沿直线创建颜色渐变。
1 | <style> |
其他的渐变语法我们开发中不会太常用,为了避免知识点罗列我们就略过了
7.4. 滤镜 (filter
):CSS 中的 Photoshop
filter
属性可以将各种图形效果应用于元素,就像在 Photoshop 中使用滤镜一样。
函数 | 核心描述 |
---|---|
blur(px) | 高斯模糊 |
brightness(%) | 亮度 |
contrast(%) | 对比度 |
grayscale(%) | 灰度(黑白) |
invert(%) | 反相 |
saturate(%) | 饱和度 |
sepia(%) | 褐色(复古) |
hue-rotate(deg) | 色相旋转 |
drop-shadow(...) | (常用) 投射阴影 |
7.4.1. 实战:创建交互式图片效果
任务: 创建一个图片廊,默认显示为灰度图片,当鼠标悬停时,平滑地恢复原彩并放大。
1 | <style> |
7.4.2. drop-shadow()
vs box-shadow
这是两个非常容易混淆的属性,但区别巨大:
box-shadow
: 为元素的矩形边框盒添加阴影。filter: drop-shadow()
: 为元素内容的实际轮廓(包括 PNG 的透明部分)智能地添加阴影。
1 |
|
7.5. 裁剪与蒙版:塑造元素的可见区域
摘要: 本节我们将学习两个强大的视觉特效属性:clip-path
和 mask
。您将学习如何使用 clip-path
将元素裁剪成圆形、多边形等任意形状,打破矩形的束缚。同时,我们还将探索如何利用 mask-image
,通过一张图片或渐变来控制元素的像素级可见性,创造出丰富的淡入淡出和镂空效果。
7.5.1. 裁剪路径 (clip-path
)
clip-path
属性通过定义一个裁剪区域,来决定元素的哪一部分是可见的。区域内的部分会被显示,区域外的部分则会被彻底“剪掉”,变得不可见。
在旧的 CSS 版本中曾有一个 clip
属性,但它功能有限且已被废弃。clip-path
是其现代的、功能强大的替代品。
函数 | 核心描述 & 参数解析 |
---|---|
circle() | 创建圆形。参数为 (半径 at 圆心位置) 。示例: circle(50% at center) |
ellipse() | 创建椭圆形。参数为 (水平半径 垂直半径 at 中心位置) 。示例: ellipse(50% 30% at center) |
inset() | 创建内凹矩形。参数为 (内凹值 round 圆角) 。内凹值遵循 margin 简写,round 可选。示例: inset(10% 10% round 20px) |
polygon() | (最强大) 用一系列 X Y 坐标点创建任意多边形。至少需要三个点。 示例 (三角形): polygon(50% 0, 100% 100%, 0 100%) |
url() | 使用一个外部 SVG <clipPath> 元素的 id 作为裁剪路径。用于实现复杂图形。 示例: url(#my-clip-path) |
- 语法: polygon(x1 y1, x2 y2, x3 y3, …)
- 坐标点: 每一对 x y 值都代表多边形的一个顶点(角)。坐标 0 0 是左上角。
- 至少需要 3 对坐标点才能构成一个面(三角形)。
- 浏览器会自动将最后一个点与第一个点连接起来,形成一个封闭的图形
对于polygon的使用,强烈推荐您收藏 Clippy — CSS clip-path 生成器 网站,他能够快速的帮你创建您几乎所有想创建的图形
实战: 将同一张图片裁剪成不同的形状。
1 | <style> |
7.5.2. 蒙版 (mask
):像素级的视觉控制器
与 clip-path
的硬性裁剪不同,mask
提供了一种更精细、更具艺术性的方式来控制元素的可见性。它不是“剪掉”,而是像透过一块有图案的毛玻璃看东西,玻璃上透明或亮的地方,我们就能看到东西;不透明或暗的地方,东西就被遮挡了。
核心 mask
属性三巨头
在使用蒙版时,我们最先需要掌握的是这三个最核心的属性,它们决定了蒙版的基础形态。
mask-image
(定义蒙版源): 这是最重要的属性,它指定了用作“毛玻璃”的图案。这个图案可以是一张带透明通道的url()
图片,也可以是一个 CSS 渐变。mask-size
(控制蒙版尺寸): 控制蒙版图案的大小,用法与background-size
完全相同,contain
和cover
是最常用的值。mask-repeat
(控制蒙版平铺): 控制蒙版图案是否重复,用法与background-repeat
完全相同。对于形状遮罩,我们通常使用no-repeat
。
实战一:SVG 形状蒙版
任务: 将一张头像图片,通过一个五角星形状的 SVG 文件进行遮罩,使其呈现为五角星形状。
1 | <style> |
实战二:渐变蒙版 (淡出效果)
这是 mask
最巧妙的应用之一。我们无需任何图片,仅用 CSS 渐变就可以创造出优雅的淡出效果。
任务: 为一张图片的底部创造出“淡出至透明”的效果。
1 | <style> |
微调与进阶属性详解
在掌握了 mask-image
等核心属性后,我们可以通过以下属性,像控制背景图一样,对蒙版进行更精细的调整。
1. mask-position
: 定义蒙版位置
此属性用于设置 mask-image
在元素内的起始位置,其用法与 background-position
完全相同。
值 | 描述 |
---|---|
关键字 | top , bottom , left , right , center 的组合 |
<percentage> / <length> | 使用百分比或 px 等单位设置 X Y 坐标 |
1 | <style> |
观察星形蒙版是如何被精确定位到容器右上角的。
2. mask-origin
与 mask-clip
: 定义蒙版原点与裁剪区域
这两个属性共同决定了蒙版的作用范围,它们的参照物都是元素的盒模型(border-box
, padding-box
, content-box
)。
mask-origin
: 定义mask-position
的0 0
坐标从哪里开始计算。mask-clip
: 定义蒙版效果在哪里被裁剪。
值 | 描述 |
---|---|
border-box | 默认值。从边框的外边缘开始计算/裁剪。 |
padding-box | 从内边距的外边缘(即边框的内边缘)开始计算/裁剪。 |
content-box | 从内容区的边缘开始计算/裁剪。 |
1 | <style> |
在示例中,mask-origin: padding-box
让渐变蒙版的左上角从内边距区域开始,而 mask-clip: content-box
则让蒙版的效果只在内容区内生效,不影响内边距和边框。
7.6. 其他实用 UI 属性
7.6.1. resize
属性
允许用户通过拖动来缩放元素的尺寸。
resize
属性需要与 overflow
属性(值为 auto
, hidden
或 scroll
)结合使用才有效。
1 | <style> |
7.6.2. cursor
属性:改变鼠标指针
cursor
属性用于定义当鼠标指针悬停在元素上时所显示的图标样式。为可交互元素设置正确的鼠标指针,是提升用户体验、提供明确视觉线索的关键。在浏览网页的过程中,当我们将鼠标移动到一些元素上时,鼠标的样式会发生相应的改变,例如当鼠标指向文本时,鼠标的样式会变成类似大写字母I
的样子;当鼠标指向链接时,鼠标会变成一个小手的形状等。
除了这些默认的变化外,您还可以通过 CSS 中的 cursor 属性来改变网页中鼠标(光标)的样式,下表中列举了 cursor 属性的可选值:
属性值 | 示意图 | 描述 |
---|---|---|
auto | 默认值,由浏览器根据当前上下文确定要显示的光标样式 | |
default | ![]() | 默认光标,不考虑上下文,通常是一个箭头 |
none | 不显示光标 | |
initial | 将此属性设置为其默认值 | |
inherit | 从父元素基础 cursor 属性的值 | |
context-menu | ![]() | 表示上下文菜单可用 |
help | ![]() | 表示有帮助 |
pointer | ![]() | 表示一个链接 |
progress | ![]() | 进度指示器,表示程序正在执行一些处理,但是您仍然可以在该界面进行一些操作(与 wait 不同) |
wait | ![]() | 表示程序繁忙,您应该等待程序指向完成 |
cell | ![]() | 表示可以选择一个单元格(或一组单元格) |
crosshair | ![]() | 一个简单的十字准线 |
text | ![]() | 表示可以选择的文本 |
vertical-text | ![]() | 表示可以选择的垂直文本 |
alias | ![]() | 表示要创建别名或快捷方式 |
copy | ![]() | 表示可以复制某些内容 |
move | ![]() | 表示可以移动鼠标下方的对象 |
no-drop | ![]() | 表示所拖动的项目不能放置在当前位置 |
not-allowed | ![]() | 表示无法完成某事 |
all-scroll | ![]() | 表示对象可以沿任何方向滚动(平移) |
col-resize | ![]() | 表示可以水平调整列的大小 |
row-resize | ![]() | 表示可以垂直调整行的大小 |
n-resize | ![]() | 表示对象的边缘可以向上(向北)移动 |
e-resize | ![]() | 表示对象的边缘可以向右(向东)移动 |
s-resize | ![]() | 表示对象的边缘可以向下(向南)移动 |
w-resize | ![]() | 表示对象的边缘可以向左(向西)移动 |
ne-resize | ![]() | 表示对象的边缘可以向上和向右(北/东)移动 |
nw-resize | ![]() | 表示对象的边缘可以向上和向左(北/西)移动 |
se-resize | ![]() | 表示对象的边缘可以向下和向右(向南/向东)移动 |
sw-resize | ![]() | 表示对象的边缘可以向下和向左(南/西)移动 |
ew-resize | ![]() | 表示可以双向调整对象大小的光标 |
ns-resize | ![]() | |
nesw-resize | ![]() | |
nwse-resize | ![]() | |
zoom-in | ![]() | 表示可以放大某些内容 |
zoom-out | ![]() | 表示可以缩小某些内容 |
grab | ![]() | 表示可以抓取(拖动)某些东西 |
grabbing | ![]() | 表示已经抓取到某些东西 |
url(“”) | 自定义光标的样式,括号中的内容为光标图像的源文件路径 |
自定义光标样式
除了可以使用上表中介绍的光标样式外,您也可以使用图像文件来自定义光标的样式,如下所示:
1 | cursor: url("custom.gif"), url("custom.cur"), default; |
提示:.cur 格式是光标文件的标准格式,您可以使用一些在线工具(例如 https://convertio.co/zh/cur-converter/)将 .jpg、.gif 等格式的图像文件转换为 .cur 格式。
实战: 为不同功能的元素设置对应的鼠标指针。
1 | <style> |
将鼠标依次悬停在上面的方块上,观察指针的变化。
7.7. 本章核心速查总结与实战
分类 | 关键项 | 核心描述 |
---|---|---|
显隐 | visibility: hidden | 隐藏元素,但保留其布局空间。 |
display: none | 隐藏元素,并移除其布局空间。 | |
透明度 | opacity: 0.5 | 整个元素(包括子元素)都变半透明。 |
background: rgba() | (推荐) 仅背景半透明。 | |
阴影 | box-shadow | 为元素的矩形盒子添加阴影。 |
filter: drop-shadow() | 为元素内容的实际轮廓添加阴影。 | |
渐变 | linear-gradient() | 线性渐变。 |
radial-gradient() | 径向渐变。 | |
滤镜 | filter | blur() , grayscale() 等,实现 Photoshop 级特效。 |
综合实战:创建“毛玻璃”效果卡片
“毛玻璃” (Glassmorphism) 是现代 UI 设计中非常流行的效果,它模拟了透过磨砂玻璃看背景的观感。
核心属性: backdrop-filter
backdrop-filter
是一个特殊的属性,它不对元素本身应用滤镜,而是对其背后区域的内容应用滤镜。
1 |
|
第八章:动态 CSS:@规则与动画
摘要: 在本章中,我们将为静态的页面注入生命力,全面开启 CSS 动态效果的大门。我们将首先学习 CSS 中强大的“宏观指令”——@规则
,理解它们如何从更高维度控制样式表的行为,特别是为动画服务的 @keyframes
。随后,我们将系统性地学习从 transform
(变形)、transition
(过渡) 到 animation
(动画) 的完整动态效果体系,最终让您有能力创造出流畅、优雅且富有表现力的网页动画。
在本章的学习地图中,我们将:
- 首先,学习
@规则
,这是 CSS 中用于执行宏观指令或条件化操作的基础。 - 接着,掌握
transform
(变形),学习如何对元素进行移动、旋转、缩放等几何操作。 - 然后,我们将学习
transition
(过渡),让元素在不同状态间的变化过程变得如丝般顺滑。 - 最后,我们将把所有知识融会贯通,精通
animation
(动画),编排复杂的多步动画序列。
8.1. CSS @规则:代码的宏观指令
@规则
(At-rules) 是一种特殊的 CSS 语句,以 @
符号开头,用于下达一些比单个样式声明更宏观的指令,例如导入外部文件、定义动画关键帧、或根据条件应用样式等,注意,此小节仅作了解,使用次数并不多
8.1.1. 常规 @规则
这类规则通常是独立的指令,以分号 ;
结尾。
@charset
: 定义 CSS 文件本身使用的字符编码。1
2/* 必须是样式文件的第一行,且不能有任何前置字符 */
@charset "UTF-8";@import
: 在一个 CSS 文件中导入另一个 CSS 文件的内容。1
2/* 导入一个名为 theme.css 的样式表 */
@import url("theme.css");深入探讨2025-08-26我@import
和<link>
标签都能引入 CSS,它们有什么区别吗?PProrise问得好!这是个非常重要的性能问题。
<link>
是 HTML 标签,它会在页面加载时并行下载 CSS 文件,不阻塞浏览器渲染。而@import
是 CSS 规则,它会等到包含它的 CSS 文件被下载并解析后,才串行地去下载被导入的文件。PProrise这会导致页面渲染被延迟,出现“白屏”时间更长的问题。因此,在原生前端中,我们强烈推荐始终使用
<link>
标签来引入所有 CSS 文件,而在脚手架环境下,也就是后续我们要学习的 Vue / React 是为了方便管理样式文件,且现代构建工具会处理好它的加载问题,所以对于这个规则,反而我们需要了解@namespace
: 用于在混合 XML 的文档(如内联 SVG)中定义命名空间,以避免选择器冲突。这是一个较少见的用法,了解即可。
8.1.2. 嵌套 @规则
这类规则包含一个规则块 {}
,可以在其中嵌套其他的 CSS 样式。
@media
: 媒体查询,我们在第六章响应式设计中已经深入学习过。它根据设备特性(如视口宽度)来条件性地应用样式。@supports
: 功能查询,用于检查浏览器是否支持某个特定的 CSS 属性或值,从而实现优雅降级。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<style>
.container {
/* 默认使用 flex 布局作为备选方案 */
display: flex;
justify-content: center;
}
/* 如果浏览器支持 grid 布局,则使用更优的 grid 方案 */
@supports (display: grid) {
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
}
</style>@font-face
: 允许我们引入并使用自定义的字体文件。1
2
3
4
5
6
7
8
9@font-face {
font-family: "MyCustomFont"; /* 为字体命名 */
src: url("/fonts/my-font.woff2") format("woff2"); /* 指定字体文件路径 */
font-weight: 400;
font-style: normal;
}
body {
font-family: "MyCustomFont", sans-serif; /* 在页面中使用自定义字体 */
}@keyframes
: (本章重点) 用于定义一个动画的完整序列。我们将在8.4
节详细讲解。
8.2. CSS 变形 (transform
):元素的几何魔法
transform
属性允许我们在不影响元素在文档流中所占空间的情况下,对其进行移动、旋转、缩放和倾斜等视觉变换。
8.2.1. 2D 变形函数
函数 | 核心描述 | 示例 |
---|---|---|
translate() | 平移。沿 X 轴和 Y 轴移动元素。 | transform: translate(50px, 20px); |
scale() | 缩放。放大或缩小元素。 | transform: scale(1.2); (放大 20%) |
rotate() | 旋转。顺时针旋转元素。 | transform: rotate(45deg); |
skew() | 倾斜。沿 X 轴和 Y 轴倾斜元素。 | transform: skew(10deg, 5deg); |
transform
属性可以接受多个变形函数,用空格隔开,它们会按照从左到右的顺序依次生效。
8.2.2. 改变变形原点 (transform-origin
)
默认情况下,所有的变形(如旋转、缩放)都是以元素的中心点 (50% 50%
) 为基准的。transform-origin
属性可以改变这个基准点。
实战: 创建多样化的悬停变形效果。
1 | <style> |
8.3. CSS 过渡 (transition
):让变化如丝般顺滑
transition
属性可以让元素的样式变化不再是瞬间完成的,而是以一个平滑的、有持续时间的动画过程来呈现。
8.3.1. 过渡核心属性
属性 | 核心描述 | 示例 |
---|---|---|
transition-property | 指定对哪个 CSS 属性应用过渡效果。all 表示所有可过渡的属性。 | transition-property: background-color; |
transition-duration | 指定过渡效果完成所需的时间。 | transition-duration: 0.3s; |
transition-timing-function | 指定过渡的速度曲线(动画节奏)。 | transition-timing-function: ease-in-out; |
transition-delay | 指定过渡效果开始前的延迟时间。 | transition-delay: 0.1s; |
深入讲解 transition-timing-function
(速度曲线)
速度曲线决定了动画的“性格”。
ease
: 默认值,慢速开始 -> 加速 -> 慢速结束。linear
: 匀速。ease-in
: 慢速开始。ease-out
: 慢速结束。ease-in-out
: 慢速开始和结束。cubic-bezier(...)
: 允许你通过贝塞尔曲线创建完全自定义的速度。
1 |
|
8.3.2. 简写与应用
通常,我们使用 transition
简写属性来定义过渡。
语法: transition: <property> <duration> <timing-function> <delay>;
实战: 为 8.2
节的变形效果添加平滑过渡。这是 transition
最经典的用途——与 :hover
状态和 transform
属性结合,创造平滑的交互动画。
1 | <style> |
最佳实践: 将 transition
属性定义在元素的 默认状态 下,而不是 :hover
状态下。这样可以确保无论是鼠标移入还是移出,过渡效果都能平滑地触发。
8.4. CSS 动画 (animation
):编排你的动画电影
transition
只能处理从 A 状态到 B 状态的简单过渡,而 animation
属性则要强大得多。它允许我们与 @keyframes
规则配合,创建包含多个中间步骤、可以无限循环、并能控制播放方向的复杂动画序列。
重要信息: 我们后续会使用 GSAP 这个超强的动画库来协助我们的动画效果,所以对于动画的理解,我建议您仅理解到 transform 以及 transition 即可,当然学到多也没有什么不好的!
8.4.1. 定义关键帧 (@keyframes
)
@keyframes
规则是动画的“剧本”或“故事板”。我们在这里定义动画过程中的各个关键节点(关键帧)以及在这些节点上元素的样式。
语法:
- 使用
from
(等同于0%
) 和to
(等同于100%
) 定义动画的开始和结束。 - 使用百分比 (
0%
到100%
) 来定义动画过程中的任意中间状态。
1 | /* 定义一个名为 "slide-in" 的动画 */ |
8.4.2. 动画核心属性详解
定义好 @keyframes
剧本后,我们需要在元素上使用 animation
相关属性来“播放”这个剧本。
属性 | 核心描述 |
---|---|
animation-name | 指定要绑定的 @keyframes 动画的名称。 |
animation-duration | 指定动画完成一个周期的时长。 |
animation-timing-function | 速度曲线,用法与 transition 完全相同。 |
animation-delay | 指定动画开始播放前的延迟时间。 |
animation-iteration-count | 指定动画的播放次数,infinite 表示无限循环。 |
animation-direction | 指定动画在一个周期结束后是否反向播放,alternate 表示交替反向。 |
animation-fill-mode | 定义动画在播放前后(非播放状态时)的样式。forwards 表示停留在最后一帧。 |
animation-play-state | 控制动画的播放状态,paused (暂停) 或 running (运行)。 |
8.4.3. animation
(简写属性)
与 transition
类似,我们通常使用 animation
简写属性来一次性设置所有动画参数。
语法: animation: <name> <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode>;
在简写中,至少需要指定 animation-name
和 animation-duration
才能让动画生效。
8.4.4. 实战:创建一个无限循环的呼吸灯加载动画
任务: 创建一个由小到大、由暗到亮并无限循环的“呼吸”效果,这是加载动画中最常见的类型之一。
1 | <style> |
8.5. 本章核心速查总结与疑难解答
速查表
分类 | 关键项 | 核心描述 |
---|---|---|
@规则 | @import vs <link> | (推荐) 始终使用 <link> ,因为它并行加载,性能更优。 |
@supports | CSS 功能查询,用于实现优雅降级。 | |
@keyframes | (核心) 定义动画序列的“故事板”。 | |
变形 | transform | translate (平移), scale (缩放), rotate (旋转), skew (倾斜)。不影响文档流。 |
transform-origin | 改变变形的中心点。 | |
过渡 | transition | (核心) 使元素在不同状态间的样式变化变得平滑。应定义在默认状态下。 |
动画 | animation | (核心) 结合 @keyframes 创建复杂、可循环的多步动画。 |
第九章:CSS 工程化:变量、命名与代码架构
摘要: 在本章中,我们将跳出单个 CSS 属性的学习,从更高维度审视如何构建一个健壮、可维护的 CSS 项目。我们将深入两大现代 CSS 工程化基石:CSS 变量 (Custom Properties),学习如何创建可复用的设计规范和实现一键换肤;以及 BEM 命名规范,掌握一套业界公认的、能从根本上避免样式冲突的代码组织方法论。
在本章的学习地图中,我们将:
- 首先,直面传统 CSS 开发中的“魔术数字”与样式重复的痛点。
- 接着,我们将学习 CSS 变量,掌握在原生 CSS 中实现动态主题化的强大能力。
- 然后,我们将深入 BEM 命名规范,学习如何构建清晰、无冲突、可扩展的组件化 CSS。
- 最后,我们将把这两种工程化思想结合起来,进行总结和答疑。
9.1. CSS 变量:开启主题化的大门
CSS 变量(官方称为“自定义属性”)是现代 CSS 中一项革命性的功能,它允许我们将一个值存储在一个变量中,并在样式表的任何地方重复使用。
9.1.1. 痛点解析:“魔术数字”与重复的诅咒
痛点背景:在传统的 CSS 项目中,我们经常会遇到这样的代码:
1 | .button-primary { |
这里的 #3498db
就是一个“魔术数字”。想象一下,如果现在需要将品牌主色调从蓝色换成绿色,你将不得不进行 20 多次“查找与替换”操作,这既繁琐又极易出错。
9.1.2. 核心语法:声明、使用与作用域
CSS 变量完美地解决了这个问题。
- 声明 (Declaration): 我们通常在
:root
伪类中声明全局变量,它代表了文档的根元素 (<html>
)。变量名必须以两个连字符--
开头。1
2
3
4
5:root {
--primary-color: #3498db;
--base-font-size: 16px;
--card-border-radius: 8px;
} - 使用 (Usage): 通过
var()
函数来读取变量的值。var()
函数还可以接受第二个参数,作为备用值(当变量未定义时)。1
2
3
4
5
6
7.button-primary {
/* 读取 --primary-color 变量 */
background-color: var(--primary-color);
/* 如果 --spacing-unit 未定义,则使用 10px 作为备用值 */
padding: var(--spacing-unit, 10px);
} - 作用域 (Scoping): CSS 变量遵循正常的 CSS 级联规则。你可以在更具体的选择器中重新定义变量,它会覆盖全局定义。这正是实现主题化的关键。
9.1.3. 实战:一键切换“暗黑模式”
任务: 创建一个简单的卡片组件,并通过切换 <html>
标签上的一个 data-theme
属性,实现白天/黑夜主题的瞬间切换。
1 |
|
9.2. BEM 命名规范:告别样式冲突
BEM 是一种强大的 CSS 命名约定,旨在帮助开发者在大型项目中创建可复用、可维护的组件,从根本上避免样式冲突。
9.2.1. 痛点解析:全局作用域与“样式战争”
痛点背景: 考虑以下场景,你有两个独立的组件,它们都用到了 .title
这个通用的类名。
1 | <style> |
如果某天,另一个开发者为了修复商品卡片的样式,不小心写了一个全局的 .title { color: red; }
,那么文章的标题也会被污染。为了覆盖这个样式,你可能需要写 .page .article > h2.title
这样更复杂的选择器,这就是所谓的“权重战争”,最终会让 CSS 变得一团糟。
9.2.2. BEM 方法论:块、元素与修饰符
BEM 通过一套简单的命名规则解决了这个问题,它将界面划分为三个部分:
概念 | 语法 | 作用 | 示例 |
---|---|---|---|
Block | .block | 页面上一个独立的、可复用的组件。 | .user-profile |
Element | .block__element | Block 的一个组成部分,不能脱离 Block 单独存在。 | .user-profile__avatar |
Modifier | .block--modifier | Block 或 Element 的一个变体或状态。 | .user-profile--vip , .user-profile__avatar--small |
9.2.3. 实战:使用 BEM 重构一个卡片组件
任务: 将一个拥有混乱类名的卡片组件,用 BEM 规范进行重构。
重构前 (Before):
1 | <div class="card featured"> |
重构后 (After):
1 |
|
BEM 的优势:
- 无全局冲突: 所有样式都通过唯一的块(如
.bem-card
)来限定作用域。 - 低权重: 选择器都是单一的类,避免了复杂的权重计算和覆盖问题。
- 自描述: 从类名
bem-card__title
就能清晰地看出它的结构和作用。
9.3. 本章核心速查总结与疑难解答
速查表
分类 | 语法 | 示例 |
---|---|---|
CSS 变量声明 | --name: value; | :root { --main-color: blue; } |
CSS 变量使用 | var(--name, [fallback]) | color: var(--main-color, black); |
BEM Block | .block | .nav-menu |
BEM Element | .block__element | .nav-menu__item |
BEM Modifier | .block--modifier | .nav-menu--dark |
疑难解答
CSS 变量和 Sass/SCSS 中的变量有什么本质不同?
这是一个非常核心的问题!最大的区别在于作用时机。Sass 变量(如 $color
)是编译时的,当 Sass 代码被编译成 CSS 后,变量就不存在了,它只是一个方便我们开发的工具。而 CSS 变量 (--color
) 是运行时的,它在浏览器中真实存在,你可以用 JavaScript 动态地去读取和修改它,这就是我们能实现“一键换肤”的根本原因。
BEM 命名看起来很长很丑,为什么它反而是业界推荐的规范?
问得好!BEM 确实牺牲了一部分简洁性,但它换来的是大型项目中至关重要的三大特性:可读性、可预测性和零冲突。一个又长又明确的类名 (.user-profile__avatar--small
) 远比一个简短但模糊的类名 (.avatar.small
) 要好维护得多。在团队协作中,这种“丑陋”的明确性,远比个人审美上的“简洁”要宝贵。