第 1 章:CSS 基础语法与应用
1.1 CSS 的作用与核心概念
| 项目 | 内容 |
|---|---|
| 定义 | CSS (Cascading Style Sheets),层叠样式表,用于描述 HTML 或 XML(包括 SVG)文档的呈现方式(外观和格式)。 |
| 核心作用 | 1. 分离关注点 (Separation of Concerns):将网页的结构 (HTML) 与表现 (CSS) 分离。 2. 控制视觉样式:精确控制元素的颜色、字体、布局、大小、位置、动画等。 3. 提高效率与维护性:一套 CSS 可以控制多个页面,修改样式无需改动 HTML 结构。 4. 实现响应式设计:根据设备特性(如屏幕尺寸)动态调整页面布局。 |
| 与 HTML 关系 | HTML 负责”是什么”(What),CSS 负责”长什么样”(How)。两者协同工作构建现代网页。 |
| 类比说明 | 想象 HTML 是一栋房子的钢筋水泥骨架和房间划分,而 CSS 则是房子的装修风格、墙纸颜色、家具摆放。 |
关键要点:
- CSS 是 Web 前端三大基石之一(HTML, CSS, JavaScript)。
- “层叠 (Cascading)” 指的是当多个样式规则应用于同一元素时,浏览器如何决定最终样式(通过特异性、来源顺序等规则)。
1.2 CSS 语法规则:选择器、声明块、属性与值
| 项目 | 内容 |
|---|---|
| 语法结构 | 选择器 { 属性: 值; } |
| 选择器 (Selector) | 指定需要应用样式的 HTML 元素。可以是标签名 (p)、类名 (.class)、ID 名 (#id) 或更复杂的组合。 |
| 声明块 (Declaration Block) | 由一对花括号 {} 包围,包含一个或多个声明。 |
| 声明 (Declaration) | 由一个属性和一个值组成,中间用冒号 : 分隔,以分号 ; 结尾。 |
| 属性 (Property) | 定义要修改的样式方面,如 color, font-size, margin。 |
| 值 (Value) | 属性的具体设置,如 red, 16px, 10px。 |
代码示例
/* 选择器 */
p {
/* 声明块开始 */
color: blue; /* 声明1:属性: 值; */
font-size: 18px; /* 声明2:属性: 值; */
} /* 声明块结束 */
多声明示例
h1 {
color: green;
background-color: yellow;
padding: 10px;
margin-bottom: 20px;
/* 每个声明都以分号结尾 */
}
单行 vs 多行
- 单行写法(紧凑):
p { color: blue; font-size: 18px; } - 多行写法(推荐,易读):如上所示。
关键要点:
- 分号
;至关重要:它是声明的结束符。最后一个声明的分号可省略,但强烈建议始终添加以避免错误和便于扩展。 - 选择器决定了”谁”被影响,声明块决定了”如何”被影响。
1.3 引入 CSS 的方式:内联样式、内部样式表、外部样式表(<link>)
| 引入方式 | 方法描述 | 优点 | 缺点 | 使用场景 |
|---|---|---|---|---|
| 内联样式 (Inline Styles) | 直接在 HTML 元素的 style 属性中编写 CSS 规则。 | - 权重最高,优先级最高。 - 即时生效。 | - 严重违反结构与表现分离原则。 - 无法复用,维护性极差。 - 代码冗余。 | 仅用于临时调试或极少数必须覆盖所有其他样式的场景。 |
| 内部样式表 (Internal/Embedded Stylesheet) | 在 HTML 文档的 <head> 部分使用 <style> 标签包裹 CSS 代码。 | - 样式集中在一个文件内。 - 不污染全局。 | - 样式与 HTML 仍在同一文件,未完全分离。 - 无法跨页面复用。 | 适用于单页应用或样式非常简单的独立页面。 |
| 外部样式表 (External Stylesheet) | 将 CSS 代码写在独立的 .css 文件中,然后在 HTML 的 <head> 中使用 <link> 标签引入。 | - 最佳实践! - 完全实现结构与表现分离。 - 高度可复用(一个 CSS 文件可被多个 HTML 文件引用)。 - 易于维护和更新(改一处,所有引用处生效)。 - 浏览器可缓存 CSS 文件,提升加载速度。 | - 需要额外的 HTTP 请求来加载 CSS 文件(现代优化可缓解)。 | 所有生产环境项目的标准做法。 |
代码示例
内联样式
<p style="color: red; font-weight: bold;">红色粗体段落。</p>
内部样式表
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>内部样式表</title>
<style>
body { background-color: #f0f0f0; }
p { color: blue; }
</style>
</head>
<body>
<p>这个段落是蓝色的。</p>
</body>
</html>
外部样式表
styles.css:
/* styles.css */
body { background-color: #e0e0e0; }
h1 { color: purple; }
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>外部样式表</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>标题</h1>
<p>正文</p>
</body>
</html>
关键要点:
- 优先级:内联 > 内部 > 外部(在特异性相同的情况下)
- 文件路径:href 属性中的路径需正确指向 .css 文件(相对路径或绝对路径)。
rel="stylesheet":这是必需的属性,告诉浏览器链接的是样式表。
1.4 CSS 注释 (/* … */) 与代码组织
| 项目 | 内容 |
|---|---|
| 注释语法 | /* 这是一个 CSS 注释,可以跨越多行 */ |
代码示例
/* **************************************
* 页面通用样式
* Author: Your Name
* Date: 2025-09-11
************************************** */
body, h1, h2, p {
margin: 0;
padding: 0;
}
/* 导航栏样式 */
.navbar {
background-color: #333; /* 深灰色背景 */
overflow: hidden; /* 清除浮动并隐藏溢出 */
}
.navbar a {
float: left; /* 链接左浮动 */
color: white; /* 白色文字 */
text-align: center;
padding: 14px 20px;
text-decoration: none; /* 去掉下划线 */
}
注释用途
- 解释复杂逻辑:说明为什么这样写 CSS。
- 标记代码区域:如
/* Header Styles */,/* Footer Styles */。 - 临时禁用代码:将不想生效的 CSS 代码块用
/* */包裹起来。 - 添加作者、日期、版权信息。
代码组织建议
- 按功能/模块分组:将相关的样式放在一起(如头部、导航、内容、侧边栏、底部)。
- 使用空行分隔:不同功能模块之间用空行隔开,提高可读性。
- 保持缩进一致:使用统一的缩进(通常 2 或 4 个空格)。
- 合理排序属性:可按字母顺序或逻辑分组(如盒模型 -> 排版 -> 视觉 -> 布局)。
关键要点:
- CSS 不支持
//单行注释(这是预处理器或 JS 的语法)。 - 注释不会被浏览器渲染,不影响页面性能,但会使文件体积略微增大(可忽略)。
- 养成写注释的好习惯,尤其是团队协作或长期维护的项目。
1.5 CSS 文件结构与最佳实践
文件结构示例
project-root/
├── index.html
├── css/
│ ├── reset.css # (可选) CSS Reset 或 Normalize.css
│ ├── base.css # 基础样式 (body, typography, links)
│ ├── layout.css # 布局相关 (header, footer, grid)
│ ├── components.css # 可复用组件 (buttons, cards, modals)
│ ├── pages.css # 特定页面样式 (home.css, about.css)
│ └── theme.css # 主题变量 (colors, fonts)
└── …
| 项目 | 说明 |
|---|---|
| 文件拆分策略 | • reset.css / normalize.css: 统一不同浏览器的默认样式差异。 • base.css: 设置全局基础样式(字体、链接、列表等)。 • layout.css: 定义页面整体框架和网格系统。 • components.css: 存放按钮、卡片、表单控件等 UI 组件的样式。 • pages.css: 针对特定页面的独特样式。 • theme.css: 使用 CSS 自定义属性 ( --primary-color: #007bff;) 定义主题变量,方便全局更换主题。 |
| 命名约定 | • 小写字母 + 连字符 (-):main-content, user-profile。• 避免使用下划线 (_) 或驼峰命名 (camelCase)。 • 语义化命名:名称应反映其用途或含义,而非外观(如 .btn-primary 比 .blue-button 更好)。 |
最佳实践总结
- 始终使用外部样式表。
- 拥抱模块化:将样式拆分成小的、专注的文件。
- 利用 CSS 自定义属性:管理颜色、间距、字体等变量,提升一致性与可维护性。
- 遵循 BEM/OOCSS 等方法论:解决命名冲突和样式蔓延问题。
- 使用版本控制 (Git):跟踪样式变更。
- 考虑使用预处理器 (Sass/Less):它们提供了变量、嵌套、混合等功能,能更好地组织大型 CSS 项目。
关键要点:
- 良好的文件结构是大型项目成功的关键。
normalize.css比传统的reset.css更受欢迎,因为它保留了有用的默认样式,只修复不一致的地方。
第 2 章:选择器详解
2.1 基础选择器:元素、类、ID、通配符
| 选择器类型 | 语法 | 作用 | 关键要点 |
|---|---|---|---|
| 元素选择器 | element | 选择指定类型的 HTML 元素。 | • 最基础的选择器。 • 会影响文档中所有该类型的元素。 |
| 类选择器 | .classname | 选择具有指定 class 属性值的元素。 | • 可复用性最强,一个类可在多个元素上使用。 • 一个元素可以有多个类( class="highlight important"),用空格分隔。• 类名区分大小写。 |
| ID 选择器 | #idname | 选择具有指定 id 属性值的唯一元素。 | • ID 在页面中必须是唯一的(HTML 规范要求)。 • 优先级高于类选择器和元素选择器。 • 过度使用 ID 会降低 CSS 的可复用性。 |
| 通配符选择器 | * | 选择文档中的所有元素。 | • 性能较低,应谨慎使用,避免在复杂选择器中滥用。 • 常用于全局重置或特定上下文下的批量设置。 |
代码示例
元素选择器
/* 选择所有 <p> 段落 */
p {
color: black;
font-size: 16px;
}
/* 选择所有 <h1> 标题 */
h1 {
margin-bottom: 20px;
}
类选择器
HTML:
<p class="highlight">这个段落有高亮样式。</p>
<div class="highlight">这个 div 也有高亮样式。</div>
CSS:
/* 选择所有 class="highlight" 的元素 */
.highlight {
background-color: yellow;
}
ID 选择器
HTML:
<div id="header">这是页面头部</div>
CSS:
/* 选择 id="header" 的元素 */
#header {
background-color: #333;
color: white;
padding: 20px;
}
通配符选择器
/* 重置所有元素的内外边距 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 选择 body 内的所有后代元素 */
body * {
font-family: Arial, sans-serif;
}
2.2 组合选择器:后代、子代、相邻兄弟、通用兄弟
| 组合方式 | 语法 | 作用 | 关键要点 |
|---|---|---|---|
| 后代选择器 | A B | 选择 A 元素内部的所有 B 元素(无论嵌套多深)。 | • 应用最广泛的组合方式。 • 空格是后代选择器的关键。 |
| 子代选择器 | A > B | 选择 A 元素的直接子元素 B(只限一层嵌套)。 | • > 符号表示“直接子元素”。• 比后代选择器更精确,避免意外样式污染。 |
| 相邻兄弟选择器 | A + B | 选择紧接在 A 元素之后的同级 B 元素(必须是下一个兄弟)。 | • + 号连接两个同级元素。• 必须是紧邻的下一个兄弟元素。 |
| 通用兄弟选择器 | A ~ B | 选择 A 元素之后的所有同级 B 元素(不要求紧邻)。 | • ~ 波浪号表示“之后的所有同级兄弟”。• 范围比相邻兄弟选择器更广。 |
代码示例
后代选择器
HTML:
<div class="container">
<p>第一层段落</p>
<section>
<p>第二层段落(也被选中)</p>
</section>
</div>
CSS:
/* 选择 .container 内部的所有 <p> 元素 */
.container p {
color: blue;
}
子代选择器
HTML:
<div class="container">
<p>直接子段落(被选中)</p>
<section>
<p>非直接子段落(不被选中)</p>
</section>
</div>
CSS:
/* 选择 .container 的直接子 <p> 元素 */
.container > p {
font-weight: bold;
}
相邻兄弟选择器
HTML:
<h2>标题 1</h2>
<p>段落 1(紧跟在 h2 后,被选中)</p>
<p>段落 2(不被选中)</p>
<h2>标题 2</h2>
<p>段落 3(紧跟在 h2 后,被选中)</p>
CSS:
/* 选择紧跟在 h2 后的第一个 <p> 元素 */
h2 + p {
margin-top: 5px;
}
通用兄弟选择器
HTML:
<h2>标题 1</h2>
<p>段落 1(被选中)</p>
<blockquote>引用</blockquote>
<p>段落 2(被选中)</p>
<h2>标题 2</h2>
<p>段落 3(被选中)</p>
CSS:
/* 选择 h2 之后的所有同级 <p> 元素 */
h2 ~ p {
color: green;
}
2.3 属性选择器:[attr], [attr=value], [attr~=value], [attr|=value] 等
| 属性选择器 | 语法 | 作用 | 关键要点 |
|---|---|---|---|
| 存在性选择器 | [attr] | 选择带有指定属性 attr 的元素(无论属性值是什么)。 | • 不关心属性的具体值,只关心属性是否存在。 |
| 精确值选择器 | [attr="value"] | 选择属性 attr 的值完全等于 "value" 的元素。 | • 区分大小写(除非使用 i 修饰符)。 |
| 单词匹配选择器 | [attr~="value"] | 选择属性 attr 的值包含单词 "value" 的元素(以空格分隔的单词列表)。 | • 常用于选择包含特定类名的元素,等价于 .primary。• value 必须是一个独立的单词(由空格界定)。 |
| 前缀匹配选择器 | `[attr | =“value”]` | 选择属性 attr 的值等于 "value" 或以 "value-" 开头的元素。 |
| 子串匹配选择器 | [attr^="value"] | ^=:值以 "value" 开头。 | • 非常强大的动态选择能力。 • ^=, $=, *= 是现代 CSS 布局和交互中常用的技巧。 |
[attr$="value"] | $=:值以 "value" 结尾。 | ||
[attr*="value"] | *=:值包含 "value" 子串。 |
代码示例
存在性选择器
HTML:
<a href="https://example.com">外部链接</a>
<a href="#">内部锚点</a>
<img src="logo.png" alt="Logo">
CSS:
/* 选择所有带有 href 属性的 <a> 元素 */
a[href] {
text-decoration: underline;
}
/* 选择所有带有 alt 属性的 <img> 元素 */
img[alt] {
border: 1px solid gray;
}
精确值选择器
HTML:
<input type="text" name="username">
<input type="password" name="password">
CSS:
/* 选择 type="text" 的输入框 */
input[type="text"] {
background-color: #f9f9f9;
}
/* 选择 name="password" 的输入框 */
input[name="password"] {
font-family: monospace;
}
单词匹配选择器
HTML:
<div class="btn primary large">大号主要按钮</div>
<div class="btn secondary small">小号次要按钮</div>
CSS:
/* 选择 class 中包含 "primary" 这个词的元素 */
[class~="primary"] {
background-color: blue;
color: white;
}
子串匹配选择器
HTML:
<a href="https://external.com">外部链接</a>
<a href="/internal/page">内部链接</a>
<a href="mailto:contact@example.com">邮箱链接</a>
CSS:
/* 选择 href 以 "https://" 开头的链接 (外部链接) */
a[href^="https://"] {
color: red;
}
/* 选择 href 以 ".pdf" 结尾的链接 */
a[href$=".pdf"] {
background: url(icon-pdf.png) left center no-repeat;
}
/* 选择 href 包含 "example.com" 的链接 */
a[href*="example.com"] {
font-weight: bold;
}
2.4 伪类选择器
结构性伪类
| 伪类 | 作用 | 关键要点 |
|---|---|---|
:first-child | 选择作为其父元素第一个子元素的元素。 | • 关注元素在其父容器内的位置。 • :nth-* 系列功能强大,使用公式 (an + b) 计算。例如 :nth-child(2n) 选择所有偶数项,:nth-child(3n+1) 选择第 1, 4, 7… 项。• :only-child 表示该元素是其父元素的唯一子元素。• :empty 选择没有任何子元素(包括文本节点)的元素。 |
:last-child | 选择作为其父元素最后一个子元素的元素。 | |
:nth-child(n) | 选择其父元素的第 n 个子元素(按所有子元素计数)。 | |
:nth-of-type(n) | 选择其父元素的第 n 个同类型子元素(只计算指定类型的元素)。 | • :nth-child 和 :nth-of-type 的区别在于计数范围。nth-of-type 更精确,只针对特定标签类型。 |
:only-child | 选择其父元素的唯一子元素。 | |
:empty | 选择没有子元素(包括文本)的元素。 |
状态伪类
| 伪类 | 作用 | 关键要点 |
|---|---|---|
:hover | 当用户将指针悬停在元素上时应用样式。 | • 最常用的交互效果之一。 • 对触摸设备支持有限(通常模拟为点击后短暂状态)。 • :focus 对键盘导航至关重要,不应移除默认轮廓(可通过 outline: none 移除,但需提供替代焦点指示)。• :checked 常用于样式化选中的单选/复选框。 |
:focus | 当元素获得焦点时(如通过 Tab 键或点击)。 | |
:active | 当元素被激活时(如鼠标按下但未释放)。 | |
:visited | 选择用户已访问过的链接。 | • 出于隐私考虑,visited 链接的可设置样式非常有限(主要是颜色相关属性)。 |
:checked | 选择处于选中状态的 <input type="radio"> 或 <input type="checkbox">。 | |
:disabled / :enabled | 分别选择禁用或启用的表单元素。 | |
:required / :optional | 分别选择有 required 属性或没有 required 属性的表单元素。 | |
:valid / :invalid | 分别选择通过或未通过验证的表单元素。 |
链接伪类
| 伪类 | 作用 | 关键要点 |
|---|---|---|
:link | 选择未被访问过的链接。 | • :link 和 :visited 是 :any-link 的子集。• 伪类顺序很重要!推荐遵循 LVHA 顺序: :link, :visited, :hover, :active,以确保预期的行为。如果顺序错误,某些样式可能被覆盖。 |
:visited | 选择用户已访问过的链接。 | (见上文状态伪类) |
代码示例
结构性伪类
<ul>
<li>项目 1(被选中)</li>
<li>项目 2</li>
<li>项目 3</li>
</ul>
li:first-child {
font-weight: bold;
}
li:last-child {
color: gray;
}
/* 选择列表中的奇数项 */
li:nth-child(odd) {
background-color: #f0f0f0;
}
/* 选择列表中的偶数项 */
li:nth-child(even) {
background-color: #e0e0e0;
}
/* 选择第 3 个元素 */
li:nth-child(3) {
border-top: 2px solid black;
}
:nth-of-type 示例:
<article>
<h2>章节标题</h2>
<p>第一段</p>
<p>第二段(被选中)</p>
<h2>另一个标题</h2>
<p>第三段</p>
</article>
/* 选择 article 内的第二个 <p> 元素 */
p:nth-of-type(2) {
font-style: italic;
}
:only-child 和 :empty 示例:
.single-item > *:only-child {
text-align: center;
}
.placeholder:empty::before {
content: "暂无内容";
color: #aaa;
}
状态伪类
button:hover {
background-color: #0056b3;
}
a:hover {
text-decoration: underline;
}
input:focus {
border-color: #007bff;
outline: 2px solid #007bff;
}
button:active {
transform: translateY(1px);
}
a:visited {
color: purple;
}
input[type="checkbox"]:checked + label {
color: green;
font-weight: bold;
}
input:disabled {
background-color: #eee;
cursor: not-allowed;
}
input:required {
border-left: 3px solid red;
}
input:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
链接伪类
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:hover {
text-decoration: underline;
}
a:active {
color: red;
}
2.5 伪元素选择器:::before, ::after, ::first-line, ::first-letter, ::selection
| 伪元素 | 语法 | 作用 | 关键要点 |
|---|---|---|---|
::before | ::before | 在选定元素的内容之前插入生成的内容。 | • 必须配合 content 属性使用,否则不会显示。• 默认是行内元素 ( display: inline)。• 常用于添加图标、装饰符号、清除浮动( ::after { content: ""; display: table; clear: both; })。• 单冒号 : 是 CSS2 的旧语法,双冒号 :: 是 CSS3 为区分伪类而引入的标准,推荐使用 ::。 |
::after | ::after | 在选定元素的内容之后插入生成的内容。 | (同上) |
::first-line | ::first-line | 选择块级元素的第一行文本。 | • 只能应用于块级容器内的文本。 • 可设置的属性有限(字体、颜色、背景、文本对齐等排版属性)。 |
::first-letter | ::first-letter | 选择块级元素的第一个字母(或标点符号)。 | • 常用于创建“首字下沉”(Drop Cap) 效果。 • 同样只能应用于块级容器内的文本。 • 如果第一个字符是标点(如引号),它也会被选中。 |
::selection | ::selection | 选择用户选中(高亮)的文本部分。 | • 是一个全局伪元素,但可以限定在特定元素内。 • 可设置 color, background-color, cursor, outline 等少数属性。• 提升用户体验的小细节。 |
代码示例
::before
.quote::before {
content: "\""; /* 插入引号 */
font-size: 2em;
color: #ccc;
}
HTML:
<p class="quote">这是一个引用段落。</p>
渲染效果: “这是一个引用段落。
::after
.clearfix::after {
content: "";
display: table;
clear: both;
}
.icon::after {
content: " ➔"; /* 添加右箭头 */
color: blue;
}
HTML:
<a href="#" class="icon">了解更多</a>
渲染效果: 了解更多 ➔
::first-line
p::first-line {
font-weight: bold;
color: #555;
}
HTML:
<p>这是一段很长的文字,它的第一行会被加粗并变色。当文本换行后,后续行不受此样式影响...</p>
::first-letter
p::first-letter {
font-size: 3em;
font-weight: bold;
float: left;
margin-right: 0.1em;
color: red;
}
HTML:
<p>从前有一座山,山里有一座庙...</p>
渲染效果: 从前有一座山,山里有一座庙…
::selection
/* 修改选中文本的样式 */
::selection {
background-color: orange;
color: white;
}
/* 特定元素内的选中样式 */
p.special::selection {
background-color: pink;
}
HTML:
<p>普通段落,选中时背景橙色。</p>
<p class="special">特殊段落,选中时背景粉色。</p>
2.6 选择器优先级 (Specificity):权重计算规则与 !important 的使用规范
权重计算规则
| 概念 | 说明 | 权重值 | 计算示例 |
|---|---|---|---|
| 内联样式 | 直接在 HTML 元素的 style 属性中定义的样式。 | 1000 | <h1 style="color: red;">标题</h1> → 权重 = 1000 |
| ID 选择器 | 每个 #id 选择器增加 100 点权重。 | 100 | #main-header → 权重 = 100#sidebar ul li → 权重 = 100 (只有1个ID) |
| 类选择器、属性选择器、伪类 | 每个 .class, [attr], :hover 等增加 10 点权重。 | 10 | .nav-menu → 权重 = 10[type="text"] → 权重 = 10:hover → 权重 = 10ul.menu li.active:hover → 权重 = 10 + 10 + 10 = 30 |
| 元素选择器、伪元素 | 每个 div, p, ::before 等增加 1 点权重。 | 1 | div → 权重 = 1p::first-line → 权重 = 1 + 1 = 2ul li a → 权重 = 1 + 1 + 1 = 3 |
通配符、组合符、否定伪类 :not() | 不增加权重。:not(.class) 的权重取决于 :not() 内部的选择器。 | 0 | * → 权重 = 0div p → 权重 = 1 + 1 = 2 (空格不加分):not(.important) → 权重 = 10 (内部 .important 的权重) |
!important | 最高优先级,会覆盖任何其他声明(包括内联样式)。 | ∞ (无限) | p { color: blue !important; } → 无论其他规则权重多高,只要匹配,文字就是蓝色。例外: !important 在用户样式表中的权重低于作者样式表中的 !important。 |
优先级比较规则
-
比较权重:将四个数值(ID, 类/属性/伪类, 元素/伪元素)分别比较。从左到右,哪个数值大,哪个选择器优先级就高。例如 100 (ID) > 013 (0个ID, 1个类, 3个元素)。
-
比较来源与重要性:如果权重相同,则比较:
!important声明 > 普通声明。然后比较来源:作者样式表 > 用户样式表 > 用户代理(浏览器默认)样式表。 -
比较声明顺序:如果以上都相同,则后出现的声明覆盖先出现的(层叠的体现)。
!important 使用规范
| 建议 | 说明 |
|---|---|
| 何时使用 | • 覆盖第三方库或框架中难以修改的内联样式(临时方案)。 • 在开发调试时快速测试样式效果(记得移除)。 |
| 何时避免 | • 日常开发中应极力避免。 • 它破坏了 CSS 的自然层叠和特异性,使样式难以预测和维护。 • 大量使用 !important 会导致“!important 战争”,最终所有样式都需要 !important 才能生效,代码变得混乱不堪。 |
| 最佳实践 | • 通过提高选择器特异性来解决问题(如添加一个更具体的类),而不是使用 !important。• 如果必须使用,务必添加注释说明原因。 |
第 3 章:盒模型与尺寸计算
3.1 标准盒模型 (W3C Box Model) 解析
| 内容项 | 说明 |
|---|---|
| 定义 | 标准盒模型(W3C Box Model)是 CSS 中默认的盒模型,元素的 width 和 height 仅指内容区域(content)的尺寸,不包括 padding、border 和 margin。 |
| 组成部分 | - Content:实际内容显示区域 - Padding:内边距,围绕 content 的透明区域 - Border:边框,围绕 padding 的线条 - Margin:外边距,元素与其他元素之间的空白区域 |
| 总尺寸计算公式 | - 总宽度 = width + 2×padding-left/right + 2×border-left/right + 2×margin-left/right - 总高度 = height + 2×padding-top/bottom + 2×border-top/bottom + 2×margin-top/bottom |
结构图示
+-------------------------------------------+
| Margin (outer) |
| +-----------------------------------+ |
| | Border | |
| | +---------------------------+ | |
| | | Padding | | |
| | | +-------------------+ | | |
| | | | Content | | | |
| | | +-------------------+ | | |
| | +---------------------------+ | |
| +-----------------------------------+ |
+-------------------------------------------+
代码示例
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>标准盒模型示例</title>
<style>
.box {
width: 200px;
height: 100px;
padding: 20px;
border: 5px solid #000;
margin: 10px;
background-color: lightblue;
box-sizing: content-box; /* 默认值,即标准模型 */
}
</style>
</head>
<body>
<div class="box">这是一个标准盒模型的 div</div>
</body>
</html>
计算验证
- 内容宽高:200px × 100px
- 实际占用宽度:200 + 2×20 + 2×5 + 2×10 = 270px
- 实际占用高度:100 + 2×20 + 2×5 + 2×10 = 170px
3.2 IE 盒模型与 box-sizing 属性
| 属性名 | 值 | 描述 | 适用场景 |
|---|---|---|---|
box-sizing | content-box | 默认值,遵循 W3C 标准盒模型,width/height 仅作用于 content | 兼容旧布局 |
border-box | IE 盒模型逻辑,width/height 包括 content + padding + border | 现代布局、响应式设计常用 |
对比表格:相同设置下的差异
设置项:.box1 { width: 200px; padding: 20px; border: 5px; }
| box-sizing 值 | 尺寸计算 |
|---|---|
content-box | - content 宽度 = 200px - 总宽度 = 200 + 40 + 10 = 250px |
border-box | - content 宽度自动压缩为 150px - 总宽度 = 200px(固定) |
⚠️ 注意:margin 始终不计入 box-sizing 计算范围。
代码示例
/* 使用 border-box 统一重置所有元素 */
* {
box-sizing: border-box;
}
.example {
width: 200px;
height: 100px;
padding: 20px;
border: 5px solid red;
margin: 10px;
background: yellow;
}
此时 .example 的总宽度仍为 200px,内部 content 自动调整为 200 - 2*(20+5) = 150px。
推荐实践
*, *::before, *::after {
box-sizing: border-box;
}
这是现代 CSS Reset 或 Normalize 的常见做法,避免尺寸计算混乱。
3.3 深入理解 content、padding、border、margin
| 区域 | 功能说明 | 是否可设背景 | 是否影响布局 | 特殊性质 |
|---|---|---|---|---|
| Content | 显示文本、图像等内容 | ✅ 是(background-color/image) | ✅ 是 | 可滚动(若 overflow 非 visible) |
| Padding | 内部留白,增强可读性 | ✅ 是(继承父背景或独立设置) | ✅ 是 | 不可为负值 |
| Border | 边框装饰或分隔 | ✅ 是 | ✅ 是 | 支持样式(solid/dashed等)、圆角(border-radius) |
| Margin | 外部间距,控制元素间距离 | ❌ 否(透明) | ✅ 是 | 可为负值,支持自动居中(auto) |
属性语法速查表
| 属性 | 单边写法 | 简写规则(顺时针) |
|---|---|---|
| padding | padding-top, padding-right 等 | padding: 10px; → 四边一致padding: 10px 20px; → 上下=10, 左右=20padding: 10px 20px 15px; → 上=10, 右=20, 下=15, 左=20padding: 10px 20px 15px 25px; → 上右下左 |
| margin | 同上 | 规则同 padding |
| border | border-width, border-style, border-color | border: 2px solid red; |
示例代码
.box {
content: "伪元素内容"; /* 仅用于 ::before/after */
padding: 10px 20px; /* 上下10px,左右20px */
border: 3px dashed green; /* 宽度、样式、颜色 */
margin: 20px auto; /* 上下20px,左右自动居中 */
background: #eee url("bg.jpg") no-repeat center;
}
📌 提示:padding 和 border 会影响点击热区;margin 不可点击。
3.4 计算元素的总宽度与总高度
| 参数 | 符号 | 是否受 box-sizing 影响 |
|---|---|---|
| 内容宽度 | W_c | ✅ 是(由 width 定义) |
| 内边距总和 | P = 2×(left + right) | 否 |
| 边框总和 | B = 2×(left + right) | 否 |
| 外边距总和 | M = 2×(left + right) | 否 |
尺寸计算对照表
| box-sizing 类型 | 实际宽度(含 margin) | 内容可用宽度 |
|---|---|---|
content-box | width + P + B + M | width |
border-box | specified width + M | specified width - P - B |
💡 示例:一个元素设置 width: 300px; padding: 10px; border: 5px; margin: 20px;
| box-sizing | 内容宽度 | 实际占用宽度(页面中) |
|---|---|---|
content-box | 300px | 300 + 20 + 10 + 40 = 370px |
border-box | 270px(自动压缩) | 300 + 40 = 340px |
JavaScript 获取尺寸方法对比
| 方法 | 返回值说明 | 是否包含 margin |
|---|---|---|
offsetWidth | width + padding + border | ❌ 否 |
clientWidth | width + padding | ❌ 否 |
getBoundingClientRect().width | 浮点型渲染后宽度 | ❌ 否 |
getComputedStyle(elem).width | 字符串如 “300px” | ❌ 否(需手动加 margin) |
要获取完整占位宽度,需手动相加:
// 注意:以下代码仅在浏览器环境中运行
// const elem = document.querySelector('.box');
// const style = getComputedStyle(elem);
// const totalWidth =
// elem.offsetWidth +
// parseFloat(style.marginLeft) +
// parseFloat(style.marginRight);
// console.log(totalWidth); // 包括 margin 的总宽度
3.5 外边距折叠 (Margin Collapse) 现象与处理
外边距折叠类型汇总表
| 类型 | 发生条件 | 折叠规则 | 图示说明 |
|---|---|---|---|
| 相邻兄弟元素 | 垂直排列的 block 元素,之间无 border/padding/inline content 隔开 | 取两者 margin 的最大值(同向)或代数和(反向) | A↓10px 与 B↑20px → 实际间距 20px |
| 父子关系折叠 | 父元素无 border/padding/block formatting context,子元素 margin-top/bottom 无阻挡 | 子元素的 margin 会”穿透”到父元素外部 | 导致父元素整体下移 |
| 空块级元素自身折叠 | 元素无 border/padding/content,且上下 margin 存在 | 上下 margin 合并为一个,取较大者 | <div style="margin:20px 0 30px;"></div> → 实际 margin: 30px |
折叠规则详解(同方向)
| margin-top A | margin-bottom B | 折叠后垂直间距 |
|---|---|---|
| 20px | 30px | 30px(取大) |
| -10px | 20px | 20px(正数优先) |
| -15px | -25px | -25px(更小) |
⚠️ 注意:只有垂直方向的 margin 会折叠,水平方向不会!
解决方案对照表
| 问题类型 | 解决方法 | 原理 |
|---|---|---|
| 防止兄弟折叠 | 使用 padding 或 border 替代部分 margin | 打破”纯 margin 相邻”条件 |
| 防止父子折叠 | 给父元素添加 padding-top: 1px 或 border-top: 1px solid transparent | 阻断 margin 传递路径 |
| 将父元素变成 BFC(Block Formatting Context) | 创建独立布局环境 | |
例如:overflow: hidden/auto | ||
使用伪元素 ::before { content: ""; display: table; } | 触发 BFC | |
| 统一控制布局 | 使用 CSS Grid / Flexbox 布局 | 这些容器默认不参与传统 margin 折叠 |
代码示例:防止父子 margin 折叠
<div class="parent">
<div class="child">子元素</div>
</div>
.parent {
background: #f0f0f0;
/* 解决方案任选其一 */
/* 方案1:加 border */
/* border: 1px solid transparent; */
/* 方案2:创建 BFC */
overflow: hidden;
/* 方案3:使用伪元素触发 BFC */
/* &:before { content:""; display:table; } */
}
.child {
margin-top: 30px;
background: coral;
height: 50px;
}
✅ 应用以上任一方案后,.child 的 margin-top 将只作用于内部,不再导致 .parent 整体下移。
第 4 章:文档流、定位与层叠
4.1 块级元素、行内元素、行内块元素 (display 属性)
| 显示类型 | 典型元素 | 是否换行 | 可设宽高 | 占据空间方式 | 内容排列 |
|---|---|---|---|---|---|
block | <div>, <p>, <h1>~<h6>, <ul> | ✅ 自动换行 | ✅ 可设置 | 独占一行,默认宽度为父容器 100% | 垂直堆叠 |
inline | <span>, <a>, <strong>, <em> | ❌ 不换行 | ❌ 宽高无效(由内容决定) | 仅占内容所需空间 | 水平排列,忽略上下 margin |
inline-block | —(需手动设置) | ❌ 不换行 | ✅ 可设置 | 行内排列但可设宽高 | 类似 inline,但支持 block 特性 |
特性对比表
| 特性 | block | inline | inline-block |
|---|---|---|---|
| 换行显示 | ✅ | ❌ | ❌ |
| 可设置 width/height | ✅ | ❌ | ✅ |
| 忽略 vertical-align | ✅ | ❌ | ✅(有效) |
| margin 上下生效 | ✅ | ⚠️ 不影响布局(但视觉存在) | ✅ |
| padding 生效 | ✅ | ✅(但可能重叠) | ✅ |
💡 提示:inline 元素的上下 margin 和 padding 不会推挤其他元素,但背景仍会渲染。
结构图示
[ Block Element 1 ] ← 占满整行
[ Block Element 2 ] ← 下一行开始
Inline: This is <span style="background:yellow">highlighted</span> text.
↑ 所有内容在同一行流动
Inline-block:
[Item1][Item2][Item3] ← 可设宽高,同行排列
代码示例
.box1 {
display: block;
width: 100px;
height: 50px;
background: red;
}
.box2 {
display: inline;
background: blue;
padding: 10px;
}
.box3 {
display: inline-block;
width: 80px;
height: 40px;
background: green;
margin: 5px;
}
<div class="box1">Block</div>
<span class="box2">Inline</span>
<span class="box3">In-B</span>
<span class="box3">In-B</span>
输出效果:
.box1单独一行,红色方块.box2蓝色背景,文字连排- 两个
.box3并列显示,绿色小方块带间距
4.2 定位方案 (position 属性)
| position 值 | 含义 | 是否脱离文档流 | 定位参考点 | 使用场景 |
|---|---|---|---|---|
static | 默认值,遵循正常文档流 | ❌ 否 | 无(不可用 top/right/bottom/left) | 常规布局 |
relative | 相对自身原始位置偏移 | ❌ 否(仍占原位) | 自身原本位置 | 微调位置、作为绝对定位的容器 |
absolute | 绝对定位 | ✅ 是(脱离文档流) | 最近的已定位祖先元素(非 static);否则为初始包含块(通常是视口) | 弹窗、提示框、复杂层叠布局 |
fixed | 固定定位 | ✅ 是(脱离文档流) | 浏览器视口(viewport) | 导航栏、回到顶部按钮 |
sticky | 粘性定位 | ❌ 否(条件性固定) | 视口 + 滚动容器边界 | 吸顶菜单、侧边栏锚定 |
定位行为说明表
| 类型 | 文档流中占位? | 是否响应 scroll? | 是否创建层叠上下文? | 注意事项 |
|---|---|---|---|---|
static | ✅ 是 | N/A | ❌ | 设置 top 等无效 |
relative | ✅ 是 | ✅ | ❌(除非 z-index ≠ auto) | 偏移后原位置保留空白 |
absolute | ❌ 否 | ✅ | ✅(若 z-index ≠ auto) | 需注意父级是否”已定位” |
fixed | ❌ 否 | ❌(相对于视口) | ✅ | 在移动端可能表现异常(Safari) |
sticky | ✅ 是(滚动前) | ✅ | ✅(当”粘住”时) | 必须指定 top 或 bottom 才生效 |
代码示例
.container {
position: relative;
border: 2px solid #000;
height: 300px;
background: #f0f0f0;
}
.abs-box {
position: absolute;
top: 20px;
right: 20px;
width: 100px;
height: 100px;
background: red;
}
.fix-btn {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px;
background: black;
color: white;
}
.sticky-header {
position: sticky;
top: 0;
background: blue;
color: white;
padding: 10px;
font-weight: bold;
}
<div class="container">
<div class="abs-box">绝对定位</div>
</div>
<header class="sticky-header">吸顶标题</header>
<button class="fix-btn">回到顶部</button>
✅ 效果说明:
.abs-box相对于.container定位(因父级 relative).fix-btn固定在右下角,滚动不消失.sticky-header滚动到顶部时”吸附”
4.3 top, right, bottom, left 偏移属性
| 属性 | 适用 position 类型 | 正值方向 | 负值效果 | 特殊规则 |
|---|---|---|---|---|
top | relative, absolute, fixed, sticky | 向下偏移 | 向上移动 | 对 absolute/fixed,距离参考点的距离 |
right | 同上 | 向左偏移 | 向右移动 | 优先级高于 left(当两者都设时) |
bottom | 同上 | 向上偏移 | 向下移动 | 常用于底部对齐 |
left | 同上 | 向右偏移 | 向左移动 | 默认基准为 0 |
偏移行为对照表
| position | 设置 top: 50px 效果 |
|---|---|
static | ❌ 无效 |
relative | 元素从原位置向下移动 50px,原位置保留 |
absolute | 元素距其定位祖先顶部 50px 处定位 |
fixed | 元素距视口顶部 50px 处定位 |
sticky | 当滚动到距视口顶部 ≤50px 时,“粘住”在此位置 |
居中技巧示例
/* 水平居中(relative/absolute) */
.center-h {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
/* 垂直居中 */
.center-v {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
/* 完全居中 */
.center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 100px;
}
📌 替代方法(现代布局):
.modern-center {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
margin: auto;
width: 200px;
height: 100px;
}
4.4 z-index 与层叠上下文 (Stacking Context)
| 属性 | 作用 | 取值范围 | 是否创建层叠上下文? |
|---|---|---|---|
z-index | 控制元素在 Z 轴上的堆叠顺序 | auto(默认)、整数(正/负) | ✅ 仅当 position 非 static 且值不为 auto 时 |
层叠顺序(从后到前)
- 根元素的背景和边框
position: static/relative的 block 元素(按 HTML 顺序)position: static/relative的 inline 元素- 浮动元素(内容在前,浮动框在后)
position: absolute/fixed元素(按 z-index 排序)
🔁 在同一层叠上下文中,z-index 越大越靠前。
创建新层叠上下文的条件(任一满足即成立)
| 条件 | 示例 CSS |
|---|---|
| position + z-index(非 auto) | position: relative; z-index: 1; |
| opacity < 1 | opacity: 0.9; |
| transform 非 none | transform: scale(1); |
| filter 非 none | filter: blur(1px); |
| will-change 指定相关属性 | will-change: transform; |
| isolation: isolate | isolation: isolate; |
| mix-blend-mode 非 normal | mix-blend-mode: multiply; |
层叠陷阱示例
<div class="parent-a" style="position:relative; z-index:10;">
<div class="child-a" style="position:absolute; z-index:100;">A</div>
</div>
<div class="parent-b" style="position:relative; z-index:20;">
<div class="child-b" style="position:absolute; z-index:1;">B</div>
</div>
❌ 尽管 .child-a 的 z-index=100 > .child-b=1,但由于 .parent-b 的 z-index=20 > 10,整个 B 分支都在 A 上方!
✅ 解决方案:统一管理 z-index,避免深层嵌套冲突。
4.5 浮动 (float) 原理、历史用途与清除浮动方法
| float 值 | 行为描述 | 是否脱离文档流 | 是否影响后续元素 |
|---|---|---|---|
left | 向左浮动,允许文本环绕右侧 | ✅ 是 | ✅ 是(后续 inline 内容会环绕) |
right | 向右浮动 | ✅ 是 | ✅ 是 |
none | 默认值,不浮动 | ❌ 否 | ❌ 否 |
浮动特性表
| 特性 | 说明 |
|---|---|
| 脱离文档流 | 后续 block 元素可能”上移”填充空间 |
| 创建块格式化上下文 (BFC) | 浮动元素自动成为 BFC,防止外边距折叠 |
| 高度塌陷问题 | 父容器无法感知浮动子元素的高度,导致高度为 0 |
清除浮动方法对比
| 方法 | 实现方式 | 原理 | 优缺点 |
|---|---|---|---|
| 空 div 法 | <div style="clear:both;"></div> | 插入不可见元素阻止环绕 | 简单但语义差,增加冗余标签 |
| overflow 触发 BFC | .parent { overflow: hidden; } | 创建 BFC 包含浮动 | 简洁,但可能裁剪内容或影响滚动 |
| after 伪元素法 | .clearfix::after { content:""; display:block; clear:both; } | 动态添加清除符 | 推荐做法,无额外标签 |
| Flex/Grid 替代 | .parent { display: flex; } | 现代布局天然解决浮动问题 | 更优方案,无需清除 |
代码示例:clearfix 技巧
.clearfix::before,
.clearfix::after {
content: "";
display: table;
}
.clearfix::after {
clear: both;
}
/* IE6/7 兼容(可选) */
.clearfix {
*zoom: 1;
}
<div class="parent clearfix">
<div style="float:left; width:100px; height:100px; background:red;"></div>
<div style="float:left; width:100px; height:100px; background:blue;"></div>
</div>
<!-- 父元素现在能正确包裹两个浮动子元素 -->
浮动的历史与现状
- ✅ 曾用于:多列布局、导航菜单、图片环绕文字
- ❌ 现已被取代:Flexbox 和 Grid 提供更强大、可控的布局能力
- ⚠️ 仍适用场景:简单的文本环绕图像(如文章配图)
第 5 章:Flexbox 弹性布局
5.1 Flexbox 核心概念:容器、项目、主轴、交叉轴
| 概念 | 定义 | 说明 |
|---|---|---|
| Flex 容器 (Flex Container) | 应用了 display: flex 或 display: inline-flex 的父元素 | 所有直接子元素自动成为”flex 项目” |
| Flex 项目 (Flex Items) | Flex 容器的直接子元素 | 受容器的 flex 属性控制排列方式 |
| 主轴 (Main Axis) | 主要排列方向轴 | 由 flex-direction 决定,默认为水平从左到右 |
| 交叉轴 (Cross Axis) | 垂直于主轴的方向 | 自动确定,用于对齐垂直方向 |
主轴与交叉轴方向对照表
| flex-direction 值 | 主轴方向 | 交叉轴方向 | 图示(→=主轴,↓=交叉轴) |
|---|---|---|---|
row(默认) | ← → 水平(左到右) | ↑ ↓ 垂直(上到下) | [Item1][Item2][Item3] ↓ |
row-reverse | → ← 水平(右到左) | ↑ ↓ 垂直(上到下) | [Item3][Item2][Item1] ↓ |
column | ↑ ↓ 垂直(上到下) | ← → 水平(左到右) | Item1 Item2 Item3 ← |
column-reverse | ↓ ↑ 垂直(下到上) | ← → 水平(左到右) | Item3 Item2 Item1 ← |
📌 提示:主轴决定排列顺序,交叉轴决定对齐方式。
结构图示
flex-direction: row;
+-----------------------------+
| [Item 1] [Item 2] [Item 3] |
+-----------------------------+
←---------- Main Axis --------→
↓ ↓ ↓
Cross Axis (vertical)
flex-direction: column;
+---------+
| Item 1 | ← Main Axis (down)
+---------+
| Item 2 |
+---------+
| Item 3 |
+---------+
←-- Cross Axis (horizontal) --→
代码示例
.container {
display: flex; /* 创建 flex 容器 */
flex-direction: row; /* 主轴为水平方向 */
height: 200px; /* 为 column 提供交叉轴空间 */
border: 2px solid #333;
}
.item {
width: 100px;
height: 80px;
background: lightblue;
margin: 5px;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
✅ 效果:三个项目水平排列,主轴为水平,交叉轴为垂直。
5.2 容器属性详解:display, flex-direction, flex-wrap, justify-content, align-items, align-content, gap
| 属性 | 值示例 | 功能说明 | 适用场景 |
|---|---|---|---|
display | flex, inline-flex | 启用 Flex 布局 | 必须设置 |
flex-direction | row, row-reverse, column, column-reverse | 设置主轴方向 | 控制排列方向 |
flex-wrap | nowrap(默认), wrap, wrap-reverse | 是否换行 | 多行布局、响应式卡片 |
justify-content | flex-start, center, flex-end, space-between, space-around, space-evenly | 主轴对齐方式 | 水平/垂直居中、间距分配 |
align-items | stretch(默认), flex-start, center, flex-end, baseline | 交叉轴对齐方式 | 垂直居中、顶部对齐 |
align-content | stretch, flex-start, center, space-between 等 | 多行时行之间的对齐 | 仅当 flex-wrap: wrap 时有效 |
gap | 10px, 1em, 1rem | 项目间间距(主轴+交叉轴) | 替代 margin,避免外边距折叠 |
justify-content 详细对照表
| 值 | 描述 | 图示([ ] = 项目) |
|---|---|---|
flex-start | 靠近起点 | [1][2][3] |
center | 居中 | [1][2][3] |
flex-end | 靠近终点 | [1][2][3] |
space-between | 两端对齐,中间间距相等 | [1] [2] [3] |
space-around | 每个项目周围空间相等 | [1] [2] [3] |
space-evenly | 所有间距完全相等 | [1] [2] [3] |
align-items 详细对照表
| 值 | 描述 | 适用情况 |
|---|---|---|
stretch | 拉伸填满容器(无固定高度时) | 默认行为 |
flex-start | 顶部对齐 | 所有项目顶部对齐 |
center | 居中对齐 | 垂直居中 |
flex-end | 底部对齐 | 所有项目底部对齐 |
baseline | 文本基线对齐 | 多行文字对齐 |
代码示例:完整容器布局
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
align-content: space-around;
gap: 16px;
height: 400px;
border: 2px dashed #666;
}
<div class="flex-container">
<div style="height:60px;background:red;">A</div>
<div style="height:80px;background:blue;">B</div>
<div style="height:40px;background:green;">C</div>
<div style="height:100px;background:orange;">D</div>
</div>
✅ 效果:
- 项目主轴间距相等(space-between)
- 交叉轴居中对齐(align-items)
- 若换行,行间间距分配(align-content)
5.3 项目属性详解:order, flex-grow, flex-shrink, flex-basis, flex, align-self
| 属性 | 作用 | 取值说明 | 示例 |
|---|---|---|---|
order | 控制项目显示顺序 | 整数(默认 0),数值越小越靠前 | order: -1; → 最前 |
flex-grow | 放大比例(剩余空间分配) | 数字(默认 0),0=不放大 | flex-grow: 1; → 平分剩余空间 |
flex-shrink | 缩小比例(空间不足时) | 数字(默认 1),0=不缩小 | flex-shrink: 0; → 禁止压缩 |
flex-basis | 项目主轴初始尺寸 | 长度值(如 100px, auto) | flex-basis: 200px; → 初始宽 200px |
flex | 缩写:flex-grow flex-shrink flex-basis | 推荐写法:flex: 1 或 flex: 0 1 auto | flex: 1; = 1 1 0(注意:现代浏览器中 flex: 1 等价于 1 1 0%) |
align-self | 单个项目交叉轴对齐方式 | 覆盖 align-items,值同 align-items | align-self: flex-end; |
flex 缩写常见写法对照表
| 写法 | 等效展开 | 含义 |
|---|---|---|
flex: 0 1 auto | grow=0, shrink=1, basis=auto | 默认行为,大小由内容决定,可压缩 |
flex: 1 | 1 1 0% | 占据可用空间(推荐用于”填满”) |
flex: 0 0 200px | grow=0, shrink=0, basis=200px | 固定尺寸,不放大不缩小 |
flex: 2 | 2 2 0% | 放大权重为 2,优先获得更多空间 |
代码示例
.container {
display: flex;
width: 600px;
height: 100px;
border: 1px solid #000;
}
.item-a {
flex: 2; /* 占比 2 */
background: red;
}
.item-b {
flex: 1; /* 占比 1 */
background: blue;
}
.item-c {
flex: 0 0 100px; /* 固定 100px */
background: green;
}
.item-d {
order: -1; /* 最先显示 */
background: orange;
width: 50px;
}
.item-e {
align-self: flex-end; /* 底部对齐 */
background: purple;
height: 60px;
}
<div class="container">
<div class="item-a">A (flex:2)</div>
<div class="item-b">B (flex:1)</div>
<div class="item-c">C (fixed)</div>
<div class="item-d">D (order:-1)</div>
<div class="item-e">E (align-self)</div>
</div>
✅ 效果:
.item-d显示在最左侧(order 最小)- A:B 宽度比约为 2:1
- C 固定 100px
- E 底部对齐
5.4 Flexbox 实战案例:居中对齐、导航栏、卡片布局、圣杯布局
案例 1:完美居中对齐
.center {
display: flex;
justify-content: center;
align-items: center;
height: 100vh; /* 或任意容器高度 */
}
<div class="center">
<div>居中的内容</div>
</div>
✅ 支持文字、图片、固定尺寸元素的居中。
案例 2:水平导航栏
.nav {
display: flex;
justify-content: space-between; /* 或 center */
list-style: none;
padding: 0;
background: #333;
}
.nav-item {
padding: 1rem 1.5rem;
color: white;
text-decoration: none;
}
.nav-item:hover {
background: #555;
}
<ul class="nav">
<li><a href="#" class="nav-item">首页</a></li>
<li><a href="#" class="nav-item">产品</a></li>
<li><a href="#" class="nav-item">关于</a></li>
</ul>
✅ 响应式,无需浮动。
案例 3:卡片布局(响应式)
.card-container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
padding: 1rem;
}
.card {
flex: 1 1 200px; /* 最小 200px,可伸缩 */
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
background: white;
}
<div class="card-container">
<div class="card">卡片 1</div>
<div class="card">卡片 2</div>
<div class="card">卡片 3</div>
<div class="card">卡片 4</div>
</div>
✅ 在小屏幕上自动换行,每行尽可能放满。
案例 4:圣杯布局(Header + Flex Content + Footer)
.holy-grail {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.header, .footer {
flex: 0 0 auto; /* 不伸缩,保持原高 */
background: #333;
color: white;
text-align: center;
padding: 1rem;
}
.main {
flex: 1; /* 填满剩余空间 */
display: flex;
gap: 1rem;
padding: 1rem;
}
.sidebar {
flex: 0 0 200px;
background: #f0f0f0;
}
.content {
flex: 1;
background: #fff;
}
<div class="holy-grail">
<header class="header">Header</header>
<main class="main">
<aside class="sidebar">Sidebar</aside>
<section class="content">Main Content</section>
</main>
<footer class="footer">Footer</footer>
</div>
✅ 特点:
- 头尾固定高度
- 中间主体填满剩余空间
- 侧边栏固定宽度,内容区自适应
核心口诀
- 容器控方向(
flex-direction) - 主轴看
justify-content - 交叉轴看
align-items - 项目用
flex调比例
第 6 章:Grid 网格布局
6.1 Grid 布局核心概念:网格容器、网格项目、网格线、网格轨道、网格区域
| 概念 | 定义 | 说明 |
|---|---|---|
| 网格容器 (Grid Container) | 设置了 display: grid 或 inline-grid 的父元素 | 所有直接子元素自动成为”网格项目” |
| 网格项目 (Grid Items) | 网格容器的直接子元素 | 可跨越多个单元格 |
| 网格线 (Grid Lines) | 划分行和列的线(从 1 开始编号) | 可用于定位项目起止位置 |
| 网格轨道 (Grid Track) | 相邻两条网格线之间的空间(即行或列) | 对应 grid-template-rows/columns 中定义的一行/一列 |
| 网格单元格 (Grid Cell) | 单个行与列交叉形成的最小单位 | 类似表格中的一个”格子” |
| 网格区域 (Grid Area) | 由四条网格线围成的矩形区域(可跨多行多列) | 可命名并用于布局 |
结构图示
网格线编号(列):
1 2 3 4
| | | |
v v v v
+-----+-------+--------+
1 | A | B | C | ← 第1行(轨道)
+-----+-------+--------+
2 | | | |
| D | E | F | ← 第2行
| | | |
+-----+-------+--------+
3 | G | H | I | ← 第3行
+-----+-------+--------+
A 占据:列1→2,行1→2 E 是一个单元格:列2→3,行2→3 一个”网格区域”可以是 A + D + G(第1列全部)
📌 提示:网格线支持负数编号(如 -1 表示最右边/底部的线)。
6.2 容器属性详解:display, grid-template-columns/rows, grid-template-areas, gap, justify-items, align-items, justify-content, align-content
| 属性 | 功能说明 | 示例值 | 适用场景 |
|---|---|---|---|
display | 启用 Grid 布局 | grid, inline-grid | 必须设置 |
grid-template-columns | 定义列宽(每条轨道) | 100px 1fr 2fr, repeat(3, 1fr) | 控制列分布 |
grid-template-rows | 定义行高 | auto 100px minmax(50px, auto) | 控制行高度 |
grid-template-areas | 使用名称定义区域布局 | "header header"<br />"nav main"<br />"footer footer" | 可视化布局设计 |
gap / row-gap, column-gap | 行/列间距 | 10px, 1rem | 替代 margin,避免外边距折叠 |
justify-items | 项目在单元格内的水平对齐 | start, center, end, stretch | 统一控制项目水平对齐方式 |
align-items | 项目在单元格内的垂直对齐 | start, center, end, stretch(默认) | 统一控制垂直对齐 |
justify-content | 整个网格在容器中的水平对齐(当总尺寸小于容器) | start, center, space-between, space-around | 多余空间分配 |
align-content | 整个网格在容器中的垂直对齐 | 同上 | 垂直方向多余空间分配 |
grid-template-columns/rows 示例对照表
| 写法 | 含义 |
|---|---|
100px 200px 1fr | 三列:第一列100px,第二列200px,第三列占剩余空间 |
repeat(3, 1fr) | 三列等分剩余空间 |
minmax(100px, 1fr) | 最小100px,最大占满可用空间 |
2fr 1fr | 两列,比例为 2:1 |
fit-content(200px) | 内容宽度最多不超过200px,否则自适应 |
代码示例:使用 grid-template-areas 布局
.container {
display: grid;
grid-template-areas:
"header header"
"nav main"
"footer footer";
grid-template-columns: 200px 1fr;
grid-template-rows: 80px 1fr 60px;
gap: 10px;
min-height: 100vh;
}
.header { grid-area: header; background: #333; color: white; }
.nav { grid-area: nav; background: #f0f0f0; }
.main { grid-area: main; background: white; }
.footer{ grid-area: footer; background: #333; color: white; }
<div class="container">
<header class="header">Header</header>
<nav class="nav">Nav</nav>
<main class="main">Main Content</main>
<footer class="footer">Footer</footer>
</div>
✅ 效果:清晰的二维布局,语义化强,易于维护。
6.3 项目属性详解:grid-column/row-start/end, grid-area, justify-self, align-self
| 属性 | 作用 | 示例 | 说明 |
|---|---|---|---|
grid-column-start | 项目从哪条列线开始 | grid-column-start: 2; | 支持数字或名称 |
grid-column-end | 项目到哪条列线结束 | grid-column-end: 4; | 可用 span 2 表示跨越2列 |
grid-row-start | 项目从哪条行线开始 | grid-row-start: 1; | — |
grid-row-end | 项目到哪条行线结束 | grid-row-end: span 2; | — |
grid-column | 简写:start / end | grid-column: 2 / 4; | 推荐写法 |
grid-row | 简写:start / end | grid-row: 1 / span 2; | — |
grid-area | 四合一简写:row-start / col-start / row-end / col-end | grid-area: 1 / 2 / 3 / 4; | 也可用于命名区域 |
justify-self | 单个项目在单元格内的水平对齐 | center, start, end, stretch | 覆盖 justify-items |
align-self | 单个项目在单元格内的垂直对齐 | center, start, end, stretch | 覆盖 align-items |
grid-area 缩写示例
.item {
grid-area: 2 / 1 / 4 / 3;
/* 等价于:
grid-row-start: 2;
grid-column-start: 1;
grid-row-end: 4;
grid-column-end: 3;
*/
}
即:从第2行开始,第1列开始,到第4行结束,第3列结束 → 跨越2行2列。
代码示例:项目跨越与对齐
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 100px 200px;
gap: 10px;
}
.item-a {
grid-column: 1 / 3; /* 横跨前两列 */
background: red;
}
.item-b {
grid-row: 1 / 3; /* 纵跨两行 */
justify-self: center; /* 水平居中 */
align-self: end; /* 底部对齐 */
background: blue;
}
<div class="container">
<div class="item-a">A (col 1-2)</div>
<div class="item-b">B (row 1-2)</div>
<div>C</div>
</div>
✅ 效果:
- A 横跨第1-2列,第1行
- B 纵跨第1-2行,第3列,且在单元格内右下角对齐
- C 自动填入剩余位置
6.4 网格函数:fr 单位、minmax(), repeat(), fit-content()
| 函数/单位 | 语法 | 功能说明 | 示例 |
|---|---|---|---|
fr | 1fr, 2fr | 分数单位,表示可用空间的份数 | 1fr 2fr → 比例 1:2 |
minmax(min, max) | minmax(100px, 1fr) | 定义尺寸范围 | 最小100px,最大占满 |
repeat(n, track-list) | repeat(3, 1fr) | 重复生成轨道 | 三列等分 |
repeat(auto-fill, 100px) | 自动填充尽可能多的100px列 | 响应式卡片 | |
repeat(auto-fit, minmax(100px, 1fr)) | 自动适配,每列至少100px,可伸缩 | 更智能的响应式 | |
fit-content(length) | fit-content(200px) | 内容宽度最多不超过指定长度 | 类似 max-width 行为 |
响应式网格技巧对比
| 写法 | 行为描述 |
|---|---|
repeat(3, 1fr) | 固定3列,等分宽度 |
repeat(auto-fill, 100px) | 容器够宽就一直加100px列,不够就不显示 |
repeat(auto-fit, 100px) | 同上,但会拉伸填满剩余空间 |
repeat(auto-fit, minmax(150px, 1fr)) | 每列至少150px,超出则等分剩余空间(推荐) |
代码示例:响应式卡片网格
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
padding: 1rem;
}
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 1rem;
background: white;
}
<div class="card-grid">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
<!-- 可添加更多卡片 -->
</div>
✅ 效果:
- 大屏:每行尽可能放满 ≥250px 的卡片
- 小屏:自动变为单列
- 无媒体查询,纯 CSS 实现响应式
6.5 Grid 实战案例:复杂网页布局、仪表盘、杂志式排版
案例 1:复杂网页布局(带侧边栏和页脚)
.layout {
display: grid;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
grid-template-columns: 200px 1fr;
grid-template-rows: 80px 1fr 60px;
gap: 10px;
min-height: 100vh;
}
.sidebar { grid-area: sidebar; background: #333; color: white; }
.header { grid-area: header; background: #007acc; color: white; }
.main { grid-area: main; background: #f9f9f9; padding: 20px; }
.footer { grid-area: footer; background: #666; color: white; }
✅ 优势:无需浮动或定位,语义清晰。
案例 2:仪表盘布局(不规则区域)
.dashboard {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
grid-template-rows: 100px 200px 150px;
gap: 10px;
height: 100vh;
}
.big-chart { grid-area: 1 / 1 / 3 / 4; background: #ffcc00; } /* 横跨三列两行 */
.stats-left { grid-area: 3 / 1 / 4 / 2; background: #66bb6a; }
.stats-right { grid-area: 3 / 2 / 4 / 4; background: #42a5f5; }
.sidebar { grid-area: 1 / 4 / 4 / 5; background: #9c27b0; color: white; }
<div class="dashboard">
<div class="big-chart">主图表</div>
<div class="stats-left">统计A</div>
<div class="stats-right">统计B</div>
<div class="sidebar">控制面板</div>
</div>
✅ 实现不规则、跨区域的复杂布局。
案例 3:杂志式排版(图文混排)
.magazine {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto;
gap: 15px;
padding: 20px;
}
.article-main {
grid-column: 1 / 5; /* 全宽标题 */
font-size: 2em;
font-weight: bold;
}
.img-large {
grid-column: 1 / 3;
grid-row: span 2; /* 跨两行 */
background: url('large.jpg') center/cover;
}
.text-block {
grid-column: 3 / 5;
background: #f8f8f8;
padding: 10px;
}
✅ 模拟传统印刷品的灵活排版效果。
第 7 章:响应式设计与视口管理
7.1 移动优先 (Mobile-First) 设计理念
| 概念 | 定义 | 说明 |
|---|---|---|
| 移动优先 (Mobile-First) | 从最小屏幕开始设计,逐步增强大屏体验 | 使用 min-width 媒体查询向上适配 |
| 桌面优先 (Desktop-First) | 从最大屏幕开始设计,向下调整小屏样式 | 使用 max-width 向下覆盖 |
| 渐进增强 (Progressive Enhancement) | 基础功能在所有设备可用,高级功能按需添加 | 移动优先的实现策略 |
移动优先 vs 桌面优先 对比表
| 特性 | 移动优先 | 桌面优先 |
|---|---|---|
| 媒体查询方向 | @media (min-width: ...) | @media (max-width: ...) |
| 默认样式 | 针对手机(窄屏) | 针对桌面(宽屏) |
| 性能优化 | ✅ 更好(小屏加载轻量 CSS) | ❌ 可能加载冗余样式 |
| 维护性 | ✅ 推荐现代开发方式 | ⚠️ 易产生样式覆盖混乱 |
| 用户覆盖 | 所有设备都能访问基础内容 | 小屏可能被忽略 |
开发流程图示
[ 编写基础移动端样式 ]
↓
[ 添加 min-width 断点 ]
↓
[ 为平板/桌面增加布局增强 ]
↓
[ 最终:所有设备良好体验 ]
💡 核心原则:先保证小屏可用,再为大屏”加料”。
代码示例:移动优先媒体查询
/* 基础样式(手机) */
.container {
padding: 10px;
font-size: 14px;
}
/* 平板及以上 */
@media (min-width: 768px) {
.container {
padding: 20px;
font-size: 16px;
}
}
/* 桌面及以上 */
@media (min-width: 1024px) {
.container {
max-width: 1200px;
margin: 0 auto;
}
}
✅ 优势:小屏设备无需下载和解析大屏专用样式。
7.2 视口元标签(<meta name="viewport">)
| 属性 | 取值示例 | 功能说明 | 是否必需 |
|---|---|---|---|
width | device-width, 320, 414 | 设置视口宽度 | ✅ 推荐设置为 device-width |
initial-scale | 1.0, 0.5 | 初始缩放比例 | ✅ 推荐设为 1.0 |
user-scalable | yes, no | 是否允许用户缩放 | ⚠️ 设 no 不利于无障碍访问 |
maximum-scale / minimum-scale | 1.0, 2.0 | 限制缩放范围 | 可选 |
常见组合写法
| 场景 | <meta> 标签写法 |
|---|---|
| 标准响应式网页 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 禁止缩放(不推荐) | <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> |
| 固定宽度(如H5游戏) | <meta name="viewport" content="width=375, initial-scale=1"> |
📌 提示:
device-width表示设备的逻辑像素宽度(如 iPhone 14 Pro Max 为 430px)- 缺少该标签时,移动浏览器会模拟桌面宽度(通常 980px),导致页面被缩小显示
代码示例
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式页面</title>
<style>
body { margin: 0; font-size: 16px; }
.box {
width: 100%;
height: 200px;
background: #007acc;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div class="box">全宽蓝色块</div>
</body>
</html>
✅ 效果:.box 在手机上正确占据 100% 屏幕宽度。
7.3 媒体查询(@media)语法与常用特性 (width, height, orientation, resolution)
| 语法结构 | 示例 | 说明 |
|---|---|---|
@media media-type and (media-feature) { ... } | @media screen and (min-width: 768px) { ... } | 标准写法 |
多条件 and | (min-width: 768px) and (max-width: 1023px) | 同时满足 |
多条件 ,(或) | (orientation: portrait), (hover: hover) | 满足任一 |
not 否定 | not all and (color) | 取反结果 |
常用媒体特性对照表
| 特性 | 取值示例 | 用途 |
|---|---|---|
width | 768px, min-width, max-width | 响应式布局主要依据 |
height | 600px | 控制垂直空间(如全屏 banner) |
orientation | portrait, landscape | 区分竖屏/横屏 |
resolution | 2dppx, 192dpi | 高清屏适配(@2x 图) |
hover | hover, none | 判断是否支持悬停(触摸屏为 none) |
prefers-color-scheme | dark, light | 深色模式检测 |
prefers-reduced-motion | reduce | 动画偏好(无障碍) |
代码示例:多条件媒体查询
/* 横屏手机 */
@media (max-width: 767px) and (orientation: landscape) {
.hero-text { font-size: 18px; }
}
/* 平板竖屏 */
@media (min-width: 768px) and (max-width: 1023px) and (orientation: portrait) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
/* 高分辨率屏幕 */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.logo {
background-image: url('logo@2x.png');
background-size: 100px 50px;
}
}
/* 支持悬停的设备 */
@media (hover: hover) and (pointer: fine) {
.nav-item:hover { background: #eee; }
}
/* 深色模式 */
@media (prefers-color-scheme: dark) {
body { background: #121212; color: #fff; }
}
✅ 实现真正的”情境感知”式设计。
7.4 断点 (Breakpoints) 的设定策略
| 策略 | 说明 | 推荐做法 |
|---|---|---|
| 内容驱动断点 | 当内容在特定宽度下出现换行、挤压等问题时添加断点 | ✅ 推荐 |
| 设备参考断点 | 基于主流设备尺寸设置(iPhone, iPad, etc.) | 可作为起点,但需验证 |
| 预设断点系统 | 使用框架提供的断点(如 Bootstrap 的 sm/md/lg/xl) | 适合快速开发 |
常见断点参考值(单位:px)
| 断点名称 | min-width | 对应设备 |
|---|---|---|
| xs (超小) | 0 | 手机(竖屏) |
| sm (小) | 576px | 小屏手机横屏 / 超小平板 |
| md (中) | 768px | 平板(竖屏) |
| lg (大) | 992px | 平板(横屏) / 小桌面 |
| xl (超大) | 1200px | 桌面 |
| xxl | 1400px | 大桌面 |
📌 建议使用 Sass 变量或 CSS 自定义属性管理断点:
:root {
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
}
/* 使用 */
@media (min-width: var(--breakpoint-md)) {
/* 中屏以上样式 */
}
断点设计原则:
- ✅ 从窄到宽:使用 min-width 逐步增强
- ✅ 避免过多断点:3~5 个足够
- ✅ 测试真实内容:不要只看骨架
- ❌ 不要为每台设备设断点:响应的是”宽度”而非”设备”
7.5 相对单位深度解析:em, rem, vw, vh, %, ch, ex
| 单位 | 基准 | 说明 | 适用场景 |
|---|---|---|---|
% | 父元素对应尺寸 | 高度 % 需父元素有明确高度 | 宽度、弹性布局 |
em | 继承字体大小(或自身) | 文字相关组件内常用 | font-size, padding 在文字组件中 |
rem | 根元素字体大小(通常是 <html>) | 推荐用于全局布局 | 边距、容器尺寸、响应式字体 |
vw | 视口宽度的 1% | 1vw = 1% of viewport width | 全屏元素、响应式字体 |
vh | 视口高度的 1% | 注意移动端地址栏影响 | 全高布局(需处理兼容性) |
ch | 字符 “0” 的宽度 | 等宽字体中特别准确 | 代码块、输入框宽度 |
ex | 小写字母 “x” 的高度 | 字体相关度量 | 特殊排版需求(较少用) |
单位使用建议表
| 场景 | 推荐单位 | 示例 |
|---|---|---|
| 字体大小 | rem | font-size: 1.2rem; |
| 容器宽度 | %, rem, vw | width: 90%; 或 max-width: 80rem; |
| 间距(margin/padding) | rem | margin: 1rem 0; |
| 响应式字体 | clamp() + vw | font-size: clamp(1rem, 2.5vw, 2rem); |
| 全屏背景 | 100vw × 100vh | width: 100vw; height: 100vh; |
| 输入框字符限制宽度 | ch | input[type="text"] { width: 20ch; } |
代码示例:响应式字体
h1 {
/* 最小 1.5rem, 最大 3rem, 在视口中动态变化 */
font-size: clamp(1.5rem, 4vw, 3rem);
}
.sidebar {
width: 80%; /* 相对于父容器 */
max-width: 20rem; /* rem 保证不会过大 */
}
.hero-section {
height: 100vh; /* 全高 */
padding: 10vh 5vw; /* 边距随视口变化 */
}
✅ 实现真正流体的响应式效果。
7.6 流体布局与弹性设计原则
| 原则 | 说明 | 实现方式 |
|---|---|---|
| 使用相对单位 | 避免固定像素值(px) | 用 rem, %, vw 替代 px |
| 弹性容器 | 容器能自动调整子元素排列 | Flexbox、Grid、display: inline-block |
| 最大最小约束 | 防止过度拉伸或压缩 | min-width, max-width, min-height |
| 内容自适应 | 图片、视频等媒体可缩放 | img { max-width: 100%; height: auto; } |
| 断点微调 | 在关键宽度点优化布局 | @media 调整 flex-direction, grid-template |
流体布局示例:卡片网格
.card-container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card {
flex: 1 1 calc(33.333% - 1rem); /* 三列,减去gap */
min-width: 250px; /* 最小宽度 */
background: white;
border-radius: 8px;
overflow: hidden;
}
.card img {
width: 100%;
height: auto;
}
✅ 效果:
- 大屏:每行最多3张卡
- 中屏:自动变为2列
- 小屏:单列堆叠
- 无媒体查询,纯流体实现
弹性设计检查清单
- ✅ 所有尺寸使用相对单位(rem/%/vw)
- ✅ 图片设置
max-width: 100% - ✅ 容器使用 Flexbox 或 Grid
- ✅ 关键元素设置
min-width/max-width - ✅ 在不同设备宽度下测试布局流畅性
第 8 章:视觉样式与装饰效果
8.1 颜色系统:十六进制、RGB/RGBA、HSL/HSLA、颜色关键字
| 颜色格式 | 示例 | 说明 | 适用场景 |
|---|---|---|---|
| 十六进制 (Hex) | #ff0000, #f00 | 前缀 #,6位或3位表示 RGB | 最常用,简洁 |
| RGB | rgb(255, 0, 0) | 红绿蓝三原色,0–255 | 精确控制色彩 |
| RGBA | rgba(255, 0, 0, 0.5) | RGB + Alpha(透明度 0–1) | 半透明背景、遮罩 |
| HSL | hsl(0, 100%, 50%) | 色相(H)、饱和度(S)、亮度(L) | 更直观的颜色调整 |
| HSLA | hsla(0, 100%, 50%, 0.3) | HSL + Alpha | 半透明且易调色 |
| 颜色关键字 | red, blue, transparent | 预定义名称(共147个) | 快速原型、语义化 |
📌 提示:
transparent等价于rgba(0,0,0,0)- HSL 更适合通过 JS 动态调整颜色(如”更亮”、“更饱和”)
HSL 参数说明
| 参数 | 取值范围 | 含义 |
|---|---|---|
| H (Hue) | 0–360 | 色相(红=0,绿=120,蓝=240) |
| S (Saturation) | 0%–100% | 饱和度(灰→鲜艳) |
| L (Lightness) | 0%–100% | 亮度(黑→白) |
代码示例
.example {
color: #f00; /* 红 */
background-color: rgba(0,0,255,0.3); /* 半透蓝 */
border-color: hsl(120, 100%, 25%); /* 深绿色 */
box-shadow: 0 0 10px hsla(0, 100%, 50%, 0.5); /* 红色半透阴影 */
}
✅ 推荐使用 HSLA 进行动态主题切换。
8.2 背景 (background) 属性:图像、重复、位置、大小 (cover, contain)、多重背景、background-origin/clip
| 属性 | 功能 | 示例 |
|---|---|---|
background-color | 背景色 | #eee |
background-image | 背景图 | url(bg.jpg) |
background-repeat | 重复方式 | no-repeat, repeat-x |
background-position | 图片位置 | center, 10px 20px, top right |
background-size | 图片尺寸 | cover, contain, 100% 200px |
background-attachment | 滚动行为 | scroll, fixed(视差) |
background-origin | 定位参考框 | padding-box, border-box, content-box |
background-clip | 裁剪区域 | 同上,控制背景绘制范围 |
background(简写) | 组合写法 | 推荐顺序见下方 |
background-size 对照表
| 值 | 行为描述 |
|---|---|
auto | 保持原始尺寸 |
cover | 缩放图片以完全覆盖容器(可能裁剪) |
contain | 缩放图片使其完整显示(留空白) |
100% 100% | 拉伸填满(可能变形) |
200px auto | 宽200px,高自动等比 |
多重背景语法(从上到下堆叠)
.multi-bg {
background-image:
url(layer1.png), /* 最上层 */
url(layer2.png),
linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5));
background-position:
center,
top left,
center;
background-repeat: no-repeat, repeat, no-repeat;
background-size: cover, auto, cover;
}
✅ 实现图像+渐变叠加效果。
background-origin vs background-clip
| 属性 | 控制什么? | 默认值 |
|---|---|---|
background-origin | position 和 size 的参考点 | padding-box |
background-clip | 背景(包括颜色和图像)的绘制区域 | border-box |
.example {
padding: 20px;
border: 10px dashed red;
background: url(logo.png) no-repeat;
background-origin: content-box; /* 图片从内容区开始定位 */
background-clip: content-box; /* 背景只在内容区显示 */
}
✅ 效果:背景图不覆盖 padding 和 border 区域。
8.3 边框 (border):border-radius (圆角), border-image
| 属性 | 功能 | 示例 |
|---|---|---|
border-width | 边框宽度 | 2px |
border-style | 边框样式 | solid, dashed, double |
border-color | 边框颜色 | #333 |
border-radius | 圆角半径 | 10px, 50%(圆形) |
border-image-source | 边框图像源 | url(border.png) |
border-image-slice | 切片方式 | 30 fill(保留中间) |
border-image-width | 图像边框宽度 | 10px, 20% |
border-image-outset | 外扩距离 | 5px |
border-image-repeat | 平铺方式 | stretch, repeat, round |
border-image(简写) | source slice width outset repeat | url() 30 round |
border-radius 高级用法
/* 四角统一 */
border-radius: 10px;
/* 左上右下 */
border-radius: 10px 20px;
/* 左上 右上 右下 左下 */
border-radius: 10px 20px 30px 40px;
/* 椭圆圆角(水平 / 垂直) */
border-radius: 20px / 10px;
/* 分别设置每个角 */
border-top-left-radius: 15px;
✅ 50% 可创建完美圆形头像:
.avatar {
width: 100px;
height: 100px;
border-radius: 50%;
overflow: hidden;
}
border-image 示例:花纹边框
.fancy-border {
border: 20px solid transparent;
border-image: url('border-pattern.png') 30 round;
/* 图像被切成9宫格,30px为切片宽度,round自动平铺 */
}
⚠️ 注意:border-image 兼容性较好,但性能开销略高。
8.4 阴影:box-shadow, text-shadow
| 属性 | 参数顺序 | 示例 |
|---|---|---|
box-shadow | h-offset v-offset blur spread color inset? | 2px 2px 5px 0px rgba(0,0,0,0.3) |
text-shadow | h-offset v-offset blur color | 1px 1px 2px black |
参数说明
| 参数 | 含义 | 取值 |
|---|---|---|
h-offset | 水平偏移 | 正右负左 |
v-offset | 垂直偏移 | 正下负上 |
blur | 模糊半径 | 越大越模糊 |
spread | 扩展半径(仅 box-shadow) | 正值扩大,负值收缩 |
inset | 内阴影关键字 | 添加则为内阴影 |
多重阴影语法(逗号分隔)
.card {
box-shadow:
0 2px 4px rgba(0,0,0,0.1),
0 8px 16px rgba(0,0,0,0.1);
}
.button {
text-shadow:
1px 1px 1px #fff,
-1px -1px 1px #000;
}
✅ 多层阴影可模拟真实光照层次感。
内阴影示例(凹陷效果)
.inset-panel {
box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
background: #f0f0f0;
}
✅ 常用于输入框、按钮按下状态。
8.5 渐变:线性渐变 (linear-gradient), 径向渐变 (radial-gradient), 重复渐变
| 渐变类型 | 函数 | 示例 |
|---|---|---|
| 线性渐变 | linear-gradient() | to right, red, blue |
| 径向渐变 | radial-gradient() | circle at center, yellow, red |
| 重复线性 | repeating-linear-gradient() | 45deg, red 0, red 10px, white 10px, white 20px |
| 重复径向 | repeating-radial-gradient() | circle, red 0 10px, white 10px 20px |
linear-gradient 语法
background: linear-gradient(
[to left | right | top | bottom | 角度],
color-stop1, color-stop2, ...
);
/* 从左到右红→蓝 */
background: linear-gradient(to right, red, blue);
/* 45度角,带色标位置 */
background: linear-gradient(45deg, red 0%, orange 25%, yellow 50%, green 75%, blue 100%);
radial-gradient 语法
background: radial-gradient(
[shape] [size] at [position],
color-stop1, color-stop2
);
/* 圆形,中心点,黄→红 */
background: radial-gradient(circle at center, yellow, red);
/* 椭圆,左上角,小→大 */
background: radial-gradient(ellipse farthest-corner at top left, #ff0, #00f);
重复渐变应用:条纹背景
.stripes {
background: repeating-linear-gradient(
45deg,
#f00,
#f00 10px,
#000 10px,
#000 20px
);
}
✅ 创建无限重复的 45° 红黑条纹。
8.6 变形 (transform):2D 变换 (translate, rotate, scale, skew),3D 变换基础
| 函数 | 作用 | 示例 |
|---|---|---|
translate(x, y) | 位移 | translate(10px, -5px) |
rotate(angle) | 旋转 | rotate(45deg) |
scale(sx, sy?) | 缩放 | scale(1.5), scale(1, 2) |
skew(ax, ay?) | 倾斜 | skew(10deg, 5deg) |
matrix(a,b,c,d,tx,ty) | 2D 矩阵变换 | 高级用法 |
perspective(n) | 3D 透视距离 | perspective(500px) |
rotateX(angle) | 绕 X 轴旋转 | rotateX(45deg) |
rotateY(angle) | 绕 Y 轴旋转 | rotateY(30deg) |
translateZ(z) | Z 轴位移 | translateZ(100px) |
scaleZ(sz) | Z 轴缩放 | scaleZ(2) |
3D 变换关键属性
| 属性 | 作用 |
|---|---|
transform-style: preserve-3d | 子元素也参与 3D 空间 |
perspective | 设置观察者与 Z=0 平面的距离 |
perspective-origin | 透视视角原点(默认 center) |
代码示例:3D 卡片翻转
.card-container {
perspective: 1000px;
}
.card {
transform-style: preserve-3d;
transition: transform 0.6s;
}
.card:hover {
transform: rotateY(180deg);
}
.front { backface-visibility: hidden; }
.back { backface-visibility: hidden; transform: rotateY(180deg); }
✅ 实现鼠标悬停翻转卡片效果。
8.7 过渡 (transition):属性、时长、缓动函数、延迟
| 属性 | 作用 | 示例 |
|---|---|---|
transition-property | 要过渡的属性 | width, all |
transition-duration | 过渡时长 | 0.3s, 500ms |
transition-timing-function | 缓动函数 | ease, linear, cubic-bezier() |
transition-delay | 延迟时间 | 0.2s |
transition(简写) | property duration timing-function delay | 推荐写法 |
常用缓动函数
| 值 | 效果 | 适用场景 |
|---|---|---|
ease(默认) | 慢快慢 | 通用 |
linear | 匀速 | 旋转、循环动画 |
ease-in | 慢→快 | 元素入场 |
ease-out | 快→慢 | 元素消失 |
ease-in-out | 慢→快→慢 | 弹性进出 |
cubic-bezier(x1,y1,x2,y2) | 自定义贝塞尔曲线 | 精确控制 |
代码示例:按钮悬停效果
.btn {
background: #007acc;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
/* 过渡所有变化属性 */
transition: all 0.3s ease;
}
.btn:hover {
background: #005a99;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
✅ 用户交互更流畅、有反馈感。
8.8 动画 (animation):@keyframes, animation-* 属性详解
| 属性 | 作用 | 示例 |
|---|---|---|
@keyframes name | 定义动画关键帧 | @keyframes slideIn { from {} to {} } |
animation-name | 引用关键帧名称 | slideIn |
animation-duration | 动画时长 | 1s |
animation-timing-function | 缓动函数 | ease-in-out |
animation-delay | 延迟启动 | 0.5s |
animation-iteration-count | 循环次数 | 3, infinite |
animation-direction | 方向 | normal, reverse, alternate |
animation-fill-mode | 动画前后状态 | none, forwards, backwards, both |
animation-play-state | 播放状态 | running, paused |
animation(简写) | 组合所有属性 | 推荐最后写 name duration |
@keyframes 语法
@keyframes fadeIn {
0% { opacity: 0; transform: translateY(10px); }
100% { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
from, to { transform: scale(1); }
50% { transform: scale(1.1); }
}
完整动画示例:加载动画
@keyframes spin {
to { transform: rotate(360deg); }
}
.loader {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #007acc;
border-radius: 50%;
animation: spin 1s linear infinite;
}
<div class="loader"></div>
✅ 创建无限旋转的加载指示器。
animation-fill-mode 说明
| 值 | 含义 |
|---|---|
none | 动画外无影响 |
forwards | 结束后保持最后一帧 |
backwards | 开始前应用第一帧样式 |
both | 同时应用 forwards 和 backwards |
.fade-in {
animation: fadeIn 1s forwards;
}
/* 动画结束后 opacity 保持 1 */
第 9 章:高级 CSS 概念与机制
9.1 层叠 (Cascading) 与继承 (Inheritance) 规则
| 概念 | 定义 | 说明 |
|---|---|---|
| 层叠 (Cascading) | 多个样式规则作用于同一元素时的冲突解决机制 | 按”来源 → 重要性 → 特异性 → 顺序”决定 |
| 继承 (Inheritance) | 子元素自动获得父元素某些样式的特性 | 并非所有属性都可继承 |
层叠优先级(从高到低)
| 优先级 | 来源 | 说明 |
|---|---|---|
| 1 | 用户代理样式(浏览器默认) | 如 <h1> 默认加粗 |
| 2 | 用户样式(用户自定义) | 较少使用 |
| 3 | 作者样式(开发者编写) | 我们编写的 CSS |
| 4 | !important 声明 | 打破常规层叠,慎用 |
| 5 | 特异性 (Specificity) | ID > 类 > 标签 |
| 6 | 源码顺序 | 后出现的覆盖先出现的(同特异性) |
特异性计算表
| 选择器类型 | 权重(千-百-十-个) |
|---|---|
内联样式 style="" | 1,0,0,0 |
ID 选择器 #id | 0,1,0,0 |
类、属性、伪类 .class, [type], :hover | 0,0,1,0 |
元素、伪元素 div, ::before | 0,0,0,1 |
通配符 *、组合符 +, >、否定伪类 :not() | 0,0,0,0 |
📌 示例:
#nav .item a→ 0,1,1,1div#header nav ul li a→ 0,1,0,5
可继承属性示例
| 属性类别 | 可继承属性 |
|---|---|
| 文本相关 | color, font-family, font-size, line-height, text-align |
| 列表相关 | list-style |
| 不可继承 | width, height, margin, padding, border, display, position |
代码示例
/* 特异性 0,0,1,1 */
.nav .link { color: blue; }
/* 特异性 0,0,0,1,但后出现,同级覆盖 */
.link { color: red; } /* ✅ 最终生效 */
/* 使用 !important 强制优先 */
.link { color: green !important; } /* ✅ 最终为绿色 */
⚠️ 建议:避免滥用 !important,可通过提高特异性或重构选择器解决冲突。
9.2 特殊值:inherit, initial, unset, revert
| 关键字 | 作用 | 示例 | 适用场景 |
|---|---|---|---|
inherit | 强制继承父元素的计算值 | color: inherit; | 子元素需与父元素一致(如链接颜色) |
initial | 重置为属性的初始值 | display: initial; | 恢复默认行为(如取消 display: flex) |
unset | 若可继承 → inherit;否则 → initial | margin: unset; | 通用重置 |
revert | 恢复到用户代理或用户样式,忽略作者样式 | font-weight: revert; | 覆盖框架样式 |
初始值对照表
| 属性 | 初始值 (initial) |
|---|---|
color | black(通常由浏览器决定) |
display | inline |
margin | 0 |
font-weight | normal (400) |
text-align | start (通常为 left) |
代码示例
.parent {
color: #007acc;
font-weight: bold;
margin: 20px;
}
.child {
color: inherit; /* 蓝色,继承父元素 */
font-weight: initial; /* normal,重置为初始值 */
margin: unset; /* 0,因为 margin 不可继承 */
display: revert; /* 恢复为 inline(若原为 block) */
}
✅ unset 是最常用的”安全重置”值。
9.3 BFC (块级格式化上下文):触发条件与实际应用
| 概念 | 定义 | 说明 |
|---|---|---|
| BFC (Block Formatting Context) | 一个独立的渲染区域,内部块级元素的布局不受外部影响 | 类似”隔离的沙箱” |
触发 BFC 的条件(满足任一即可)
| 条件 | 示例 CSS |
|---|---|
根元素 <html> | — |
float 不为 none | float: left; |
position 为 absolute 或 fixed | position: absolute; |
display 为 inline-block, flex, grid, table-cell, table-caption | display: flex; |
overflow 不为 visible | overflow: hidden;(最常用) |
BFC 的特性
- ✅ 内部块级元素垂直排列
- ✅ 相邻 margin 不会合并(外边距折叠被阻止)
- ✅ 不与浮动元素重叠
- ✅ 包含内部浮动元素(清除浮动)
实际应用案例
案例 1:防止外边距折叠
.container {
overflow: hidden; /* 触发 BFC */
}
.child {
margin: 20px;
}
/* 两个 .child 的上下 margin 不会折叠 */
案例 2:文字环绕浮动元素时避免重叠
.float-left {
float: left;
width: 100px;
height: 100px;
background: red;
}
.text-content {
overflow: hidden; /* 触发 BFC,文字不与浮动块重叠 */
}
案例 3:清除浮动(旧方法 vs 现代方法)
/* 旧方法:clearfix */
.clearfix::after {
content: "";
display: block;
clear: both;
}
/* 现代方法:直接触发 BFC */
.container {
overflow: hidden; /* 自动包含浮动子元素 */
}
✅ 推荐使用 overflow: hidden 或 display: flow-root(专为清除浮动设计)。
9.4 IFC (行内格式化上下文) 基础
| 概念 | 定义 | 说明 |
|---|---|---|
| IFC (Inline Formatting Context) | 块级容器中仅包含行内级元素时形成的格式化上下文 | 文本排版的基础 |
触发条件
- 块级容器(如 div, p)中只包含行内元素(span, a, img 等)
- 或包含纯文本内容
IFC 的布局规则
- ✅ 行内元素水平排列,超出换行
- ✅ 每行形成一个”行框”(line box)
- ✅ 行框高度由内部元素的
line-height和vertical-align决定 - ✅
text-align控制行内内容水平对齐
vertical-align 常用值
| 值 | 说明 |
|---|---|
baseline(默认) | 基线对齐 |
top | 顶部对齐 |
middle | 居中对齐 |
bottom | 底部对齐 |
text-top / text-bottom | 文本顶部/底部对齐 |
垂直对齐问题示例
<div>
<img src="icon.png" alt="icon">
<span>文本</span>
</div>
img { vertical-align: middle; } /* 使图标与文本垂直居中 */
✅ 若不设置,img 默认 baseline 对齐,底部会留空隙。
9.5 CSS 自定义属性 (Variables):定义、使用 (var())、作用域
| 语法 | 说明 | 示例 |
|---|---|---|
--name: value; | 定义变量(必须以 -- 开头) | --primary-color: #007acc; |
var(--name, fallback) | 使用变量(可设默认值) | color: var(--primary-color, blue); |
| 作用域 | 在哪个选择器内定义,就在其后代中生效 | 推荐在 :root 定义全局变量 |
代码示例:主题变量系统
:root {
--primary-color: #007acc;
--error-color: #d32f2f;
--font-size-base: 16px;
--border-radius: 4px;
}
.button {
background: var(--primary-color);
color: white;
padding: 10px 20px;
border: none;
border-radius: var(--border-radius);
font-size: var(--font-size-base);
}
/* 动态修改变量(JS) */
/* document.documentElement.style.setProperty('--primary-color', 'purple'); */
✅ 支持 JavaScript 动态修改,实现主题切换。
9.6 calc() 函数:动态计算值
| 语法 | 说明 | 示例 |
|---|---|---|
calc(expression) | 表达式中可包含 +, -, *, / | width: calc(100% - 20px); |
| 运算符 | + 和 - 两侧必须有空格 | calc(100% - 2em) ✅;calc(100%-2em) ❌ |
| 单位混合 | 可混合 %, px, em, vw 等 | height: calc(100vh - 60px); |
| 嵌套 | 可嵌套 calc() | width: calc(50% + calc(10px * 2)); |
实际应用场景
| 场景 | calc() 写法 |
|---|---|
| 全宽减去边栏 | width: calc(100% - 200px); |
| 响应式字体 | font-size: clamp(1rem, 2.5vw, 2rem);(配合 calc 更灵活) |
| 网格间隙补偿 | grid-template-columns: repeat(3, calc((100% - 20px) / 3)); |
| 视口减去导航栏 | main { height: calc(100vh - 80px); } |
代码示例:自适应侧边栏布局
.container {
display: flex;
}
.sidebar {
width: 200px;
}
.main-content {
width: calc(100% - 200px);
/* 主内容区自动填满剩余空间 */
}
✅ 替代部分 JavaScript 计算逻辑。
9.7 :root 伪类与全局变量
| 概念 | 定义 | 说明 |
|---|---|---|
:root | 代表文档的根元素(即 <html>) | 特异性为 0,0,1,0,高于普通标签选择器 |
| 全局变量 | 在 :root 中定义的 CSS 变量 | 可在文档任何位置使用 |
优势
- ✅ 变量集中管理,易于维护
- ✅ 支持继承,子元素可直接使用
- ✅ 可结合媒体查询动态更新
代码示例:响应式断点变量
:root {
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--spacing-unit: 1rem;
}
@media (max-width: var(--breakpoint-md)) {
:root {
--spacing-unit: 0.5rem; /* 小屏减小间距 */
}
}
.card {
margin: var(--spacing-unit);
}
主题切换示例
:root {
--bg-color: white;
--text-color: black;
}
[data-theme="dark"] {
--bg-color: #121212;
--text-color: #eee;
}
body {
background: var(--bg-color);
color: var(--text-color);
transition: all 0.3s ease;
}
<!-- 注意:以下示例中的 onclick 在服务端渲染环境中无法运行 -->
<!-- <button onclick="document.body.setAttribute('data-theme','dark')">切换深色模式</button> -->
<button class="theme-toggle">切换深色模式</button>
✅ 实现无需预编译的动态主题系统。
第 10 章:CSS 方法论与工程化
10.1 CSS 架构模式:BEM, SMACSS, OOCSS
| 架构 | 全称 | 核心思想 | 适用场景 |
|---|---|---|---|
| BEM | Block Element Modifier | 将 UI 拆分为独立的块(Block),元素(Element)和修饰符(Modifier) | 中大型项目,组件化开发 |
| SMACSS | Scalable and Modular Architecture for CSS | 将样式分为五类:基础、布局、模块、状态、主题 | 复杂页面结构,强调分层 |
| OOCSS | Object-Oriented CSS | 面向对象思想,分离结构与皮肤,容器与内容 | 提高样式复用性 |
BEM 命名规范详解
| 部分 | 语法 | 示例 | 说明 |
|---|---|---|---|
| Block | block-name | header, menu | 独立功能模块 |
| Element | block__element | menu__item, header__logo | 属于某个块的子元素 |
| Modifier | block--modifier 或 block__element--modifier | menu--vertical, button__icon--hidden | 表示状态或变体 |
📌 BEM 优势:
- 类名语义清晰
- 避免嵌套过深
- 支持并行开发
BEM 代码示例
<nav class="menu menu--horizontal">
<ul class="menu__list">
<li class="menu__item menu__item--active">
<a href="#" class="menu__link">首页</a>
</li>
<li class="menu__item">
<a href="#" class="menu__link">关于</a>
</li>
</ul>
</nav>
.menu { display: flex; }
.menu--horizontal { flex-direction: row; }
.menu__list { list-style: none; margin: 0; padding: 0; }
.menu__item { position: relative; }
.menu__item--active { font-weight: bold; }
.menu__link { text-decoration: none; padding: 10px; }
SMACSS 分类表
| 类别 | 描述 | 示例 |
|---|---|---|
| Base | 元素默认样式 | body, h1, a |
| Layout | 页面级布局容器 | .header, .sidebar, .main |
| Module | 可复用组件 | .carousel, .dropdown |
| State | 特定状态样式 | .is-active, .is-hidden |
| Theme | 主题相关样式 | .theme-dark |
OOCSS 原则示例
/* 结构与皮肤分离 */
.btn { display: inline-block; padding: 10px 20px; border-radius: 4px; }
.btn-primary { background: #007acc; color: white; }
.btn-success { background: #28a745; color: white; }
/* 容器与内容分离 */
.media { display: flex; align-items: flex-start; }
.media__img { margin-right: 16px; }
.media__body { flex: 1; }
✅ 实现高复用、低耦合的样式系统。
10.2 CSS 预处理器:Sass/SCSS, Less, Stylus (变量、嵌套、混合、函数)
| 特性 | Sass (SCSS) 示例 | 说明 |
|---|---|---|
| 变量 | $primary-color: #007acc; | 以 $ 开头,支持作用域 |
| 嵌套 | nav { ul { li { a { &:hover { ... } } } } } | 模拟 DOM 结构,减少重复选择器 |
| 混合 (Mixin) | @mixin center { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } | 可带参数的代码块 |
| 继承 (@extend) | %.btn-base { padding: 10px; } .btn { @extend %btn-base; } | 减少 CSS 重复 |
| 函数 | @function pow($n, $exp) { @return $n * $exp; } | 自定义计算逻辑 |
| 条件与循环 | @if $type == primary { ... } @for $i from 1 through 3 { .item-#{$i} { order: $i; } } | 动态生成样式 |
SCSS 代码示例:按钮系统
// 变量
$primary: #007acc;
$spacing: 1rem;
// 混合
@mixin button-style($bg, $color: white) {
background: $bg;
color: $color;
border: none;
padding: $spacing * 0.8 $spacing;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
opacity: 0.9;
transform: translateY(-1px);
}
}
// 使用
.btn {
@include button-style($primary);
&--success {
@include button-style(#28a745);
}
&--large {
padding: $spacing $spacing * 1.5;
}
}
编译后生成标准 CSS,可在浏览器运行。
预处理器对比
| 工具 | 语法风格 | 特点 |
|---|---|---|
| Sass/SCSS | .sass(缩进)或 .scss(类似 CSS) | 生态最成熟,功能最全 |
| Less | .less,类似 CSS | 支持客户端编译(不推荐) |
| Stylus | .styl,极简语法(可省略 {} ;) | 灵活但易混乱 |
✅ 推荐使用 SCSS,社区支持最好。
10.3 CSS 后处理器:PostCSS (插件生态、自动前缀、未来语法)
| 概念 | 说明 |
|---|---|
| PostCSS | 基于 JavaScript 的 CSS 处理工具,通过插件转换 CSS |
| AST (抽象语法树) | 将 CSS 解析为树结构,便于程序操作 |
常用 PostCSS 插件
| 插件 | 功能 | 示例配置 |
|---|---|---|
| autoprefixer | 自动添加浏览器前缀 | browsers: ['> 1%', 'last 2 versions'] |
| postcss-preset-env | 使用未来 CSS 语法(如 nesting, custom media) | 支持 @custom-media |
| cssnano | CSS 压缩优化 | 减小文件体积 |
| postcss-import | 支持 @import 合并文件 | 替代预处理器的 @import |
| postcss-flexbugs-fixes | 修复 Flexbox 兼容性问题 | 提升跨浏览器一致性 |
postcss.config.js 示例
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-preset-env')({
stage: 3, // 使用稳定提案
features: {
'nesting-rules': true
}
}),
require('autoprefixer'),
require('cssnano') // 生产环境启用
]
}
使用未来语法示例(需 postcss-preset-env)
/* 嵌套(类似 SCSS) */
.card {
padding: 1rem;
&__title {
font-weight: bold;
}
&__footer {
border-top: 1px solid #eee;
}
}
/* 自定义媒体查询 */
@custom-media --sm (width >= 576px);
@media (--sm) {
.card { max-width: 500px; }
}
✅ 实现”原生 CSS + 插件增强”的现代开发流。
10.4 模块化与组件化 CSS
| 方案 | 机制 | 优点 | 缺点 |
|---|---|---|---|
| CSS Modules | 将 CSS 文件编译为 JS 模块,类名局部作用域 | 彻底避免命名冲突 | 需构建工具支持 |
| Scoped CSS | Vue <style scoped> 或 Shadow DOM | 样式仅作用于当前组件 | Vue 特有 |
| 原子化 CSS (Tailwind) | 每个类只负责一个样式属性 | 高复用,无冗余 | 学习成本高,HTML 膨胀 |
| CSS-in-JS | 在 JS 中写样式(Styled-components) | 动态样式强,作用域安全 | 运行时开销 |
CSS Modules 示例
/* Button.module.css */
.root {
padding: 10px 20px;
background: #007acc;
color: white;
border: none;
border-radius: 4px;
}
.primary {
background: #d32f2f;
}
// React 组件中使用
import styles from './Button.module.css';
function Button({ variant }) {
return (
<button className={`${styles.root} ${styles[variant]}`}>
Click Me
</button>
);
}
// 编译后类名类似:`Button_root__abc123`
组件化设计原则
- ✅ 单一职责:每个组件只做一件事
- ✅ 可组合:组件可嵌套使用
- ✅ 可配置:通过类名或属性定制外观
- ✅ 文档化:提供使用说明和示例
10.5 CSS 性能优化:减少重排重绘、高效选择器、文件压缩、动画性能 (transform, opacity, will-change)
| 优化方向 | 策略 | 说明 |
|---|---|---|
| 减少重排重绘 | 避免频繁修改布局属性(width, height, margin, top 等) | 每次修改可能触发整个页面重新计算 |
| 高效选择器 | 避免深层嵌套和通用选择器(*, tag) | 浏览器从右向左匹配,.a .b .c 比 .c 慢 |
| 动画性能 | 优先使用 transform 和 opacity | 这些属性由 GPU 加速,不触发重排 |
| will-change | 提示浏览器提前优化 | will-change: transform; |
| 文件压缩 | 使用 cssnano 或构建工具压缩 | 删除空格、注释,合并规则 |
| 关键 CSS 内联 | 将首屏关键样式内联到 <head> | 减少渲染阻塞 |
| 异步加载非关键 CSS | <link rel="preload" as="style"> 或动态插入 | 提升首屏速度 |
触发重排的属性(慎用)
width,height,margin,padding,display,position,overflow,float,border
高性能动画示例
.animated-box {
/* ✅ 推荐:GPU 加速 */
transition: transform 0.3s ease, opacity 0.3s ease;
}
.animated-box:hover {
transform: scale(1.1) rotate(5deg);
opacity: 0.8;
}
/* ❌ 不推荐:触发重排 */
.bad-animation {
width: 200px;
height: 200px;
}
.bad-animation:hover {
width: 220px;
height: 220px;
}
will-change 使用建议
.carousel-item {
will-change: transform; /* 提示将要变换 */
transition: transform 0.5s ease;
}
⚠️ 仅对真正会动画的元素使用,滥用会导致内存浪费。
构建优化流程
源文件 (.scss)
↓
Sass 编译 → CSS
↓
PostCSS 处理(autoprefixer, nesting)
↓
压缩(cssnano)
↓
输出生产 CSS 文件
✅ 结合 Webpack/Vite 实现自动化工程流。
第 11 章:无障碍访问 (a11y) 与用户体验
11.1 CSS 在无障碍中的角色
| 作用 | 说明 | 正确做法 vs 错误做法 |
|---|---|---|
| 视觉呈现 | 将语义化 HTML 转换为用户可感知的界面 | ✅ 用 CSS 控制样式 ❌ 用 CSS 改变语义(如用 div 模拟按钮) |
| 响应用户偏好 | 尊重用户系统设置(如动画、颜色模式) | ✅ 使用 prefers-* 媒体查询 ❌ 强制覆盖用户设置 |
| 焦点管理 | 确保键盘用户能清晰看到当前焦点 | ✅ 定义清晰的 :focus 样式❌ 设置 outline: none 而不提供替代样式 |
| 内容隐藏 | 控制元素的显示与隐藏 | ✅ 使用 visibility: hidden 或 aria-hidden="true"❌ 仅用 display: none 隐藏仍需屏幕阅读器读取的内容 |
📌 核心原则:CSS 不应破坏 HTML 的语义结构。
常见反模式与修复
| 问题 | 反模式代码 | 修复方案 |
|---|---|---|
| 用 div 当按钮 | <div onclick="...">提交</div> | 改用 <button> 或添加 role="button" tabindex="0" |
| 隐藏标题但需读取 | <h2 style="display:none">搜索结果</h2> | 改用 .sr-only 类(见下文) |
| 移除轮廓后无替代 | *:focus { outline: none; } | 提供高对比度背景或边框 |
屏幕阅读器友好类(.sr-only)
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
<h2 class="sr-only">搜索结果</h2>
<!-- 屏幕阅读器可读,视觉上隐藏 -->
✅ 用于分页、状态提示等视觉隐藏但语义重要的内容。
11.2 颜色对比度与可读性
| WCAG 等级 | 正常文本 (≥) | 大文本 (≥) | 说明 |
|---|---|---|---|
| AA | 4.5:1 | 3:1 | 最低可接受标准 |
| AAA | 7:1 | 4.5:1 | 更高可访问性 |
📌 大文本:18pt(24px)以上,或粗体 14pt(18.66px)以上。
对比度计算示例
| 背景色 | 文本色 | 对比度 | 是否达标 (AA) |
|---|---|---|---|
#ffffff (白) | #000000 (黑) | 21:1 | ✅ |
#ffffff | #666666 | 4.5:1 | ✅ (刚好) |
#f0f0f0 | #333333 | 12.6:1 | ✅ |
#ffeb3b (黄) | #000000 | 19.7:1 | ✅ |
#ffeb3b | #ffffff | 1.1:1 | ❌ 极差 |
提高对比度策略
- ✅ 使用深灰 (
#333) 替代纯黑,减少视觉疲劳 - ✅ 背景复杂时添加文字阴影或半透底衬
- ✅ 提供”高对比度”主题切换选项
代码示例:增强可读性
.text-overlay {
color: white;
/* 添加半透黑底衬提升对比度 */
background: linear-gradient(transparent, rgba(0,0,0,0.7));
padding: 10px;
}
/* 或使用 text-shadow */
.high-contrast {
color: #000;
text-shadow: 1px 1px 1px #fff, -1px -1px 1px #fff;
}
✅ 推荐工具:WebAIM Contrast Checker
11.3 键盘导航与 :focus 样式
| 概念 | 说明 |
|---|---|
| 键盘用户 | 包括残障人士、开发者、高效用户 |
| Tab 键 | 在可聚焦元素间移动(<a>, <button>, input, tabindex 元素) |
:focus | 伪类,表示元素获得焦点 |
:focus-visible | 仅在键盘触发时显示焦点样式(现代浏览器支持) |
可聚焦元素
| 元素 | 默认可聚焦? |
|---|---|
<a href="..."> | ✅ |
<button> | ✅ |
<input>, <textarea>, <select> | ✅ |
<details>, <summary> | ✅ |
tabindex="0" | ✅(手动添加) |
tabindex="-1" | ❌(不可聚焦,但可通过 JS 聚焦) |
焦点样式最佳实践
/* ✅ 好做法:提供清晰的视觉反馈 */
button:focus,
input:focus,
.custom-button:focus {
outline: 2px solid #007acc;
outline-offset: 2px;
/* 或使用 box-shadow */
box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.3);
}
/* ✅ 现代方案:仅键盘用户显示轮廓 */
.custom-button {
outline: none;
}
.custom-button:focus {
/* 默认无轮廓 */
}
.custom-button:focus-visible {
/* 仅键盘聚焦时显示 */
outline: 2px solid #007acc;
outline-offset: 2px;
}
避免焦点陷阱
// 注意:以下代码仅在浏览器环境中运行
// 模态框打开时
// modal.addEventListener('keydown', (e) => {
// if (e.key === 'Tab') {
// const focusable = modal.querySelectorAll('button, a, input');
// const first = focusable[0];
// const last = focusable[focusable.length - 1];
//
// if (e.shiftKey && document.activeElement === first) {
// e.preventDefault();
// last.focus();
// } else if (!e.shiftKey && document.activeElement === last) {
// e.preventDefault();
// first.focus();
// }
// }
// });
✅ 确保模态框内焦点循环,不跳出到背景内容。
11.4 媒体查询与用户偏好
| 媒体查询 | 作用 | 示例 |
|---|---|---|
prefers-reduced-motion | 用户请求减少动画 | 关闭非必要动画 |
prefers-color-scheme | 用户偏好浅色或深色模式 | 切换主题 |
prefers-contrast | 用户需要高对比度 | 增强颜色对比 |
prefers-reduced-transparency | 减少透明效果 | 移除模糊、半透背景 |
代码示例
/* 11.4.1 减少动画 (prefers-reduced-motion) */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* 11.4.2 暗黑/明亮模式 (prefers-color-scheme) */
:root {
--bg-color: white;
--text-color: #333;
--link-color: #007acc;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #121212;
--text-color: #eee;
--link-color: #4ea4f8;
}
}
body {
background: var(--bg-color);
color: var(--text-color);
transition: background 0.3s ease;
}
a { color: var(--link-color); }
/* 11.4.3 高对比度 (prefers-contrast) */
@media (prefers-contrast: high) {
:root {
--border-thick: 3px;
--bg-highlight: black;
--text-highlight: white;
}
.card {
border: var(--border-thick) solid black;
}
.highlight {
background: var(--bg-highlight);
color: var(--text-highlight);
font-weight: bold;
}
}
✅ 尊重用户设置是现代 Web 的基本素养。
11.5 避免仅依赖视觉线索传达信息
| 问题类型 | 仅视觉线索 | 多通道解决方案 |
|---|---|---|
| 必填字段 | 红星 * | 添加 aria-required="true" 和文本”(必填)“ |
| 错误提示 | 红色边框 | 添加 aria-invalid="true"、错误图标、错误文本 |
| 成功状态 | 绿色对勾 | 添加 aria-live="polite" 播报”提交成功” |
| 警告信息 | 黄色背景 | 添加感叹号图标、role="alert" |
| 链接状态 | 下划线 | 添加 aria-current="page" 表示当前页 |
代码示例:表单验证
<label for="email">
邮箱 <span aria-hidden="true">*</span>
<span class="sr-only">(必填)</span>
</label>
<input
type="email"
id="email"
required
aria-describedby="email-error"
>
<div id="email-error" role="alert" aria-live="assertive" style="display:none;">
❌ 请输入有效的邮箱地址
</div>
// JS 验证逻辑
emailInput.addEventListener('invalid', () => {
emailError.style.display = 'block';
emailInput.setAttribute('aria-invalid', 'true');
});
导航当前页指示
<nav>
<a href="/home" aria-current="page">首页</a>
<a href="/about">关于</a>
</nav>
[aria-current="page"] {
font-weight: bold;
text-decoration: underline;
/* 视觉用户可见 */
}
/* 屏幕阅读器会播报"当前页" */
✅ 所有状态信息应通过视觉、听觉、程序化三种方式传达。
第 12 章:浏览器兼容性与开发工具
12.1 主流浏览器差异与兼容性策略
| 浏览器 | 内核 | 市场份额(2025) | 特点 |
|---|---|---|---|
| Chrome | Blink (Chromium) | ~65% | 更新快,支持新特性最早 |
| Edge | Blink (Chromium) | ~10% | 基于 Chromium,兼容性好 |
| Safari | WebKit | ~18% | iOS 唯一内核,更新慢,私有前缀多 |
| Firefox | Gecko | ~5% | 注重隐私与标准,支持良好 |
| 旧版 IE | Trident | <1% | 已淘汰,但遗留系统仍需考虑 |
📌 当前主流:Blink (Chrome/Edge) 和 WebKit (Safari)
兼容性策略
| 策略 | 说明 | 示例 |
|---|---|---|
| 渐进增强 (Progressive Enhancement) | 从基础功能开始,逐步为高级浏览器添加增强特性 | 先实现静态布局,再为支持 Flex 的浏览器使用弹性布局 |
| 优雅降级 (Graceful Degradation) | 为现代浏览器设计,确保旧浏览器仍可使用核心功能 | 使用 Grid 布局,旧浏览器回退到 Float 布局 |
| 特性检测 | 检测浏览器是否支持某特性,而非检测浏览器类型 | 使用 @supports (display: grid) { ... } |
| Polyfill | 用 JS 模拟缺失的 CSS/JS 功能 | flexibility.js 为 IE 支持 Flexbox |
常见兼容性问题与修复
| 问题 | 受影响浏览器 | 解决方案 |
|---|---|---|
| Flexbox 不支持 | IE 10- | 使用 display: -ms-flexbox 或回退布局 |
| Grid 不支持 | IE, 旧版 Safari | 使用 @supports 检测,提供 Float 回退 |
position: sticky | IE, 旧版 Firefox | 使用 JS 模拟或回退为 relative |
:focus-visible | 旧版 Chrome/Firefox | 使用 :focus 作为备选 |
aspect-ratio | Safari < 15 | 使用 padding-bottom 技巧 |
12.2 Can I Use 等兼容性查询工具
| 工具 | 网址 | 功能 | 优势 |
|---|---|---|---|
| Can I use | https://caniuse.com | 查询 CSS/JS 特性在各浏览器的支持情况 | 数据权威,支持筛选地区/版本 |
| MDN Web Docs | https://developer.mozilla.org | 官方文档 + 兼容性表格 | 与规范同步,解释清晰 |
| Browserlist | 配置文件(如 .browserslistrc) | 定义目标浏览器范围,供构建工具使用 | 与 PostCSS/Autoprefixer 集成 |
| Autoprefixer | PostCSS 插件 | 自动添加浏览器前缀 | 基于 Can I Use 数据 |
caniuse.com 使用指南
- 搜索特性:如 css-grid, flexbox, prefers-color-scheme
- 查看支持率:
- ✅ 绿色:完全支持
- 🟡 黄色:部分支持
- ❌ 红色:不支持
- 筛选目标:
- 按”全球”或”中国”用户统计
- 按”最新版本”或”指定版本”
- 查看注意事项:
- 已知 bug
- 前缀需求(如
-webkit-) - 启用标志(需手动开启)
browserslist 配置示例
# .browserslistrc
> 1% # 全球使用率 >1%
last 2 versions # 每个浏览器最近2个版本
not dead # 不支持已停止更新的浏览器
not IE <= 11 # 明确排除 IE 11
// package.json 中
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 11"
]
✅ Autoprefixer 会根据此配置自动添加 -webkit-, -moz- 等前缀。
12.3 CSS 重置 (Reset) 与规范化 (Normalize.css)
| 方案 | 目标 | 代表库 | 特点 |
|---|---|---|---|
| CSS Reset | 移除所有默认样式,从零开始 | Meyer Reset, Eric Meyer’s Reset | 彻底,但需重新定义所有样式 |
| Normalize.css | 统一不同浏览器的默认样式差异 | normalize.css | 保留有用默认值,修复常见 bug |
| Modern Reset | 轻量、现代、基于自定义属性 | modern-css-reset, minireset.css | 仅处理关键差异 |
Normalize.css 核心修复
| 问题 | 修复方式 |
|---|---|
| HTML5 元素样式 | 为 <article>, <section> 等添加默认 display |
| 表单元素一致性 | 统一 <button>, <input> 的字体、边框 |
| 链接颜色 | 保留蓝色,但移除虚线轮廓 |
| pre 和 code | 正确换行与字体 |
| 移动端缩放 | 设置 viewport 提示 |
现代轻量重置示例
/* modern-css-reset 风格 */
* {
box-sizing: border-box;
}
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
#root,
#__next {
isolation: isolate;
}
推荐方案
| 项目类型 | 推荐方案 |
|---|---|
| 新项目 | 使用 modern-css-reset 或自定义轻量重置 |
| 老项目 | 使用 normalize.css 稳定过渡 |
| 极简项目 | 手动重置 margin, padding, box-sizing |
✅ 强烈建议设置 *, *::before, *::after { box-sizing: border-box; }
12.4 浏览器开发者工具 (DevTools) 深度使用
12.4.1 元素检查与样式调试
| 功能 | 操作 | 用途 |
|---|---|---|
| 元素选择 | Ctrl+Shift+C (Win) / Cmd+Shift+C (Mac) | 快速选中页面元素 |
| 样式面板 | 右侧面板查看 Styles | 查看应用的 CSS 规则、特异性、继承 |
| 修改样式 | 直接编辑颜色、尺寸、类名 | 实时调试,无需刷新 |
| 伪类强制 | :hov 按钮强制 :hover, :active 状态 | 调试交互样式 |
| CSS 变量查看 | 在 Computed 面板查看变量值 | 调试主题系统 |
12.4.2 盒模型可视化
| 功能 | 说明 |
|---|---|
| 盒模型图示 | 元素下方显示 margin, border, padding, content 区域 |
| 颜色区分 | 外边距(Margin):橙色 边框(Border):黄色 内边距(Padding):紫色 内容(Content):蓝色 |
| 实时编辑 | 点击数值可直接修改 margin, padding 等 |
✅ 快速诊断布局错位、间距异常问题。
12.4.3 布局分析 (Flex/Grid Overlay)
| 布局类型 | 操作 | 功能 |
|---|---|---|
| Flexbox | 在 Styles 面板点击 Flex 图标 | 显示主轴、交叉轴、对齐方式、项目顺序 |
| Grid | 在 Styles 面板点击 Grid 图标 | 显示网格线、区域、轨道大小,可重命名 |
| 多层叠加 | 可同时开启多个布局分析 | 调试嵌套布局 |
✅ 用于调试 justify-content, align-items, grid-template-areas 等复杂设置。
12.4.4 性能分析
| 面板 | 功能 | 用途 |
|---|---|---|
| Rendering | 开启”Paint flashing”、“Layout shift regions” | 高亮重绘区域,检测布局抖动 |
| Performance | 录制页面交互 | 分析 FPS、CPU 占用、重排重绘耗时 |
| Coverage | Ctrl+Shift+P → “Show Coverage” | 检测未使用的 CSS/JS 代码 |
| Lighthouse | 审计性能、可访问性、SEO | 生成优化建议报告 |
12.4.5 响应式设计测试
| 功能 | 操作 | 优势 |
|---|---|---|
| 设备模式 | Ctrl+Shift+M | 模拟手机、平板等设备 |
| 设备预设 | 下拉选择 iPhone, Pixel, iPad 等 | 快速切换常见分辨率 |
| 自定义尺寸 | 拖拽边框或输入尺寸 | 精确测试断点 |
| 网络 throttling | 限制为 “Slow 3G” | 模拟弱网环境加载 |
| 方向切换 | 横屏/竖屏按钮 | 测试移动端旋转 |
✅ 结合 @media 查询实时调试断点。
第 13 章:现代 CSS 与前沿技术
13.1 容器查询 (@container)
| 概念 | 说明 |
|---|---|
| 媒体查询 (Media Query) | 基于视口(viewport)尺寸变化 |
| 容器查询 (Container Query) | 基于容器元素自身尺寸变化 |
| 核心价值 | 实现”上下文感知”的组件,提升组件复用性 |
使用步骤
- 定义查询容器:使用
container-type指定查询类型 - 命名容器(可选):使用
container-name - 编写查询规则:使用
@container
代码示例
<div class="card-container">
<article class="card">
<img src="image.jpg" alt="Card image" class="card__image">
<div class="card__content">
<h3 class="card__title">标题</h3>
<p class="card__desc">描述文字...</p>
</div>
</article>
</div>
/* 1. 定义容器 */
.card-container {
container-type: inline-size; /* 或 'size' */
container-name: card-wrapper;
width: 50%; /* 容器宽度可变 */
}
/* 2. 使用容器查询 */
@container (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
.card__image {
width: 120px;
flex-shrink: 0;
}
}
@container (max-width: 399px) {
.card {
flex-direction: column;
}
.card__image {
width: 100%;
height: auto;
}
}
✅ 卡片组件在窄容器中堆叠,在宽容器中并排,无需关心页面整体宽度。
多容器查询(命名)
.sidebar {
container-name: sidebar;
container-type: inline-size;
}
.main-content {
container-name: main;
container-type: block-size;
}
/* 同时满足两个容器条件 */
@container sidebar (min-width: 200px) and main (min-height: 500px) {
.widget {
display: grid;
}
}
📌 支持:Chrome 105+, Firefox 110+, Safari 17+
13.2 CSS 嵌套 (Native Nesting)
| 特性 | 原生 CSS 嵌套 | Sass/SCSS 嵌套 |
|---|---|---|
| 编译 | 浏览器原生支持 | 构建时编译为标准 CSS |
| 作用域 | 全局 | 可配合模块化 |
| 父选择器 | & | & |
| 状态组合 | &:hover, &.active | 相同 |
语法规范
/* 基础嵌套 */
.card {
padding: 1rem;
&__title {
font-weight: bold;
&:hover {
color: #007acc;
}
}
&__footer {
border-top: 1px solid #eee;
.btn {
margin-right: 0.5rem;
}
}
}
编译后等效 CSS
.card { padding: 1rem; }
.card__title { font-weight: bold; }
.card__title:hover { color: #007acc; }
.card__footer { border-top: 1px solid #eee; }
.card__footer .btn { margin-right: 0.5rem; }
注意事项
- ❌ 不支持深层嵌套(如
a { b { c { d { ... } } } }易降低性能) - ✅ 推荐嵌套层级 ≤ 3
- ✅ 结合 BEM 命名使用效果更佳
📌 支持:Chrome 119+, Safari 17+, Firefox 正在实现中(可通过 layout.css.nested-boxes.enabled 启用)
13.3 作用域样式 (@scope)
| 概念 | 说明 |
|---|---|
@scope | 将样式规则限制在特定 HTML 范围内 |
| 语法 | @scope (<root>) to (<anchor>) { ... } |
| 用途 | 第三方组件样式隔离、主题区域、避免全局污染 |
基本语法
@scope (.card) {
h2 {
color: #333;
font-size: 1.2rem;
}
p {
line-height: 1.5;
}
}
等效于
.card h2, .card > h2 { color: #333; font-size: 1.2rem; }
.card p, .card > p { line-height: 1.5; }
高级用法:锚点限制 (to)
@scope (.header) to (.footer) {
nav a {
color: white;
background: black;
}
}
仅当 .header 和 .footer 同时存在,且 nav a 在它们之间时才生效。
组件化应用
/* 第三方评论组件样式隔离 */
@scope ([data-widget="comments"]) {
* {
all: initial; /* 重置所有样式 */
font-family: system-ui;
}
ul, ol { margin: 0; padding: 0; list-style: none; }
.comment { border-bottom: 1px solid #eee; padding: 0.5rem 0; }
}
✅ 防止外部样式污染,也防止内部样式泄漏。
📌 状态:实验性功能,Chrome Canary 可通过 flag 启用,尚未广泛支持。
13.4 滚动驱动动画 (Scroll-driven Animations)
| 动画类型 | 触发机制 | API |
|---|---|---|
| 时间动画 | 随时间推移播放 | @keyframes, animation |
| 滚动驱动动画 | 随用户滚动进度播放 | scroll-timeline, animation-timeline |
核心属性
| 属性 | 说明 |
|---|---|
scroll-timeline | 将元素的滚动容器绑定为动画时间轴 |
view-timeline | 将视口或某个元素作为时间轴(推荐) |
animation-timeline | 指定动画使用的时间轴(而非默认时间) |
代码示例:视口时间轴动画
<section class="hero">Hero Section</section>
<section class="animate-in">滚动到我时开始动画</section>
.animate-in {
opacity: 0;
transform: translateY(50px);
animation: fadeSlide 1s linear forwards;
/* 关键:使用视口作为时间轴 */
view-timeline: --slide-in;
}
@keyframes fadeSlide {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
✅ 当 .animate-in 元素进入视口时,动画开始;完全离开时,动画反向播放。
自定义滚动时间轴
.container {
overflow-y: scroll;
scroll-timeline: --scroll-y;
}
.sticky-element {
position: sticky;
top: 0;
animation: parallax 1s linear forwards;
animation-timeline: --scroll-y; /* 使用容器滚动作为时间轴 */
}
实现容器内滚动驱动的视差效果。
📌 支持:Chrome 120+, Safari 17+,Firefox 正在开发
13.5 子网格 (Subgrid)
问题:传统 Grid 嵌套缺陷
| 层级 | 问题 |
|---|---|
| 父网格 | grid-template-columns: 1fr 2fr; |
| 子网格 | 必须重新定义列,无法继承父网格轨道 |
子网格解决方案
.wrapper {
display: grid;
grid-template-columns:
[full-start] 1fr
[main-start] minmax(300px, 800px) [main-end]
1fr
[full-end];
gap: 1rem;
}
.content {
display: grid;
grid-column: main; /* 占据主区域 */
grid-template-rows: auto 1fr auto;
/* 关键:列使用 subgrid 继承父网格 */
grid-template-columns: subgrid;
grid-column: full; /* 横跨整个外层网格 */
}
.sidebar {
grid-column: full-start / main-start;
}
.main {
grid-column: main;
}
.footer {
grid-column: full;
/* 子元素可对齐到外层网格线 */
display: grid;
grid-template-columns: subgrid;
}
<div class="wrapper">
<aside class="sidebar">Sidebar</aside>
<main class="content">
<header>Header</header>
<div>Main Content</div>
<footer class="footer">
<button>Btn 1</button>
<button>Btn 2</button>
</footer>
</main>
</div>
✅ .footer 内的按钮可对齐到 .wrapper 的网格线,实现跨层级设计一致性。
📌 支持:Firefox 71+, Chrome 111+, Safari 17+
13.6 aspect-ratio 属性
| 语法 | 示例 | 说明 |
|---|---|---|
aspect-ratio: <ratio> | 16 / 9, 4 / 3, 1 | 宽高比 |
auto <ratio> | auto 16 / 9 | 优先使用固有比例,否则使用指定比例 |
传统 vs 现代方案
| 方案 | 代码 | 缺点 |
|---|---|---|
| Padding 技巧 | .container { position: relative; padding-top: 56.25%; } | 需要额外包装,难以控制内容 |
| aspect-ratio | .container { aspect-ratio: 16 / 9; } | 简洁直观 |
代码示例
.media-container {
width: 100%;
aspect-ratio: 16 / 9; /* 或 4 / 3, 1 / 1 (正方形) */
background: #000;
overflow: hidden;
}
.media-container img,
.media-container video {
width: 100%;
height: 100%;
object-fit: cover; /* 保持比例填充 */
}
<div class="media-container">
<img src="landscape.jpg" alt="Landscape">
</div>
响应式比例
.image {
width: 100%;
aspect-ratio: 1; /* 默认正方形 */
}
@media (min-aspect-ratio: 16/9) {
.image {
aspect-ratio: 16 / 9;
}
}
📌 支持:Chrome 88+, Firefox 89+, Safari 15.4+, 全面支持
13.7 CSS Houdini (自定义属性、Paint API 等)
| 概念 | 说明 |
|---|---|
| CSS Houdini | 一组底层 API,让开发者”参与”CSS 引擎工作 |
| 目标 | 实现真正的自定义 CSS 功能(如自定义属性、函数、布局) |
13.7.1 CSS 自定义属性(Typed OM)
// 注册强类型自定义属性
CSS.registerProperty({
name: '--accent-color',
syntax: '<color>',
inherits: false,
initialValue: 'blue'
});
CSS.registerProperty({
name: '--rotate-progress',
syntax: '<number>',
inherits: true,
initialValue: 0
});
.spinner {
--rotate-progress: 0; /* 现在是数字类型,可动画 */
animation: spin 2s infinite linear;
}
@keyframes spin {
to {
--rotate-progress: 1; /* 从 0 → 1 */
}
}
.spinner::before {
content: '';
display: block;
width: 40px;
height: 40px;
background: paint(spinnerPainter); /* 使用 Paint API */
}
13.7.2 Paint API(自定义绘制)
// worklet.js
class SpinnerPainter {
static get inputProperties() {
return ['--rotate-progress', '--accent-color'];
}
paint(ctx, geom, properties) {
const progress = properties.get('--rotate-progress').value;
const color = properties.get('--accent-color').value;
const { width, height } = geom;
const radius = Math.min(width, height) / 2 - 10;
ctx.lineWidth = 8;
ctx.strokeStyle = color;
ctx.lineCap = 'round';
// 绘制圆弧
ctx.beginPath();
ctx.arc(
width / 2, height / 2,
radius,
-0.5 * Math.PI,
(progress * 1.8 - 0.5) * Math.PI
);
ctx.stroke();
}
}
registerPaint('spinnerPainter', SpinnerPainter);
<!-- 注意:以下脚本仅在浏览器环境中运行 -->
<!-- <script>
CSS.paintWorklet.addModule('worklet.js');
</script> -->
✅ 实现可动画、高性能的自定义 SVG 级别图形。
Houdini API 概览
| API | 用途 | 状态 |
|---|---|---|
| CSS Properties & Values API | 注册可动画的自定义属性 | 广泛支持 |
| CSS Paint API | 自定义背景、边框绘制 | Chrome/Edge/Safari |
| CSS Layout API | 自定义布局算法(如 masonry) | 实验性 |
| CSS Animation Worklet | 高性能自定义动画 | 实验性 |
📌 Houdini 是未来,但目前主要用于高级优化与创新 UI。
第 14 章:综合实战项目
14.1 响应式企业官网重构
核心技术
- ✅ flexbox 导航栏
- ✅ grid 主内容布局
- ✅
@media响应式断点 - ✅
prefers-color-scheme暗黑模式
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>企业官网</title>
<style>
:root {
--primary: #007acc;
--text: #333;
--bg: white;
--gap: 1rem;
}
@media (prefers-color-scheme: dark) {
:root {
--text: #eee;
--bg: #121212;
}
}
body {
margin: 0;
font-family: system-ui;
background: var(--bg);
color: var(--text);
line-height: 1.6;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
border-bottom: 1px solid #ddd;
}
nav ul {
display: flex;
list-style: none;
gap: var(--gap);
margin: 0;
padding: 0;
}
main {
display: grid;
grid-template-columns: 1fr;
gap: var(--gap);
padding: 1rem;
}
.hero {
text-align: center;
padding: 2rem 0;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--gap);
}
@media (min-width: 768px) {
main {
grid-template-columns: 2fr 1fr;
}
.sidebar {
grid-row: 1;
}
}
</style>
</head>
<body>
<header>
<h1>Company</h1>
<nav>
<ul>
<li><a href="#home">首页</a></li>
<li><a href="#about">关于</a></li>
<li><a href="#contact">联系</a></li>
</ul>
</nav>
</header>
<main>
<div class="content">
<section class="hero">
<h2>欢迎来到我们的网站</h2>
<p>提供优质服务</p>
</section>
<section class="features">
<div class="card"><h3>功能一</h3><p>描述</p></div>
<div class="card"><h3>功能二</h3><p>描述</p></div>
</section>
</div>
<aside class="sidebar">侧边栏</aside>
</main>
</body>
</html>
14.2 个人博客系统 UI 实现
核心技术
- ✅ grid 卡片布局
- ✅
aspect-ratio图片容器 - ✅
:focus-visible键盘友好 - ✅
@container组件响应
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width"/>
<title>个人博客</title>
<style>
* { box-sizing: border-box; }
body {
margin: 0;
font-family: 'Segoe UI', sans-serif;
line-height: 1.6;
padding: 1rem;
max-width: 800px;
margin: 0 auto;
}
.blog-posts {
container-type: inline-size;
display: grid;
gap: 1.5rem;
margin-top: 2rem;
}
@container (min-width: 500px) {
.blog-posts {
grid-template-columns: 1fr 1fr;
}
}
.post {
border: 1px solid #eee;
border-radius: 8px;
overflow: hidden;
}
.post-img {
aspect-ratio: 16 / 9;
background: #f0f0f0;
background-image: linear-gradient(45deg, #ddd 25%, transparent 25%),
linear-gradient(-45deg, #ddd 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #ddd 75%),
linear-gradient(-45deg, transparent 75%, #ddd 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
}
.post-content {
padding: 1rem;
}
a:focus-visible {
outline: 3px solid #007acc;
outline-offset: 2px;
}
</style>
</head>
<body>
<h1>我的博客</h1>
<div class="blog-posts">
<article class="post">
<div class="post-img"></div>
<div class="post-content">
<h3><a href="#">文章标题一</a></h3>
<p>摘要文字...</p>
</div>
</article>
<article class="post">
<div class="post-img"></div>
<div class="post-content">
<h3><a href="#">文章标题二</a></h3>
<p>摘要文字...</p>
</div>
</article>
</div>
</body>
</html>
14.3 数据可视化仪表盘布局
核心技术
- ✅ CSS Grid 复杂布局
- ✅ subgrid 子网格对齐
- ✅ scroll-driven animation 滚动动画
- ✅ 自定义属性控制主题
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width"/>
<title>仪表盘</title>
<style>
:root {
--primary: #4a90e2;
--success: #7ed321;
--danger: #d0021b;
--gap: 1rem;
--header-height: 60px;
}
body {
margin: 0;
font-family: system-ui;
background: #f5f5f5;
}
header {
height: var(--header-height);
background: var(--primary);
color: white;
display: flex;
align-items: center;
padding: 0 1rem;
}
.dashboard {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto 1fr;
gap: var(--gap);
padding: var(--gap);
height: calc(100vh - var(--header-height));
}
.card {
background: white;
border-radius: 8px;
padding: 1rem;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 使用 subgrid 对齐卡片内部网格 */
.grid-4x2 {
display: grid;
grid-template-rows: subgrid;
grid-row: span 2;
}
.stat {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
}
/* 滚动驱动动画 */
.chart {
opacity: 0;
transform: translateY(30px);
animation: slideIn 0.8s ease-out forwards;
animation-timeline: view();
}
@keyframes slideIn {
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
</head>
<body>
<header>数据仪表盘</header>
<div class="dashboard">
<div class="card grid-4x2">关键指标</div>
<div class="card chart">图表 A</div>
<div class="card chart">图表 B</div>
<div class="card">通知</div>
<div class="card stat">
<div>销售额</div>
<div style="color:var(--success)">+12%</div>
</div>
<div class="card stat">
<div>错误率</div>
<div style="color:var(--danger)">-8%</div>
</div>
</div>
</body>
</html>
14.4 可复用 UI 组件库开发 (按钮、卡片、模态框等)
核心技术
- ✅ CSS 变量主题化
- ✅
:focus-visible键盘导航 - ✅
role语义化 - ✅ BEM 命名规范
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>UI 组件库</title>
<style>
:root {
--btn-primary-bg: #007acc;
--btn-primary-hover: #005a99;
--btn-danger-bg: #d32f2f;
--border-radius: 4px;
--gap: 0.5rem;
}
.btn {
display: inline-flex;
align-items: center;
gap: var(--gap);
padding: 0.5rem 1rem;
border: none;
border-radius: var(--border-radius);
background: #f0f0f0;
color: #333;
font: inherit;
cursor: pointer;
transition: background 0.2s;
}
.btn:focus-visible {
outline: 2px solid #007acc;
outline-offset: 2px;
}
.btn--primary {
background: var(--btn-primary-bg);
color: white;
}
.btn--primary:hover {
background: var(--btn-primary-hover);
}
.btn--danger {
background: var(--btn-danger-bg);
color: white;
}
.card {
border: 1px solid #ddd;
border-radius: var(--border-radius);
padding: 1rem;
margin: 1rem 0;
}
.modal {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
.modal__content {
background: white;
padding: 1.5rem;
border-radius: 8px;
max-width: 500px;
width: 100%;
}
</style>
</head>
<body>
<!-- 按钮 -->
<button class="btn btn--primary">主按钮</button>
<button class="btn btn--danger">危险按钮</button>
<!-- 卡片 -->
<div class="card">
<h3>卡片标题</h3>
<p>卡片内容...</p>
</div>
<!-- 模态框 -->
<div class="modal" role="dialog" aria-labelledby="modal-title">
<div class="modal__content">
<h2 id="modal-title">模态框</h2>
<p>这是模态框内容</p>
<button class="btn" onclick="this.parentElement.parentElement.remove()">关闭</button>
</div>
</div>
</body>
</html>
14.5 模仿 Dribbble 设计稿实现
核心技术
- ✅
clip-path创意形状 - ✅
backdrop-filter毛玻璃 - ✅
scroll-snap滑动体验 - ✅
hsl()动态颜色
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width"/>
<title>Dribbble 风格</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #fbc2eb 0%, #a6c1ee 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.hero {
width: 90%;
max-width: 400px;
aspect-ratio: 3 / 4;
background: url('https://picsum.photos/400/533') center/cover;
border-radius: 30px;
position: relative;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.hero::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(to top,
hsl(200, 50%, 20%) 30%,
transparent 80%
);
}
.hero-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 1.5rem;
color: white;
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
}
.tag {
display: inline-block;
padding: 0.3rem 0.8rem;
background: rgba(255,255,255,0.2);
border-radius: 20px;
font-size: 0.8rem;
margin-right: 0.5rem;
}
.cta {
margin-top: 1rem;
display: flex;
gap: 1rem;
}
.btn-round {
width: 40px;
height: 40px;
border-radius: 50%;
background: white;
color: #333;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
clip-path: polygon(40% 0%, 70% 50%, 40% 100%, 0% 75%, 0% 25%);
}
</style>
</head>
<body>
<div class="hero">
<div class="hero-content">
<div>
<span class="tag">设计</span>
<span class="tag">灵感</span>
</div>
<h2>创意无限</h2>
<p>探索前沿视觉设计趋势</p>
<div class="cta">
<button class="btn-round">→</button>
<span>了解更多</span>
</div>
</div>
</div>
</body>
</html>
附录
A. CSS 属性速查表
一、布局(Layout)
| 属性 | 值示例 | 说明 |
|---|---|---|
display | flex, grid, block, inline-block, none | 设置元素显示模式 |
position | static, relative, absolute, fixed, sticky | 定位方式 |
float | left, right, none | 浮动(已不推荐用于布局) |
clear | both, left, right | 清除浮动 |
z-index | 1, auto, -1 | 层叠顺序(需配合定位使用) |
Flexbox
属性(容器)
| 属性 | 值示例 | 说明 |
|---|---|---|
flex-direction | row, column, row-reverse | 主轴方向 |
justify-content | center, space-between, flex-start | 主轴对齐 |
align-items | center, flex-start, stretch | 交叉轴对齐 |
flex-wrap | nowrap, wrap, wrap-reverse | 是否换行 |
属性(项目)
| 属性 | 值示例 | 说明 |
|---|---|---|
flex | 1, 0 1 auto, 2 1 100px | 缩写:flex-grow flex-shrink flex-basis |
align-self | center, flex-end | 单个项目对齐 |
order | 1, -1 | 排序(可改变视觉顺序) |
Grid
属性(容器)
| 属性 | 值示例 | 说明 |
|---|---|---|
grid-template-columns | 1fr 2fr, repeat(3, 1fr) | 列定义 |
grid-template-rows | 100px auto, minmax(100px, 1fr) | 行定义 |
gap | 1rem, 10px 20px | 网格间距(行与列) |
grid-auto-flow | row, column, dense | 自动放置算法 |
justify-items | start, center, stretch | 内容在单元格中水平对齐 |
align-items | start, center, stretch | 内容在单元格中垂直对齐 |
属性(项目)
| 属性 | 值示例 | 说明 |
|---|---|---|
grid-column | 1 / 3, span 2 | 跨列 |
grid-row | 2 / 4 | 跨行 |
grid-area | header, 1 / 1 / 3 / 2 | 区域名称或位置 |
justify-self | center, end | 单个项目水平对齐 |
align-self | center, start | 单个项目垂直对齐 |
二、盒模型(Box Model)
| 属性 | 值示例 | 说明 |
|---|---|---|
width / height | 200px, 50%, fit-content, max-content | 尺寸 |
max-width / max-height | 800px, none | 最大尺寸 |
min-width / min-height | 300px | 最小尺寸 |
margin | 10px, auto, 1rem 0 | 外边距(可设 auto 实现居中) |
padding | 20px, 1rem 2rem | 内边距 |
border | 1px solid #ccc, 2px dashed red | 边框 |
border-radius | 8px, 50%, 10px 20px 30px 40px | 圆角 |
box-sizing | content-box, border-box | 盒模型计算方式(推荐全局设为 border-box) |
overflow | visible, hidden, scroll, auto | 溢出处理 |
三、文本与字体(Text & Font)
| 属性 | 值示例 | 说明 |
|---|---|---|
font-family | 'Arial', 'Segoe UI', system-ui | 字体族 |
font-size | 16px, 1rem, 1.2em | 字号(推荐使用 rem) |
font-weight | 400, 700, bold | 字重 |
font-style | normal, italic | 字体样式 |
line-height | 1.5, 1.2, 24px | 行高(推荐无单位) |
text-align | left, center, right, justify | 文本对齐 |
text-transform | uppercase, lowercase, capitalize | 文本转换 |
text-decoration | none, underline, line-through | 文本装饰 |
white-space | normal, nowrap, pre-line, pre-wrap | 空白处理 |
word-break | break-all, keep-all | 换行策略 |
color | #333, rgb(255,0,0), hsl(120, 100%, 50%), var(--primary) | 文本颜色 |
四、背景与边框(Background & Border)
| 属性 | 值示例 | 说明 |
|---|---|---|
background-color | #f0f0f0, transparent | 背景颜色 |
background-image | url('bg.jpg'), linear-gradient(...) | 背景图像 |
background-repeat | no-repeat, repeat-x | 重复方式 |
background-position | center, top right, 50% 50% | 位置 |
background-size | cover, contain, 100% 100% | 尺寸 |
background-attachment | scroll, fixed | 滚动行为 |
border-image | url(border.png) 30 stretch | 图像边框 |
box-shadow | 0 2px 4px rgba(0,0,0,0.1) | 盒阴影(可多重) |
clip-path | circle(50%), polygon(0 0, 100% 0, 50% 100%) | 裁剪路径(创意形状) |
backdrop-filter | blur(10px), brightness(70%) | 背后滤镜(毛玻璃效果) |
五、变换、过渡与动画(Transform, Transition, Animation)
| 属性 | 值示例 | 说明 |
|---|---|---|
transform | translate(10px, 20px), rotate(45deg), scale(1.2) | 2D/3D 变换 |
transform-origin | center, top left | 变换原点 |
transition | all 0.3s ease, opacity 0.2s | 过渡效果(缩写) |
transition-property | color, background | 过渡属性 |
transition-duration | 0.5s, 300ms | 持续时间 |
transition-timing-function | ease, linear, cubic-bezier(.42,-0.61,.58,1.4) | 缓动函数 |
animation | fade 1s infinite ease-in-out | 动画缩写 |
@keyframes | from { opacity: 0; } to { opacity: 1; } | 定义关键帧动画 |
六、响应式与媒体查询
| 属性/规则 | 示例 | 说明 |
|---|---|---|
@media | @media (min-width: 768px) { ... } | 媒体查询 |
| 常用断点 | 576px, 768px, 992px, 1200px | 移动优先 |
orientation | (orientation: portrait) | 设备方向 |
prefers-color-scheme | (prefers-color-scheme: dark) | 暗黑模式检测 |
aspect-ratio | @media (min-aspect-ratio: 16/9) | 宽高比查询 |
container-type | inline-size, size | 启用容器查询 |
@container | @container (min-width: 300px) { ... } | 容器查询规则 |
七、其他实用属性
| 属性 | 值示例 | 说明 |
|---|---|---|
cursor | pointer, move, not-allowed | 鼠标指针样式 |
visibility | visible, hidden | 是否可见(保留空间) |
opacity | 0.5, 1 | 透明度(0 = 完全透明) |
filter | blur(5px), grayscale(100%), drop-shadow() | 图像滤镜 |
pointer-events | auto, none | 是否响应鼠标事件(常用于穿透点击) |
user-select | none, text | 是否允许用户选中文本 |
scroll-behavior | smooth | 平滑滚动(设于 html) |
scroll-margin / scroll-padding | 10px | 锚点滚动偏移 |
isolation | isolate | 创建层叠上下文(替代 opacity: 0.99 黑科技) |
contain | layout, paint, strict | 提升性能(限制重排重绘范围) |
八、CSS 自定义属性(变量)
:root {
--primary-color: #007acc;
--spacing: 1rem;
--border-radius: 4px;
}
.component {
color: var(--primary-color);
padding: var(--spacing);
border-radius: var(--border-radius);
}
✅ 使用 var(--name, fallback) 提供默认值
九、无障碍(Accessibility)基础
| 属性 | 说明 |
|---|---|
:focus-visible | 仅在键盘聚焦时显示轮廓 |
outline | none(慎用!应替换为自定义焦点样式) |
aria-* | aria-label, aria-hidden 等辅助技术属性 |
role | button, dialog, navigation 等语义角色 |
十、推荐全局重置
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
B. 选择器优先级计算表
一、优先级计算模型:a-b-c-d 四元组
| 位数 | 含义 | 可用选择器类型 | 计分方式 |
|---|---|---|---|
| a | !important | 唯一来源:!important 声明 | 每出现一次 !important(且在声明末尾),a = 1,否则 a = 0 |
| b | ID 选择器 | #header, #nav | 每个 ID 选择器 +1 |
| c | 类/属性/伪类 | .btn, [type="text"], :hover, :nth-child(2) | 每个此类选择器 +1 |
| d | 元素/伪元素 | div, p, ::before, ::first-line | 每个元素或伪元素 +1 |
📌 比较规则:从左到右逐位比较(如 0-1-0-0 > 0-0-99-99)
二、优先级计算速查表(示例)
| CSS 选择器 | a (important) | b (ID) | c (类/属性/伪类) | d (元素/伪元素) | 优先级值 |
|---|---|---|---|---|---|
p | 0 | 0 | 0 | 1 | 0-0-0-1 |
.intro | 0 | 0 | 1 | 0 | 0-0-1-0 |
p.intro | 0 | 0 | 1 | 1 | 0-0-1-1 |
#main | 0 | 1 | 0 | 0 | 0-1-0-0 |
div#content p.highlight | 0 | 1 | 1 | 2 | 0-1-1-2 |
[href] | 0 | 0 | 1 | 0 | 0-0-1-0 |
:hover | 0 | 0 | 1 | 0 | 0-0-1-0 |
:nth-child(odd) | 0 | 0 | 1 | 0 | 0-0-1-0 |
::before | 0 | 0 | 0 | 1 | 0-0-0-1 |
.nav li.active:hover | 0 | 0 | 3 | 1 | 0-0-3-1 |
#sidebar .widget:nth-of-type(2) | 0 | 1 | 2 | 0 | 0-1-2-0 |
body #app .btn[disabled]:focus | 0 | 1 | 3 | 1 | 0-1-3-1 |
*(通配符) | 0 | 0 | 0 | 0 | 0-0-0-0 |
div * | 0 | 0 | 0 | 1 | 0-0-0-1 |
a:hover::after | 0 | 0 | 1 | 2 | 0-0-1-2 |
三、!important 的特殊处理
| 声明 | 是否计入 a | 说明 |
|---|---|---|
color: red !important; | ✅ 是 | a = 1 |
color: red!important; | ✅ 是 | 空格可省略 |
color: red ; important | ❌ 否 | 语法错误,不生效 |
| !important 在变量中? | ❌ 否 | --color: red !important; 不合法 |
⚠️ 注意:
- !important 打破正常优先级规则,仅被更高优先级的 !important 覆盖
- 内联样式中的 !important 仍计入 a
- 建议:仅用于调试或第三方库覆盖,避免滥用
四、特殊选择器优先级说明
| 选择器 | 优先级 | 说明 |
|---|---|---|
:where() | 0-0-0-0 | 零优先级,用于重置优先级 |
:is() | 正常计算 | 取括号内最高优先级 |
:not() | 正常计算 | 包含的选择器参与计分 |
:has() | 正常计算 | 支持较新(Chrome 105+) |
内联样式 style="" | 0-1-0-0 | 相当于一个 ID(但无 ID 语义) |
@layer | 分层控制 | 层次顺序 > 优先级 > 源码顺序 |
五、实战计算练习
示例 1:谁的字体颜色生效?
/* A */
#main .text {
color: blue;
}
/* B */
div.container p.text {
color: red;
}
| 选择器 | b | c | d | 优先级 |
|---|---|---|---|---|
#main .text | 1 | 1 | 0 | 0-1-1-0 |
div.container p.text | 0 | 2 | 2 | 0-0-2-2 |
✅ 结果:blue 生效(0-1-1-0 > 0-0-2-2)
示例 2::is() 与 :where()
:is(#nav, .sidebar) p {
color: green;
}
.sidebar p {
color: yellow;
}
:is(#nav, .sidebar)的优先级 = 0-1-0-0(取 #nav 的高优先级).sidebar p= 0-0-1-1- ✅ green 生效
:where(#nav, .sidebar) p {
color: purple;
}
:where(...)优先级 = 0-0-0-0- ✅ purple 不会生效(低于
.sidebar p)
六、优先级避坑指南
| 陷阱 | 解决方案 |
|---|---|
| 过度使用 !important | 使用更具体的选择器替代 |
| ID 选择器滥用 | 改用类名(.header 替代 #header) |
| 层层嵌套提升优先级 | 使用 BEM 命名,避免深层嵌套 |
| 第三方样式冲突 | 使用 :where() 或 @layer 隔离 |
| 通配符重置影响布局 | 使用 *, *::before, *::after { box-sizing: border-box; } 安全重置 |
七、推荐开发策略
- 优先级排序:
!important> 内联样式 > ID > 类/属性/伪类 > 元素 > 通配符 - 设计系统建议:
- 全局使用 class,避免 ID 选择器
- 使用 BEM 命名法(如
.btn__icon--large)提升可读性 - 利用 CSS Custom Properties 实现主题切换
- 使用
@layer组织样式层级(基础 → 组件 → 主题)
- 调试技巧:
- 浏览器 DevTools 中查看”Computed”面板,观察样式来源
- 使用 specificity calculator 在线工具验证
📌 总结口诀:
四个数字比大小,从左到右不能跳。 ID 最狠值一分,类属伪类紧相随。 标签伪元排最后,通配清零全靠它。 !important 插队王,能破天规但别狂。
C. 常用媒体查询断点参考
一、通用响应式断点(推荐)
| 设备类型 | 最小宽度 (min-width) | 最大宽度 (max-width) | CSS 示例 |
|---|---|---|---|
| 手机(竖屏) | - | 575px | @media (max-width: 575px) |
| 手机(横屏)/ 小平板 | 576px | 767px | @media (min-width: 576px) |
| 平板(竖屏) | 768px | 991px | @media (min-width: 768px) |
| 桌面(小屏) | 992px | 1199px | @media (min-width: 992px) |
| 桌面(大屏) | 1200px | - | @media (min-width: 1200px) |
✅ 此方案与 Bootstrap 5 断点一致,广泛采用。
二、断点代码模板(移动优先)
/* 1. 默认样式(手机竖屏) */
.container {
padding: 1rem;
font-size: 16px;
}
/* 2. 小平板 / 手机横屏 */
@media (min-width: 576px) {
.container {
max-width: 540px;
margin: 0 auto;
}
}
/* 3. 平板(竖屏) */
@media (min-width: 768px) {
.container {
max-width: 720px;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
}
/* 4. 桌面(小屏) */
@media (min-width: 992px) {
.container {
max-width: 960px;
}
.grid {
grid-template-columns: 1fr 1fr 1fr;
}
}
/* 5. 桌面(大屏) */
@media (min-width: 1200px) {
.container {
max-width: 1140px;
}
.hero-text {
font-size: 2rem;
}
}
三、常见框架断点对比
| 框架 | 超小 (xs) | 小 (sm) | 中 (md) | 大 (lg) | 超大 (xl) | 说明 |
|---|---|---|---|---|---|---|
| Bootstrap 5 | <576px | >=576px | >=768px | >=992px | >=1200px | 最广泛使用 |
| Tailwind CSS | sm:640px | md:768px | lg:1024px | xl:1280px | 2xl:1536px | 略有偏移 |
| Material Design | <600px | >=600px | >=960px | >=1280px | >=1920px | Google 设计规范 |
| 自定义常用 | <768px | >=768px | >=1024px | >=1200px | >=1440px | 简化版,适合内容站 |
📊 建议:初学者可直接采用 Bootstrap 5 断点,兼容性好,社区资源丰富。
四、方向(Orientation)媒体查询
/* 竖屏(Portrait) */
@media (orientation: portrait) {
.hero {
height: 80vh;
}
}
/* 横屏(Landscape) */
@media (orientation: landscape) {
.hero {
height: 50vh;
}
}
📱 适用于移动端,控制不同方向的布局表现。
五、高分辨率与暗黑模式
/* 高分辨率屏幕(Retina) */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.logo {
background-image: url('logo@2x.png');
}
}
/* 暗黑模式 */
@media (prefers-color-scheme: dark) {
body {
background: #121212;
color: #eee;
}
}
/* 打印样式 */
@media print {
.no-print {
display: none;
}
body {
font-size: 12pt;
}
}
六、容器查询(Container Queries)——未来趋势
✅ 适用于组件级响应式,不依赖视口
.widget {
container-type: inline-size;
container-name: sidebar;
}
/* 当容器宽度 ≥ 300px 时 */
@container sidebar (min-width: 300px) {
.widget {
display: flex;
gap: 1rem;
}
}
⚠️ 注意:需检查浏览器支持(Chrome 105+,Firefox 110+)
七、断点设置最佳实践
| 建议 | 说明 |
|---|---|
| ✅ 使用 min-width | 移动优先,避免样式覆盖混乱 |
| ✅ 用 rem 定义断点 | 如 (min-width: 48rem),与字体大小联动,更灵活 |
| ❌ 避免 device-width | 如 device-width: 375px,已被弃用,不可靠 |
| ✅ 基于内容设置断点 | 在浏览器中缩放页面,观察布局何时”断裂”,在此处加断点 |
| ✅ 命名断点变量 | 提升可维护性 |
/* 推荐:使用 CSS 变量命名断点 */
:root {
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
}
@media (min-width: var(--breakpoint-md)) {
/* 平板以上样式 */
}
八、常见设备分辨率参考
| 设备 | 典型分辨率 | 适用断点 |
|---|---|---|
| iPhone SE | 375 × 667 | max-width: 575px |
| iPhone 14 | 393 × 852 | max-width: 575px |
| iPad (竖屏) | 768 × 1024 | min-width: 768px |
| iPad Pro (横屏) | 1024 × 1366 | min-width: 992px |
| 普通笔记本 | 1366 × 768 | min-width: 992px |
| 2K / 4K 显示器 | 2560×1440 / 3840×2160 | min-width: 1200px |
🔍 注意:CSS 像素 ≠ 物理像素(Retina 屏幕有缩放)
📌 总结:
“没有最好的断点,只有最适合你设计的断点。” 从 移动优先 开始, 用 内容断裂点 定义响应, 借助 主流断点参考 快速起步, 最终实现真正自适应的用户体验。
✅ 将此表作为项目模板,快速构建响应式布局!