> ## Content Index
> Fetch the complete content index at: https://blog.vercanti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# HTML 与 CSS 入门
- URL: https://blog.vercanti.com/html-yu-css-ru-men/
- Published: 2026-08-28T14:35:14.000Z
- Updated: 2026-08-28T14:58:23.000Z
- Description: 相关文档：JavaScript入门(/javascript-ru-men/) Vue3入门(/vue-3-ru-men-zhi-nan/) 1. HTML 是什么(#html-%E6%98%AF%E4%BB%80%E4%B9%88) 2. 网页的基本结构(#%E7%BD%91%E9%A1%B5%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84) 3. 常用 HTML 标签(#%E5%B8%B8%E7%94%A8-html-%E6%A0%87%E7%AD%BE) 4. HTML 属性(#html-%E5%B1%9E%
- Author: yellowdog
- Tags: 前端开发

> 官方文档：<https://developer.mozilla.org/zh-CN/docs/Web/HTML> | <https://developer.mozilla.org/zh-CN/docs/Web/CSS>  
> 最后更新：2026-03-05

相关文档：[JavaScript入门](https://blog.vercanti.com/javascript-ru-men/) [Vue3入门](https://blog.vercanti.com/vue-3-ru-men-zhi-nan/)

---

## 目录

1. [HTML 是什么](#html-%E6%98%AF%E4%BB%80%E4%B9%88)
2. [网页的基本结构](#%E7%BD%91%E9%A1%B5%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84)
3. [常用 HTML 标签](#%E5%B8%B8%E7%94%A8-html-%E6%A0%87%E7%AD%BE)
4. [HTML 属性](#html-%E5%B1%9E%E6%80%A7)
5. [路径：相对路径与绝对路径](#%E8%B7%AF%E5%BE%84%EF%BC%9A%E7%9B%B8%E5%AF%B9%E8%B7%AF%E5%BE%84%E4%B8%8E%E7%BB%9D%E5%AF%B9%E8%B7%AF%E5%BE%84)
6. [表单完整示例](#%E8%A1%A8%E5%8D%95%E5%AE%8C%E6%95%B4%E7%A4%BA%E4%BE%8B)
7. [CSS 是什么](#css-%E6%98%AF%E4%BB%80%E4%B9%88)
8. [CSS 三种引入方式](#css-%E4%B8%89%E7%A7%8D%E5%BC%95%E5%85%A5%E6%96%B9%E5%BC%8F)
9. [CSS 选择器](#css-%E9%80%89%E6%8B%A9%E5%99%A8)
10. [盒模型](#%E7%9B%92%E6%A8%A1%E5%9E%8B)
11. [常用 CSS 属性](#%E5%B8%B8%E7%94%A8-css-%E5%B1%9E%E6%80%A7)
12. [display 属性](#display-%E5%B1%9E%E6%80%A7)
13. [Flexbox 弹性布局](#flexbox-%E5%BC%B9%E6%80%A7%E5%B8%83%E5%B1%80)
14. [Grid 网格布局](#grid-%E7%BD%91%E6%A0%BC%E5%B8%83%E5%B1%80)
15. [Position 定位](#position-%E5%AE%9A%E4%BD%8D)
16. [响应式设计](#%E5%93%8D%E5%BA%94%E5%BC%8F%E8%AE%BE%E8%AE%A1)
17. [过渡与动画](#%E8%BF%87%E6%B8%A1%E4%B8%8E%E5%8A%A8%E7%94%BB)
18. [CSS 变量](#css-%E5%8F%98%E9%87%8F)
19. [综合实战：响应式个人主页](#%E7%BB%BC%E5%90%88%E5%AE%9E%E6%88%98%EF%BC%9A%E5%93%8D%E5%BA%94%E5%BC%8F%E4%B8%AA%E4%BA%BA%E4%B8%BB%E9%A1%B5)
20. [注意事项与常见错误](#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%E4%B8%8E%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF)

---

## HTML 是什么

HTML（HyperText Markup Language，超文本标记语言）是构建网页的基础语言。它不是编程语言，而是一种**标记语言**，通过标签（Tag）来描述网页的内容结构。

你可以把网页理解为一栋房子：

- HTML 是房子的骨架和墙体（结构）
- CSS 是房子的装修和外观（样式）
- JavaScript 是房子里的电器和功能（交互）

本文只讲 HTML 和 CSS。

---

## 网页的基本结构

每个 HTML 文件都遵循固定的基本结构。用文本编辑器（如 VS Code）新建一个 `index.html` 文件，写入以下内容：

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>我的第一个网页</title>
  </head>
  <body>
    <h1>你好，世界！</h1>
    <p>这是我的第一个网页。</p>
  </body>
</html>

```

各部分说明：

| 标签 / 声明                    | 作用                       |
| -------------------------- | ------------------------ |
|                            | 声明文档类型为 HTML5，必须写在第一行    |
| <html lang="zh-CN">        | 根标签，包裹整个页面；lang 属性声明页面语言 |
| <head>                     | 头部区域，存放不显示在页面上的元信息       |
| <meta charset="UTF-8">     | 声明字符编码为 UTF-8，防止中文乱码     |
| <meta name="viewport" ...> | 适配移动端屏幕，响应式设计必备          |
| <title>                    | 浏览器标签页上显示的标题             |
| <body>                     | 页面可见内容都写在这里              |

双击 `index.html` 文件，浏览器会直接打开并渲染出网页。

---

## 常用 HTML 标签

### 标题标签 h1 - h6

HTML 提供六级标题，h1 最大，h6 最小。每个页面通常只有一个 h1。

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>标题示例</title>
  </head>
  <body>
    <h1>一级标题（最重要）</h1>
    <h2>二级标题</h2>
    <h3>三级标题</h3>
    <h4>四级标题</h4>
    <h5>五级标题</h5>
    <h6>六级标题（最小）</h6>
  </body>
</html>

```

### 段落标签 p

`<p>` 标签表示一段文字。浏览器会在段落前后自动添加间距。

```html
<p>这是第一段文字。HTML 中的换行在源代码里不起作用，</p>
<p>浏览器会把多个空格和换行都压缩成一个空格。</p>

<!-- 如果要强制换行，使用 <br> 标签 -->
<p>第一行文字<br />第二行文字（br 是自闭合标签）</p>

```

### 链接标签 a

`<a>` 标签创建超链接，点击后跳转到指定地址。

```html
<!-- 跳转到外部网站，target="_blank" 表示在新标签页打开 -->
<a href="https://www.baidu.com" target="_blank">打开百度</a>

<!-- 跳转到同一网站的另一个页面（相对路径） -->
<a href="about.html">关于我们</a>

<!-- 跳转到页面内的某个位置（锚点跳转） -->
<a href="#section-2">跳转到第二节</a>

<!-- 发送邮件 -->
<a href="mailto:example@example.com">联系我</a>

<!-- 拨打电话（手机端） -->
<a href="tel:+8613800138000">拨打电话</a>

```

### 图片标签 img

`<img>` 是自闭合标签，用于显示图片。

```html
<!-- src 是图片地址，alt 是图片无法显示时的替代文字（必须写） -->
<img src="photo.jpg" alt="一张风景照" />

<!-- 设置宽高（推荐只设置其中一个，让另一个自动等比缩放） -->
<img src="logo.png" alt="网站标志" width="200" />

<!-- 使用网络图片 -->
<img src="https://via.placeholder.com/300x200" alt="占位图片" />

```

### 列表标签

**无序列表**（ul + li）：列表项前显示圆点。

```html
<ul>
  <li>苹果</li>
  <li>香蕉</li>
  <li>橙子</li>
</ul>

```

**有序列表**（ol + li）：列表项前显示数字。

```html
<ol>
  <li>第一步：打开冰箱</li>
  <li>第二步：把大象放进去</li>
  <li>第三步：关上冰箱</li>
</ol>

```

**列表嵌套**：

```html
<ul>
  <li>水果
    <ul>
      <li>苹果</li>
      <li>香蕉</li>
    </ul>
  </li>
  <li>蔬菜
    <ul>
      <li>白菜</li>
      <li>萝卜</li>
    </ul>
  </li>
</ul>

```

### 表格标签

```html
<table border="1">
  <!-- 表格标题（可选） -->
  <caption>学生成绩表</caption>

  <!-- 表头区域 -->
  <thead>
    <tr>
      <!-- th 是表头单元格，默认加粗居中 -->
      <th>姓名</th>
      <th>语文</th>
      <th>数学</th>
      <th>英语</th>
    </tr>
  </thead>

  <!-- 表体区域 -->
  <tbody>
    <tr>
      <!-- td 是普通单元格 -->
      <td>张三</td>
      <td>90</td>
      <td>85</td>
      <td>92</td>
    </tr>
    <tr>
      <td>李四</td>
      <td>78</td>
      <td>95</td>
      <td>88</td>
    </tr>
  </tbody>

  <!-- 表脚区域（可选） -->
  <tfoot>
    <tr>
      <td>平均分</td>
      <td>84</td>
      <td>90</td>
      <td>90</td>
    </tr>
  </tfoot>
</table>

```

单元格合并：

```html
<table border="1">
  <tr>
    <!-- colspan 跨列合并（横向合并） -->
    <td colspan="2">合并了两列</td>
    <td>正常单元格</td>
  </tr>
  <tr>
    <!-- rowspan 跨行合并（纵向合并） -->
    <td rowspan="2">合并了两行</td>
    <td>第二行第二列</td>
    <td>第二行第三列</td>
  </tr>
  <tr>
    <td>第三行第二列</td>
    <td>第三行第三列</td>
  </tr>
</table>

```

### 表单标签

表单用于收集用户输入的数据。详细示例见[表单完整示例](#%E8%A1%A8%E5%8D%95%E5%AE%8C%E6%95%B4%E7%A4%BA%E4%BE%8B)。

```html
<!-- action 是提交数据的地址，method 是提交方式 -->
<form action="/submit" method="post">

  <!-- 单行文本输入 -->
  <input type="text" name="username" placeholder="请输入用户名" />

  <!-- 密码输入（内容显示为圆点） -->
  <input type="password" name="password" placeholder="请输入密码" />

  <!-- 邮箱输入（会验证格式） -->
  <input type="email" name="email" placeholder="请输入邮箱" />

  <!-- 数字输入 -->
  <input type="number" name="age" min="1" max="120" />

  <!-- 单选框（name 相同的单选框为一组，只能选一个） -->
  <input type="radio" name="gender" value="male" /> 男
  <input type="radio" name="gender" value="female" /> 女

  <!-- 复选框 -->
  <input type="checkbox" name="hobby" value="reading" /> 阅读
  <input type="checkbox" name="hobby" value="coding" /> 编程

  <!-- 下拉选择框 -->
  <select name="city">
    <option value="">请选择城市</option>
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
    <option value="guangzhou">广州</option>
  </select>

  <!-- 多行文本框 -->
  <textarea name="message" rows="4" cols="40" placeholder="请输入留言"></textarea>

  <!-- 提交按钮 -->
  <button type="submit">提交</button>

  <!-- 重置按钮（清空表单） -->
  <button type="reset">重置</button>

</form>

```

### 语义化标签

语义化标签让代码的含义更清晰，对搜索引擎和屏幕阅读器（辅助视障用户）友好。

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>语义化布局示例</title>
  </head>
  <body>

    <!-- 页头，通常包含网站标志和导航 -->
    <header>
      <h1>网站名称</h1>

      <!-- 导航栏 -->
      <nav>
        <ul>
          <li><a href="/">首页</a></li>
          <li><a href="/about">关于</a></li>
          <li><a href="/contact">联系</a></li>
        </ul>
      </nav>
    </header>

    <!-- 页面主体内容，每个页面只有一个 main -->
    <main>

      <!-- 独立的内容区块 -->
      <section>
        <h2>最新文章</h2>

        <!-- 一篇独立的文章或内容块 -->
        <article>
          <h3>文章标题一</h3>
          <p>文章摘要内容……</p>
        </article>

        <article>
          <h3>文章标题二</h3>
          <p>文章摘要内容……</p>
        </article>
      </section>

      <section>
        <h2>关于我们</h2>
        <p>这里是关于我们的介绍。</p>
      </section>

    </main>

    <!-- 侧边栏 -->
    <aside>
      <h2>相关推荐</h2>
      <ul>
        <li><a href="#">推荐文章一</a></li>
        <li><a href="#">推荐文章二</a></li>
      </ul>
    </aside>

    <!-- 页脚 -->
    <footer>
      <p>版权所有 2026 网站名称</p>
    </footer>

  </body>
</html>

```

### div 和 span

`<div>` 和 `<span>` 是没有语义的通用容器，用于组合元素、方便 CSS 样式控制。

- `<div>`：块级元素，独占一行，用于大块区域划分
- `<span>`：行内元素，不换行，用于标记一行文字中的某个部分

```html
<!-- div 用于划分区块 -->
<div class="card">
  <div class="card-header">
    <h3>卡片标题</h3>
  </div>
  <div class="card-body">
    <p>卡片内容，这段文字中有<span class="highlight">一个重要词语</span>需要标红。</p>
  </div>
</div>

```

---

## HTML 属性

属性写在开标签内，格式为 `属性名="属性值"`。

| 属性          | 适用标签                | 说明                                                 |
| ----------- | ------------------- | -------------------------------------------------- |
| id          | 所有标签                | 唯一标识符，同一页面中不能重复                                    |
| class       | 所有标签                | 类名，同一个类可以用于多个元素，CSS 通过类名来设置样式                      |
| style       | 所有标签                | 内联样式，直接在标签上写 CSS（不推荐大量使用）                          |
| href        | <a>                 | 链接目标地址                                             |
| src         | <img>, <script>     | 资源文件地址                                             |
| alt         | <img>               | 图片无法显示时的替代文字                                       |
| placeholder | <input>, <textarea> | 输入框为空时显示的提示文字                                      |
| disabled    | 表单元素                | 禁用该元素，用户无法操作                                       |
| required    | 表单元素                | 标记为必填项，提交时若为空会阻止提交                                 |
| name        | 表单元素                | 提交表单时该字段的键名                                        |
| value       | 表单元素                | 表单元素的值                                             |
| type        | <input>             | 输入框类型（text/password/email/number/radio/checkbox 等） |
| target      | <a>                 | 链接打开方式（\_blank 新标签页，\_self 当前页）                    |

```html
<!-- id 和 class 的使用 -->
<div id="main-header" class="header large-header">
  <p class="intro-text">欢迎来到我的网站</p>
</div>

<!-- disabled 和 required -->
<form>
  <input type="text" name="username" required placeholder="必填项" />
  <input type="text" name="referral" disabled placeholder="此字段不可编辑" />
  <button type="submit">提交</button>
</form>

```

---

## 路径：相对路径与绝对路径

假设项目文件结构如下：

```
my-website/
  index.html
  about.html
  images/
    photo.jpg
    logo.png
  css/
    style.css
  pages/
    contact.html

```

**绝对路径**：从网站根目录或完整 URL 开始的路径。

```html
<!-- 完整 URL（外部资源） -->
<img src="https://example.com/images/photo.jpg" alt="外部图片" />

<!-- 从网站根目录开始（以 / 开头） -->
<img src="/images/photo.jpg" alt="从根目录出发" />
<link rel="stylesheet" href="/css/style.css" />

```

**相对路径**：相对于当前文件所在位置的路径。

```html
<!-- 在 index.html 中引用同级目录的文件 -->
<a href="about.html">关于我们</a>

<!-- 在 index.html 中引用子目录的文件 -->
<img src="images/photo.jpg" alt="子目录中的图片" />
<link rel="stylesheet" href="css/style.css" />

<!-- 在 pages/contact.html 中引用上级目录的图片 -->
<!-- ../ 表示返回上一级目录 -->
<img src="../images/logo.png" alt="标志" />

<!-- 返回两级目录 -->
<a href="../../index.html">返回首页</a>

```

---

## 表单完整示例

这是一个完整的用户注册页面：

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>用户注册</title>
    <style>
      /* 简单样式，让表单好看一些 */
      body {
        font-family: sans-serif;
        max-width: 500px;
        margin: 40px auto;
        padding: 0 20px;
      }
      .form-group {
        margin-bottom: 16px;
      }
      label {
        display: block;
        margin-bottom: 4px;
        font-weight: bold;
      }
      input,
      select,
      textarea {
        width: 100%;
        padding: 8px;
        box-sizing: border-box;
        border: 1px solid #ccc;
        border-radius: 4px;
      }
      .radio-group label,
      .checkbox-group label {
        font-weight: normal;
        display: inline;
        margin-left: 4px;
      }
      button {
        padding: 10px 24px;
        background-color: #0066cc;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
      button:hover {
        background-color: #0055aa;
      }
    </style>
  </head>
  <body>
    <h1>用户注册</h1>

    <!-- action 留空表示提交到当前页面（实际开发中填写后端接口地址） -->
    <form action="" method="post">

      <!-- 用户名 -->
      <div class="form-group">
        <label for="username">用户名 *</label>
        <input
          type="text"
          id="username"
          name="username"
          placeholder="4-16个字符"
          minlength="4"
          maxlength="16"
          required
        />
      </div>

      <!-- 邮箱 -->
      <div class="form-group">
        <label for="email">邮箱 *</label>
        <input
          type="email"
          id="email"
          name="email"
          placeholder="example@example.com"
          required
        />
      </div>

      <!-- 密码 -->
      <div class="form-group">
        <label for="password">密码 *</label>
        <input
          type="password"
          id="password"
          name="password"
          placeholder="至少8位"
          minlength="8"
          required
        />
      </div>

      <!-- 性别（单选） -->
      <div class="form-group">
        <label>性别</label>
        <div class="radio-group">
          <input type="radio" id="male" name="gender" value="male" />
          <label for="male">男</label>
          <input type="radio" id="female" name="gender" value="female" />
          <label for="female">女</label>
          <input type="radio" id="other" name="gender" value="other" />
          <label for="other">其他</label>
        </div>
      </div>

      <!-- 出生日期 -->
      <div class="form-group">
        <label for="birthday">出生日期</label>
        <input type="date" id="birthday" name="birthday" />
      </div>

      <!-- 所在城市 -->
      <div class="form-group">
        <label for="city">所在城市</label>
        <select id="city" name="city">
          <option value="">请选择城市</option>
          <option value="beijing">北京</option>
          <option value="shanghai">上海</option>
          <option value="guangzhou">广州</option>
          <option value="shenzhen">深圳</option>
          <option value="other">其他</option>
        </select>
      </div>

      <!-- 兴趣爱好（复选） -->
      <div class="form-group">
        <label>兴趣爱好</label>
        <div class="checkbox-group">
          <input type="checkbox" id="hobby-reading" name="hobby" value="reading" />
          <label for="hobby-reading">阅读</label>
          <input type="checkbox" id="hobby-coding" name="hobby" value="coding" />
          <label for="hobby-coding">编程</label>
          <input type="checkbox" id="hobby-sports" name="hobby" value="sports" />
          <label for="hobby-sports">运动</label>
          <input type="checkbox" id="hobby-music" name="hobby" value="music" />
          <label for="hobby-music">音乐</label>
        </div>
      </div>

      <!-- 个人简介 -->
      <div class="form-group">
        <label for="bio">个人简介</label>
        <textarea
          id="bio"
          name="bio"
          rows="4"
          placeholder="简单介绍一下自己（选填）"
          maxlength="500"
        ></textarea>
      </div>

      <!-- 头像上传 -->
      <div class="form-group">
        <label for="avatar">上传头像</label>
        <input type="file" id="avatar" name="avatar" accept="image/*" />
      </div>

      <!-- 同意条款 -->
      <div class="form-group">
        <input type="checkbox" id="agree" name="agree" required />
        <label for="agree" style="display: inline; font-weight: normal;">
          我已阅读并同意 <a href="/terms">用户协议</a>
        </label>
      </div>

      <!-- 操作按钮 -->
      <div class="form-group">
        <button type="submit">立即注册</button>
        <button type="reset" style="margin-left: 10px; background-color: #666;">重置</button>
      </div>

    </form>
  </body>
</html>

```

---

## CSS 是什么

CSS（Cascading Style Sheets，层叠样式表）用于控制网页的视觉外观。

CSS 的基本语法：

```css
/* 选择器 { 属性: 值; } */
h1 {
  color: red;        /* 文字颜色设为红色 */
  font-size: 32px;   /* 字体大小 32 像素 */
  text-align: center; /* 文字居中 */
}

```

---

## CSS 三种引入方式

### 1\. 内联样式（不推荐大量使用）

直接写在 HTML 标签的 `style` 属性里。优先级最高，但维护困难。

```html
<p style="color: red; font-size: 18px;">这段文字是红色的。</p>
<h1 style="text-align: center; background-color: lightblue;">居中蓝底标题</h1>

```

### 2\. 内部样式表

写在 `<head>` 里的 `<style>` 标签内。适合单个页面的样式。

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>内部样式示例</title>
    <style>
      /* 这里写 CSS */
      body {
        font-family: "微软雅黑", sans-serif;
        background-color: #f5f5f5;
      }
      h1 {
        color: #333333;
        text-align: center;
      }
      p {
        color: #666666;
        line-height: 1.8;
      }
    </style>
  </head>
  <body>
    <h1>标题</h1>
    <p>段落文字。</p>
  </body>
</html>

```

### 3\. 外部样式表（推荐）

将 CSS 单独写在 `.css` 文件中，然后在 HTML 中用 `<link>` 引入。多个页面可以共用同一个 CSS 文件。

创建 `style.css`：

```css
/* style.css */
body {
  font-family: "微软雅黑", sans-serif;
  background-color: #f5f5f5;
  margin: 0;
  padding: 0;
}

h1 {
  color: #333333;
  text-align: center;
}

```

在 HTML 中引入：

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>外部样式示例</title>
    <!-- 用 link 标签引入外部 CSS 文件 -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <h1>标题</h1>
  </body>
</html>

```

---

## CSS 选择器

选择器决定 CSS 规则作用于哪些 HTML 元素。

### 基础选择器

```css
/* 标签选择器：选中所有 p 标签 */
p {
  color: #333;
}

/* 类选择器：选中所有 class="highlight" 的元素（以 . 开头） */
.highlight {
  background-color: yellow;
}

/* ID 选择器：选中 id="header" 的元素（以 # 开头，每页唯一） */
#header {
  background-color: #0066cc;
  color: white;
}

/* 通配符选择器：选中所有元素（谨慎使用） */
* {
  box-sizing: border-box;
}

```

### 组合选择器

```css
/* 后代选择器（空格）：选中 .card 内所有的 p 元素（包括多层嵌套） */
.card p {
  font-size: 14px;
}

/* 子选择器（>）：只选中 .nav 的直接子元素 li */
.nav > li {
  display: inline-block;
}

/* 相邻兄弟选择器（+）：选中紧跟在 h2 后面的那一个 p */
h2 + p {
  font-weight: bold;
}

/* 通用兄弟选择器（~）：选中 h2 后面所有的 p（同级） */
h2 ~ p {
  color: #555;
}

/* 分组选择器（,）：同时选中 h1、h2、h3 */
h1,
h2,
h3 {
  font-family: "微软雅黑", sans-serif;
}

```

### 属性选择器

```css
/* 选中有 disabled 属性的 input */
input[disabled] {
  background-color: #eee;
}

/* 选中 type="text" 的 input */
input[type="text"] {
  border: 1px solid #ccc;
}

/* 选中 href 以 https 开头的链接 */
a[href^="https"] {
  color: green;
}

```

### 伪类选择器

伪类描述元素的特定状态。

```css
/* :hover — 鼠标悬停时 */
a:hover {
  color: orange;
  text-decoration: underline;
}

button:hover {
  background-color: darkblue;
}

/* :focus — 元素获得焦点时（如 input 被点击） */
input:focus {
  outline: 2px solid #0066cc;
  border-color: #0066cc;
}

/* :first-child — 选中父元素的第一个子元素 */
li:first-child {
  font-weight: bold;
}

/* :last-child — 选中父元素的最后一个子元素 */
li:last-child {
  border-bottom: none;
}

/* :nth-child(n) — 选中第 n 个子元素 */
tr:nth-child(2) {
  background-color: #f0f0f0; /* 选中第2行 */
}

/* :nth-child(odd) 和 :nth-child(even) — 奇偶行 */
tr:nth-child(odd) {
  background-color: #fafafa;
}

tr:nth-child(even) {
  background-color: #f0f0f0;
}

/* :not() — 排除某些元素 */
li:not(:last-child) {
  border-bottom: 1px solid #eee;
}

/* :checked — 被勾选的复选框或单选框 */
input:checked + label {
  color: #0066cc;
}

```

完整示例：

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>伪类示例</title>
    <style>
      ul {
        list-style: none;
        padding: 0;
        max-width: 300px;
      }
      li {
        padding: 10px;
        border-bottom: 1px solid #eee;
        transition: background-color 0.2s;
      }
      /* 鼠标悬停高亮 */
      li:hover {
        background-color: #f0f8ff;
      }
      /* 第一项加粗 */
      li:first-child {
        font-weight: bold;
      }
      /* 最后一项去掉底部边框 */
      li:last-child {
        border-bottom: none;
      }
      /* 奇数项背景 */
      li:nth-child(odd) {
        background-color: #fafafa;
      }
    </style>
  </head>
  <body>
    <ul>
      <li>第一项（加粗）</li>
      <li>第二项</li>
      <li>第三项</li>
      <li>第四项</li>
      <li>第五项（无底部边框）</li>
    </ul>
  </body>
</html>

```

### 伪元素选择器

伪元素在元素内部的特定位置插入内容，使用双冒号 `::` 。

```css
/* ::before — 在元素内容之前插入 */
.required-field::before {
  content: "* ";
  color: red;
}

/* ::after — 在元素内容之后插入 */
.price::after {
  content: " 元";
  font-size: 12px;
  color: #999;
}

/* ::first-line — 段落的第一行 */
p::first-line {
  font-weight: bold;
}

/* ::first-letter — 段落的第一个字母/字 */
p::first-letter {
  font-size: 2em;
  float: left;
  margin-right: 4px;
}

/* ::placeholder — 输入框占位文字 */
input::placeholder {
  color: #aaa;
  font-style: italic;
}

```

```html
<!-- ::before 和 ::after 使用示例 -->
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>伪元素示例</title>
    <style>
      /* 用 ::before 给必填字段标红星号 */
      .required::before {
        content: "* ";
        color: red;
      }
      /* 用 ::after 在价格后加单位 */
      .price::after {
        content: " 元";
        font-size: 12px;
        color: #999;
      }
      /* 用 ::before 和 ::after 制作装饰线 */
      .section-title {
        text-align: center;
        position: relative;
      }
      .section-title::before,
      .section-title::after {
        content: "";
        display: inline-block;
        width: 60px;
        height: 1px;
        background-color: #ccc;
        vertical-align: middle;
        margin: 0 10px;
      }
    </style>
  </head>
  <body>
    <label class="required">用户名</label>
    <p>商品价格：<span class="price">299</span></p>
    <h2 class="section-title">精选商品</h2>
  </body>
</html>

```

---

## 盒模型

每个 HTML 元素都可以看成一个盒子，由四层组成（从内到外）：

```
+------------------------------------------+
|               margin（外边距）              |
|  +------------------------------------+   |
|  |          border（边框）             |   |
|  |  +------------------------------+  |   |
|  |  |       padding（内边距）        |  |   |
|  |  |  +------------------------+  |  |   |
|  |  |  |    content（内容区域）  |  |  |   |
|  |  |  |    width × height      |  |  |   |
|  |  |  +------------------------+  |  |   |
|  |  +------------------------------+  |   |
|  +------------------------------------+   |
+------------------------------------------+

```

| 层       | 说明                         |
| ------- | -------------------------- |
| content | 实际内容区域，由 width 和 height 控制 |
| padding | 内容与边框之间的空白，背景色会延伸到 padding |
| border  | 边框，可设置宽度、样式、颜色             |
| margin  | 元素与其他元素之间的空白，透明无背景色        |

```css
.box {
  /* 内容区域尺寸 */
  width: 300px;
  height: 200px;

  /* 内边距：上下 10px，左右 20px */
  padding: 10px 20px;

  /* 边框：2px 实线 深灰色 */
  border: 2px solid #333;

  /* 外边距：上下 16px，左右自动（实现水平居中） */
  margin: 16px auto;

  background-color: lightblue;
}

```

### padding 和 margin 的简写规则

```css
.box {
  /* 四个方向相同 */
  padding: 10px;

  /* 上下 | 左右 */
  padding: 10px 20px;

  /* 上 | 左右 | 下 */
  padding: 10px 20px 15px;

  /* 上 | 右 | 下 | 左（顺时针） */
  padding: 10px 20px 15px 5px;

  /* margin 同理 */
  margin: 0 auto;       /* 常用：水平居中（上下0，左右自动） */
}

```

### box-sizing

**重要概念**：默认情况下，`width` 只表示 content 的宽度，实际占用宽度 = width + padding + border。

使用 `box-sizing: border-box` 后，`width` 表示 content + padding + border 的总宽度，更符合直觉。

```css
/* 推荐：在所有项目开头加上这段代码 */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* 演示区别 */
.default-box {
  box-sizing: content-box; /* 默认值 */
  width: 200px;
  padding: 20px;
  border: 2px solid black;
  /* 实际占用宽度 = 200 + 20*2 + 2*2 = 244px */
}

.border-box {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 2px solid black;
  /* 实际占用宽度 = 200px（内容区会自动缩小） */
}

```

---

## 常用 CSS 属性

### 颜色

```css
.example {
  /* 颜色名称 */
  color: red;
  color: black;
  color: transparent; /* 透明 */

  /* 十六进制（最常用） */
  color: #ff0000;   /* 红色 */
  color: #333333;   /* 深灰色 */
  color: #333;      /* 简写：每两位相同时可缩短 */

  /* RGB */
  color: rgb(255, 0, 0);     /* 红色 */
  color: rgb(51, 51, 51);    /* 深灰色 */

  /* RGBA（最后一个参数是透明度，0-1） */
  color: rgba(0, 0, 0, 0.5); /* 半透明黑色 */

  /* HSL（色相/饱和度/亮度） */
  color: hsl(0, 100%, 50%);  /* 红色 */
}

```

### 字体

```css
.text {
  /* 字体大小 */
  font-size: 16px;
  font-size: 1rem;  /* 相对于根元素字体大小（通常是16px） */
  font-size: 1.5em; /* 相对于父元素字体大小 */

  /* 字体族 */
  font-family: "微软雅黑", "PingFang SC", sans-serif;
  /* 写多个字体是备用方案，浏览器从左往右找可用的 */

  /* 字重（粗细） */
  font-weight: normal;  /* 等同于 400 */
  font-weight: bold;    /* 等同于 700 */
  font-weight: 300;     /* 细体 */
  font-weight: 600;     /* 半粗体 */

  /* 行高（影响行间距） */
  line-height: 1.6;     /* 推荐：无单位，相对于字体大小 */
  line-height: 24px;

  /* 字母/文字间距 */
  letter-spacing: 2px;

  /* 文字对齐 */
  text-align: left;
  text-align: center;
  text-align: right;
  text-align: justify; /* 两端对齐 */

  /* 文字装饰 */
  text-decoration: none;        /* 去掉链接下划线 */
  text-decoration: underline;   /* 下划线 */
  text-decoration: line-through; /* 删除线 */

  /* 文字转换 */
  text-transform: uppercase; /* 全大写 */
  text-transform: lowercase; /* 全小写 */

  /* 溢出省略号（单行） */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

```

### 背景

```css
.box {
  /* 背景颜色 */
  background-color: #f5f5f5;

  /* 背景图片 */
  background-image: url("bg.jpg");

  /* 背景尺寸 */
  background-size: cover;   /* 覆盖整个区域，可能裁剪 */
  background-size: contain; /* 完整显示，可能留白 */
  background-size: 100% 100%; /* 拉伸填满 */

  /* 背景位置 */
  background-position: center center;
  background-position: top left;

  /* 背景是否重复 */
  background-repeat: no-repeat;
  background-repeat: repeat-x; /* 只横向重复 */

  /* 渐变背景 */
  background: linear-gradient(to right, #0066cc, #00aaff);
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

```

### 边框

```css
.box {
  /* 边框简写：宽度 样式 颜色 */
  border: 1px solid #ccc;
  border: 2px dashed red;
  border: 3px dotted #333;

  /* 单独设置某一侧 */
  border-top: 2px solid black;
  border-bottom: 1px solid #eee;
  border-left: 4px solid #0066cc; /* 常用于卡片左侧色条 */
  border-right: none;

  /* 圆角 */
  border-radius: 4px;        /* 全部圆角 4px */
  border-radius: 50%;        /* 圆形（配合等宽高使用） */
  border-radius: 8px 0 8px 0; /* 左上 右上 右下 左下 */
}

```

### 阴影

```css
.box {
  /* 盒阴影：x偏移 y偏移 模糊半径 扩散半径 颜色 */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);

  /* 多层阴影（用逗号分隔） */
  box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 4px 12px rgba(0,0,0,0.05);

  /* 内阴影 */
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
}

.text {
  /* 文字阴影：x偏移 y偏移 模糊半径 颜色 */
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
}

```

---

## display 属性

`display` 控制元素的显示方式。

| 值            | 特点                                  |
| ------------ | ----------------------------------- |
| block        | 块级元素，独占一行，可设置宽高（div、p、h1-h6 的默认值）   |
| inline       | 行内元素，不换行，不能设置宽高（span、a、strong 的默认值） |
| inline-block | 行内排列，但可以设置宽高                        |
| none         | 隐藏元素，不占据空间                          |
| flex         | 弹性布局（见下一节）                          |
| grid         | 网格布局（见后续章节）                         |

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>display 示例</title>
    <style>
      /* 将 span 变成块级元素 */
      .block-span {
        display: block;
        background-color: lightblue;
        margin-bottom: 8px;
      }

      /* 将 div 变成行内元素 */
      .inline-div {
        display: inline;
        background-color: lightgreen;
      }

      /* inline-block：行内排列，可设置宽高 */
      .nav-item {
        display: inline-block;
        width: 80px;
        height: 36px;
        line-height: 36px;
        text-align: center;
        background-color: #0066cc;
        color: white;
        margin-right: 4px;
      }

      /* 隐藏元素 */
      .hidden {
        display: none;
      }
    </style>
  </head>
  <body>
    <span class="block-span">我是 span，但现在独占一行</span>
    <span class="block-span">我也是</span>

    <div class="inline-div">div1</div>
    <div class="inline-div">div2（行内排列）</div>

    <div>
      <span class="nav-item">首页</span>
      <span class="nav-item">产品</span>
      <span class="nav-item">关于</span>
    </div>

    <p class="hidden">这段文字被隐藏了，不占空间</p>
  </body>
</html>

```

---

## Flexbox 弹性布局

Flexbox 是目前最常用的 CSS 布局方式，用于在一个方向上排列元素。

给父元素设置 `display: flex`，其直接子元素自动成为 flex 子项。

### 父容器属性

```css
.container {
  display: flex;

  /* 主轴方向（元素排列方向） */
  flex-direction: row;            /* 默认：水平从左到右 */
  flex-direction: row-reverse;    /* 水平从右到左 */
  flex-direction: column;         /* 垂直从上到下 */
  flex-direction: column-reverse; /* 垂直从下到上 */

  /* 主轴对齐（元素在主轴方向上的排列） */
  justify-content: flex-start;    /* 默认：靠左（或靠上） */
  justify-content: flex-end;      /* 靠右（或靠下） */
  justify-content: center;        /* 居中 */
  justify-content: space-between; /* 两端对齐，间距均分 */
  justify-content: space-around;  /* 每个元素左右各有相同间距 */
  justify-content: space-evenly;  /* 所有间距完全相等 */

  /* 交叉轴对齐（元素在垂直于主轴方向上的对齐） */
  align-items: stretch;           /* 默认：拉伸填满 */
  align-items: flex-start;        /* 顶部对齐 */
  align-items: flex-end;          /* 底部对齐 */
  align-items: center;            /* 垂直居中 */
  align-items: baseline;          /* 文字基线对齐 */

  /* 换行 */
  flex-wrap: nowrap;   /* 默认：不换行（子项可能溢出或压缩） */
  flex-wrap: wrap;     /* 超出宽度自动换行 */

  /* 间距（推荐用 gap 代替 margin） */
  gap: 16px;           /* 行间距和列间距都是 16px */
  gap: 16px 24px;      /* 行间距 16px，列间距 24px */
}

```

### 子项属性

```css
.item {
  /* 弹性增长：剩余空间的分配比例（0表示不增长） */
  flex-grow: 0;   /* 默认 */
  flex-grow: 1;   /* 占据剩余空间 */

  /* 弹性收缩：空间不足时的收缩比例 */
  flex-shrink: 1; /* 默认：允许收缩 */
  flex-shrink: 0; /* 不收缩（保持原始大小） */

  /* 基础尺寸 */
  flex-basis: auto;   /* 默认：由内容决定 */
  flex-basis: 200px;

  /* 简写：flex-grow flex-shrink flex-basis */
  flex: 1;           /* 等同于 flex: 1 1 0%，常用 */
  flex: 0 0 200px;   /* 固定宽度 200px，不伸缩 */

  /* 单个子项的交叉轴对齐（覆盖父容器的 align-items） */
  align-self: center;
  align-self: flex-end;

  /* 排列顺序（默认0，数字越小越靠前） */
  order: -1; /* 排到最前面 */
  order: 1;  /* 排到后面 */
}

```

### Flexbox 完整示例

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>Flexbox 完整示例</title>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      body {
        font-family: sans-serif;
        padding: 20px;
        background: #f5f5f5;
      }

      /* 示例1：水平导航栏 */
      .navbar {
        display: flex;
        justify-content: space-between; /* logo 在左，菜单在右 */
        align-items: center;
        background: #333;
        padding: 0 20px;
        height: 60px;
      }

      .navbar .logo {
        color: white;
        font-size: 20px;
        font-weight: bold;
      }

      .navbar .menu {
        display: flex;
        gap: 20px;
        list-style: none;
      }

      .navbar .menu a {
        color: #ccc;
        text-decoration: none;
      }

      .navbar .menu a:hover {
        color: white;
      }

      /* 示例2：卡片列表（自动换行） */
      .card-list {
        display: flex;
        flex-wrap: wrap;
        gap: 16px;
        margin-top: 20px;
      }

      .card {
        flex: 0 0 calc(33.333% - 11px); /* 三列布局 */
        background: white;
        border-radius: 8px;
        padding: 20px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      }

      .card h3 {
        margin-bottom: 8px;
        color: #333;
      }

      .card p {
        color: #666;
        font-size: 14px;
        line-height: 1.6;
      }

      /* 示例3：垂直居中 */
      .center-box {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 200px;
        background: #e8f4fd;
        border-radius: 8px;
        margin-top: 20px;
      }

      .center-box .content {
        text-align: center;
      }
    </style>
  </head>
  <body>

    <!-- 导航栏 -->
    <nav class="navbar">
      <div class="logo">MyBrand</div>
      <ul class="menu">
        <li><a href="#">首页</a></li>
        <li><a href="#">产品</a></li>
        <li><a href="#">关于</a></li>
        <li><a href="#">联系</a></li>
      </ul>
    </nav>

    <!-- 卡片列表 -->
    <div class="card-list">
      <div class="card">
        <h3>卡片标题一</h3>
        <p>这是卡片的描述文字，介绍卡片的内容。</p>
      </div>
      <div class="card">
        <h3>卡片标题二</h3>
        <p>这是卡片的描述文字，介绍卡片的内容。</p>
      </div>
      <div class="card">
        <h3>卡片标题三</h3>
        <p>这是卡片的描述文字，介绍卡片的内容。</p>
      </div>
    </div>

    <!-- 垂直居中 -->
    <div class="center-box">
      <div class="content">
        <h2>完美居中</h2>
        <p>使用 Flexbox 轻松实现水平垂直居中</p>
      </div>
    </div>

  </body>
</html>

```

---

## Grid 网格布局

Grid 是二维布局系统，同时控制行和列，适合整体页面布局。

### 父容器属性

```css
.grid-container {
  display: grid;

  /* 定义列：三列，每列 1fr（等分剩余空间） */
  grid-template-columns: 1fr 1fr 1fr;

  /* 简写：repeat(重复次数, 尺寸) */
  grid-template-columns: repeat(3, 1fr);

  /* 固定宽度和弹性宽度混合 */
  grid-template-columns: 200px 1fr 1fr;
  grid-template-columns: 250px 1fr; /* 左侧边栏 + 主内容 */

  /* 定义行高 */
  grid-template-rows: 60px 1fr 60px; /* 头部 主体 底部 */
  grid-template-rows: auto;           /* 自动高度 */

  /* 间距 */
  gap: 16px;
  gap: 16px 24px; /* 行间距 列间距 */

  /* 自动填充列（每列最少200px，自动适应数量） */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

```

### 子项属性

```css
.grid-item {
  /* 指定列的起止位置（从第1列线到第3列线，跨越2列） */
  grid-column: 1 / 3;
  grid-column: 1 / span 2; /* 等价写法：从第1列开始跨2列 */

  /* 指定行的起止位置 */
  grid-row: 1 / 2;

  /* 简写 */
  grid-area: 1 / 1 / 2 / 3; /* row-start / col-start / row-end / col-end */
}

```

### Grid 完整示例

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>Grid 布局示例</title>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      body {
        font-family: sans-serif;
        min-height: 100vh;
        padding: 20px;
        background: #f0f0f0;
      }

      /* 示例1：页面整体布局 */
      .page-layout {
        display: grid;
        grid-template-columns: 200px 1fr;
        grid-template-rows: 60px 1fr 50px;
        gap: 10px;
        height: 500px;
      }

      /* header 跨越两列 */
      .page-header {
        grid-column: 1 / 3;
        background: #333;
        color: white;
        display: flex;
        align-items: center;
        padding: 0 20px;
      }

      .page-sidebar {
        background: #e8e8e8;
        padding: 16px;
        border-radius: 4px;
      }

      .page-main {
        background: white;
        padding: 20px;
        border-radius: 4px;
      }

      /* footer 跨越两列 */
      .page-footer {
        grid-column: 1 / 3;
        background: #333;
        color: white;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 4px;
      }

      /* 示例2：响应式图片网格 */
      .photo-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
        gap: 12px;
        margin-top: 20px;
      }

      .photo-item {
        aspect-ratio: 1; /* 保持正方形 */
        background: #ccc;
        border-radius: 8px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 24px;
        color: #666;
      }
    </style>
  </head>
  <body>

    <!-- 页面布局 -->
    <div class="page-layout">
      <header class="page-header">页头（跨两列）</header>
      <aside class="page-sidebar">侧边栏</aside>
      <main class="page-main">主内容区域</main>
      <footer class="page-footer">页脚（跨两列）</footer>
    </div>

    <!-- 响应式图片网格 -->
    <div class="photo-grid">
      <div class="photo-item">1</div>
      <div class="photo-item">2</div>
      <div class="photo-item">3</div>
      <div class="photo-item">4</div>
      <div class="photo-item">5</div>
      <div class="photo-item">6</div>
    </div>

  </body>
</html>

```

---

## Position 定位

`position` 属性控制元素的定位方式。

| 值        | 说明                          |
| -------- | --------------------------- |
| static   | 默认值，按正常文档流排列，top/left 等无效   |
| relative | 相对于自身原来位置偏移，原来的空间仍然保留       |
| absolute | 相对于最近的非 static 祖先元素定位，脱离文档流 |
| fixed    | 相对于浏览器视口定位，固定在屏幕上不随滚动移动     |
| sticky   | 滚动到特定位置后固定（粘性定位）            |

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>Position 示例</title>
    <style>
      body {
        font-family: sans-serif;
        height: 2000px; /* 制造滚动条 */
        padding: 20px;
      }

      /* relative：相对自身位置偏移 */
      .relative-box {
        position: relative;
        top: 10px;    /* 向下偏移 10px */
        left: 20px;   /* 向右偏移 20px */
        background: lightblue;
        padding: 10px;
        width: 200px;
      }

      /* absolute 的容器：必须设置 position: relative */
      .card {
        position: relative;
        width: 200px;
        height: 150px;
        background: #f0f0f0;
        border: 1px solid #ccc;
        margin: 40px;
      }

      /* absolute：相对于 .card 定位（右上角角标） */
      .badge {
        position: absolute;
        top: -8px;       /* 超出父元素顶部 */
        right: -8px;     /* 超出父元素右侧 */
        width: 24px;
        height: 24px;
        background: red;
        color: white;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
      }

      /* absolute：绝对居中（常用技巧） */
      .centered {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%); /* 将自身移回一半 */
        font-weight: bold;
        color: #333;
      }

      /* fixed：固定在右下角的悬浮按钮 */
      .fab {
        position: fixed;
        bottom: 30px;
        right: 30px;
        width: 56px;
        height: 56px;
        background: #0066cc;
        color: white;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 28px;
        cursor: pointer;
        box-shadow: 0 4px 12px rgba(0, 102, 204, 0.4);
      }

      /* sticky：表格头部粘性定位 */
      .sticky-header {
        position: sticky;
        top: 0;          /* 距离视口顶部 0 时固定 */
        background: #333;
        color: white;
        padding: 12px 20px;
        z-index: 10;
      }
    </style>
  </head>
  <body>

    <div class="relative-box">relative 定位，向右下偏移</div>

    <div class="card">
      <span class="badge">3</span>
      <span class="centered">绝对居中文字</span>
    </div>

    <div class="sticky-header">向下滚动，我会粘在顶部</div>

    <p style="margin-top: 20px;">继续滚动查看 sticky 效果……</p>

    <!-- 固定悬浮按钮 -->
    <div class="fab">+</div>

  </body>
</html>

```

---

## 响应式设计

响应式设计让网页能在手机、平板、桌面等不同屏幕上都正常显示。

### viewport meta 标签

在 `<head>` 中必须加入这行，否则手机会把页面缩小显示：

```html
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

```

### 媒体查询

媒体查询根据屏幕宽度应用不同的样式。

```css
/* 默认样式（手机优先，移动端先写） */
.container {
  width: 100%;
  padding: 0 16px;
}

.card-list {
  display: flex;
  flex-direction: column; /* 手机：单列 */
  gap: 16px;
}

/* 平板：宽度 >= 768px */
@media (min-width: 768px) {
  .container {
    max-width: 768px;
    margin: 0 auto;
  }

  .card-list {
    flex-direction: row; /* 平板：横向排列 */
    flex-wrap: wrap;
  }

  .card {
    flex: 0 0 calc(50% - 8px); /* 两列 */
  }
}

/* 桌面：宽度 >= 1024px */
@media (min-width: 1024px) {
  .container {
    max-width: 1200px;
  }

  .card {
    flex: 0 0 calc(33.333% - 11px); /* 三列 */
  }
}

/* 也可以设置最大宽度（桌面优先写法） */
@media (max-width: 767px) {
  .sidebar {
    display: none; /* 手机上隐藏侧边栏 */
  }
}

```

常用断点参考（不必死记，根据项目调整）：

| 断点             | 说明         |
| -------------- | ---------- |
| < 576px        | 超小屏（手机竖屏）  |
| 576px - 767px  | 小屏（手机横屏）   |
| 768px - 991px  | 中屏（平板）     |
| 992px - 1199px | 大屏（小桌面）    |
| \>= 1200px     | 超大屏（桌面显示器） |

完整响应式示例：

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>响应式示例</title>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      body {
        font-family: sans-serif;
        background: #f5f5f5;
      }

      .container {
        width: 100%;
        padding: 0 16px;
        margin: 0 auto;
      }

      /* 导航栏 */
      .navbar {
        background: #333;
        padding: 12px 0;
      }

      .navbar .container {
        display: flex;
        justify-content: space-between;
        align-items: center;
      }

      .logo {
        color: white;
        font-size: 20px;
        font-weight: bold;
      }

      /* 手机上隐藏菜单（简化示例，实际需要 JS 控制汉堡菜单） */
      .menu {
        display: none;
        list-style: none;
        gap: 20px;
      }

      .menu a {
        color: #ccc;
        text-decoration: none;
      }

      /* 卡片网格：手机单列 */
      .card-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: 16px;
        padding: 20px 0;
      }

      .card {
        background: white;
        border-radius: 8px;
        padding: 20px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      }

      /* 平板：两列 */
      @media (min-width: 768px) {
        .container {
          max-width: 960px;
        }

        .menu {
          display: flex; /* 平板和桌面显示菜单 */
        }

        .card-grid {
          grid-template-columns: repeat(2, 1fr);
        }
      }

      /* 桌面：三列 */
      @media (min-width: 1024px) {
        .container {
          max-width: 1200px;
        }

        .card-grid {
          grid-template-columns: repeat(3, 1fr);
        }
      }
    </style>
  </head>
  <body>

    <nav class="navbar">
      <div class="container">
        <div class="logo">MySite</div>
        <ul class="menu">
          <li><a href="#">首页</a></li>
          <li><a href="#">产品</a></li>
          <li><a href="#">关于</a></li>
        </ul>
      </div>
    </nav>

    <div class="container">
      <div class="card-grid">
        <div class="card">
          <h3>卡片一</h3>
          <p>这是卡片内容。调整浏览器宽度查看响应式效果。</p>
        </div>
        <div class="card">
          <h3>卡片二</h3>
          <p>这是卡片内容。调整浏览器宽度查看响应式效果。</p>
        </div>
        <div class="card">
          <h3>卡片三</h3>
          <p>这是卡片内容。调整浏览器宽度查看响应式效果。</p>
        </div>
        <div class="card">
          <h3>卡片四</h3>
          <p>这是卡片内容。调整浏览器宽度查看响应式效果。</p>
        </div>
      </div>
    </div>

  </body>
</html>

```

---

## 过渡与动画

### transition 过渡

过渡让属性值的变化平滑发生（而非瞬间跳变）。

```css
/* 语法：transition: 属性名 时长 缓动函数 延迟; */
.button {
  background-color: #0066cc;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;

  /* 所有属性变化都有 0.3s 的过渡 */
  transition: all 0.3s ease;

  /* 只对特定属性添加过渡 */
  transition: background-color 0.3s ease, transform 0.2s ease;
}

.button:hover {
  background-color: #0055aa;
  transform: translateY(-2px); /* 向上移动 2px */
  box-shadow: 0 4px 12px rgba(0, 102, 204, 0.3);
}

```

常用缓动函数：

| 值           | 说明        |
| ----------- | --------- |
| ease        | 默认：先快后慢   |
| linear      | 匀速        |
| ease-in     | 先慢后快      |
| ease-out    | 先快后慢      |
| ease-in-out | 先慢，中间快，再慢 |

### @keyframes 动画

`@keyframes` 定义动画关键帧，`animation` 属性应用动画。

```css
/* 定义旋转动画 */
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

/* 定义渐入上浮动画 */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 定义闪烁动画（多个关键帧） */
@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.05);
  }
  100% {
    transform: scale(1);
  }
}

/* 应用动画 */
.loading-spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f0f0f0;
  border-top-color: #0066cc;
  border-radius: 50%;

  /* animation: 动画名 时长 缓动函数 延迟 次数 方向 */
  animation: spin 1s linear infinite;
}

.hero-title {
  animation: fadeInUp 0.6s ease-out;
}

.cta-button {
  animation: pulse 2s ease-in-out infinite;
}

```

animation 属性详解：

| 子属性                       | 说明            | 示例                           |
| ------------------------- | ------------- | ---------------------------- |
| animation-name            | @keyframes 名称 | spin                         |
| animation-duration        | 单次时长          | 1s                           |
| animation-timing-function | 缓动函数          | ease                         |
| animation-delay           | 开始前等待时间       | 0.5s                         |
| animation-iteration-count | 播放次数          | infinite / 3                 |
| animation-direction       | 方向            | normal / reverse / alternate |
| animation-fill-mode       | 动画结束后状态       | forwards（保持结束状态）             |

```html
<!-- 过渡与动画完整示例 -->
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>动画示例</title>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      body {
        font-family: sans-serif;
        padding: 40px;
        background: #f5f5f5;
        display: flex;
        gap: 30px;
        flex-wrap: wrap;
        align-items: center;
      }

      /* 过渡按钮 */
      .btn {
        padding: 12px 24px;
        background: #0066cc;
        color: white;
        border: none;
        border-radius: 6px;
        cursor: pointer;
        font-size: 16px;
        transition: background-color 0.3s ease,
                    transform 0.2s ease,
                    box-shadow 0.3s ease;
      }

      .btn:hover {
        background: #0055aa;
        transform: translateY(-3px);
        box-shadow: 0 6px 16px rgba(0, 102, 204, 0.3);
      }

      .btn:active {
        transform: translateY(0);
      }

      /* 旋转加载圈 */
      @keyframes spin {
        to { transform: rotate(360deg); }
      }

      .spinner {
        width: 40px;
        height: 40px;
        border: 4px solid #e0e0e0;
        border-top-color: #0066cc;
        border-radius: 50%;
        animation: spin 0.8s linear infinite;
      }

      /* 渐入卡片 */
      @keyframes fadeInUp {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .animated-card {
        background: white;
        border-radius: 8px;
        padding: 20px;
        width: 200px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        animation: fadeInUp 0.6s ease-out;
      }

      /* 心跳 */
      @keyframes heartbeat {
        0%, 100% { transform: scale(1); }
        14% { transform: scale(1.15); }
        28% { transform: scale(1); }
        42% { transform: scale(1.15); }
        70% { transform: scale(1); }
      }

      .heart {
        font-size: 40px;
        display: inline-block;
        animation: heartbeat 1.5s ease-in-out infinite;
        color: red;
      }
    </style>
  </head>
  <body>
    <button class="btn">悬停查看过渡效果</button>
    <div class="spinner"></div>
    <div class="animated-card">
      <h3>渐入卡片</h3>
      <p>刷新页面查看动画</p>
    </div>
    <span class="heart">&#10084;</span>
  </body>
</html>

```

---

## CSS 变量

CSS 变量（也叫自定义属性）让你定义可复用的值，统一管理颜色、间距等设计 token。

```css
/* 变量定义在 :root 上，全局可用 */
:root {
  /* 颜色变量 */
  --color-primary: #0066cc;
  --color-primary-hover: #0055aa;
  --color-text: #333333;
  --color-text-secondary: #666666;
  --color-background: #f5f5f5;
  --color-white: #ffffff;
  --color-border: #e0e0e0;

  /* 间距变量 */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;

  /* 圆角变量 */
  --border-radius: 6px;
  --border-radius-lg: 12px;

  /* 字体大小 */
  --font-size-sm: 14px;
  --font-size-md: 16px;
  --font-size-lg: 20px;

  /* 阴影 */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
}

/* 使用变量：var(--变量名) */
.button {
  background-color: var(--color-primary);
  color: var(--color-white);
  padding: var(--spacing-sm) var(--spacing-md);
  border-radius: var(--border-radius);
  border: none;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.button:hover {
  background-color: var(--color-primary-hover);
}

.card {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius-lg);
  padding: var(--spacing-lg);
  box-shadow: var(--shadow-md);
}

/* 在组件内覆盖变量（局部作用域） */
.dark-theme {
  --color-background: #1a1a1a;
  --color-text: #ffffff;
  --color-white: #2a2a2a;
  --color-border: #444444;
}

/* var() 第二个参数是默认值 */
.element {
  color: var(--color-accent, #ff6600); /* 若 --color-accent 未定义，用 #ff6600 */
}

```

完整变量主题示例：

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>CSS 变量示例</title>
    <style>
      :root {
        --primary: #0066cc;
        --primary-hover: #0055aa;
        --bg: #f5f5f5;
        --surface: #ffffff;
        --text: #333333;
        --text-secondary: #666666;
        --border: #e0e0e0;
        --radius: 8px;
        --shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      }

      /* 暗色主题：只需修改变量 */
      .dark {
        --primary: #4da6ff;
        --bg: #1a1a2e;
        --surface: #16213e;
        --text: #e0e0e0;
        --text-secondary: #aaaaaa;
        --border: #333366;
        --shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
      }

      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      body {
        background: var(--bg);
        color: var(--text);
        font-family: sans-serif;
        padding: 30px;
        min-height: 100vh;
        transition: background 0.3s, color 0.3s;
      }

      .card {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        padding: 24px;
        max-width: 400px;
        box-shadow: var(--shadow);
        margin-bottom: 20px;
      }

      .card p {
        color: var(--text-secondary);
        margin-top: 8px;
      }

      .btn {
        background: var(--primary);
        color: white;
        padding: 10px 20px;
        border: none;
        border-radius: var(--radius);
        cursor: pointer;
        margin-top: 16px;
        transition: background 0.3s;
      }

      .btn:hover {
        background: var(--primary-hover);
      }

      /* 切换主题的按钮 */
      .theme-toggle {
        background: var(--surface);
        border: 1px solid var(--border);
        color: var(--text);
        padding: 8px 16px;
        border-radius: var(--radius);
        cursor: pointer;
        margin-bottom: 20px;
      }
    </style>
  </head>
  <body id="theme-root">
    <button class="theme-toggle" onclick="document.getElementById('theme-root').classList.toggle('dark')">
      切换暗色/亮色主题
    </button>
    <div class="card">
      <h2>CSS 变量实现主题切换</h2>
      <p>点击上方按钮切换主题，所有颜色通过变量统一切换。</p>
      <button class="btn">主要操作按钮</button>
    </div>
  </body>
</html>

```

---

## 综合实战：响应式个人主页

下面是一个完整的响应式个人主页，包含导航栏、Hero 区域、卡片列表、页脚。

将以下代码保存为 `portfolio.html`，直接用浏览器打开即可预览：

```html
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>张三 - 个人主页</title>
    <style>
      /* ========== 全局变量与重置 ========== */
      :root {
        --primary: #0066cc;
        --primary-hover: #0055aa;
        --dark: #1a1a2e;
        --text: #333333;
        --text-secondary: #666666;
        --bg: #f8fafc;
        --surface: #ffffff;
        --border: #e2e8f0;
        --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
        --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.1);
        --radius: 10px;
        --container-max: 1100px;
      }

      *,
      *::before,
      *::after {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      html {
        scroll-behavior: smooth; /* 锚点跳转平滑滚动 */
      }

      body {
        font-family: "PingFang SC", "微软雅黑", sans-serif;
        background: var(--bg);
        color: var(--text);
        line-height: 1.6;
      }

      /* ========== 工具类 ========== */
      .container {
        width: 100%;
        max-width: var(--container-max);
        margin: 0 auto;
        padding: 0 20px;
      }

      /* ========== 导航栏 ========== */
      .navbar {
        position: sticky;
        top: 0;
        z-index: 100;
        background: rgba(26, 26, 46, 0.95);
        backdrop-filter: blur(8px); /* 毛玻璃效果 */
        border-bottom: 1px solid rgba(255, 255, 255, 0.1);
      }

      .navbar .container {
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 64px;
      }

      .nav-logo {
        font-size: 20px;
        font-weight: 700;
        color: #ffffff;
        text-decoration: none;
        letter-spacing: 1px;
      }

      .nav-menu {
        display: flex;
        gap: 32px;
        list-style: none;
      }

      .nav-menu a {
        color: rgba(255, 255, 255, 0.75);
        text-decoration: none;
        font-size: 15px;
        transition: color 0.2s;
      }

      .nav-menu a:hover {
        color: #ffffff;
      }

      /* ========== Hero 区域 ========== */
      .hero {
        background: linear-gradient(135deg, #1a1a2e 0%, #0f3460 60%, #0066cc 100%);
        color: white;
        padding: 100px 0;
        text-align: center;
      }

      .hero-avatar {
        width: 120px;
        height: 120px;
        border-radius: 50%;
        background: rgba(255, 255, 255, 0.15);
        border: 3px solid rgba(255, 255, 255, 0.4);
        margin: 0 auto 24px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 48px;
        /* 替换 background-image 为实际头像图片：
           background-image: url("avatar.jpg");
           background-size: cover; */
      }

      .hero h1 {
        font-size: 42px;
        font-weight: 700;
        margin-bottom: 12px;
        animation: fadeInUp 0.7s ease-out;
      }

      .hero .subtitle {
        font-size: 18px;
        color: rgba(255, 255, 255, 0.8);
        margin-bottom: 8px;
        animation: fadeInUp 0.7s ease-out 0.1s both;
      }

      .hero .description {
        font-size: 15px;
        color: rgba(255, 255, 255, 0.65);
        max-width: 500px;
        margin: 0 auto 36px;
        animation: fadeInUp 0.7s ease-out 0.2s both;
      }

      .hero-buttons {
        display: flex;
        gap: 12px;
        justify-content: center;
        flex-wrap: wrap;
        animation: fadeInUp 0.7s ease-out 0.3s both;
      }

      .btn-primary {
        background: white;
        color: var(--primary);
        padding: 12px 28px;
        border-radius: 50px;
        text-decoration: none;
        font-weight: 600;
        font-size: 15px;
        transition: transform 0.2s ease, box-shadow 0.2s ease;
      }

      .btn-primary:hover {
        transform: translateY(-2px);
        box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
      }

      .btn-outline {
        border: 2px solid rgba(255, 255, 255, 0.6);
        color: white;
        padding: 12px 28px;
        border-radius: 50px;
        text-decoration: none;
        font-weight: 600;
        font-size: 15px;
        transition: border-color 0.2s, background 0.2s;
      }

      .btn-outline:hover {
        border-color: white;
        background: rgba(255, 255, 255, 0.1);
      }

      /* Hero 入场动画 */
      @keyframes fadeInUp {
        from {
          opacity: 0;
          transform: translateY(24px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      /* ========== 技能标签 ========== */
      .skills-section {
        padding: 60px 0;
        background: var(--surface);
        border-bottom: 1px solid var(--border);
      }

      .section-title {
        text-align: center;
        font-size: 28px;
        font-weight: 700;
        margin-bottom: 8px;
        color: var(--text);
      }

      .section-subtitle {
        text-align: center;
        color: var(--text-secondary);
        margin-bottom: 36px;
      }

      .skills-grid {
        display: flex;
        flex-wrap: wrap;
        gap: 12px;
        justify-content: center;
      }

      .skill-tag {
        background: #f0f7ff;
        color: var(--primary);
        border: 1px solid #c3dafe;
        padding: 8px 18px;
        border-radius: 50px;
        font-size: 14px;
        font-weight: 500;
        transition: background 0.2s, transform 0.2s;
      }

      .skill-tag:hover {
        background: var(--primary);
        color: white;
        transform: translateY(-2px);
      }

      /* ========== 项目卡片区域 ========== */
      .projects-section {
        padding: 70px 0;
      }

      /* Grid 布局：手机1列，平板2列，桌面3列 */
      .projects-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: 24px;
      }

      .project-card {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        overflow: hidden;
        box-shadow: var(--shadow-sm);
        transition: transform 0.2s ease, box-shadow 0.2s ease;
      }

      .project-card:hover {
        transform: translateY(-4px);
        box-shadow: var(--shadow-md);
      }

      /* 卡片图片区域（用纯色代替实际图片） */
      .card-image {
        height: 180px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 14px;
        color: rgba(255, 255, 255, 0.8);
        font-weight: 500;
      }

      .card-image.blue   { background: linear-gradient(135deg, #0066cc, #00aaff); }
      .card-image.purple { background: linear-gradient(135deg, #764ba2, #667eea); }
      .card-image.green  { background: linear-gradient(135deg, #11998e, #38ef7d); }

      .card-content {
        padding: 20px;
      }

      .card-content h3 {
        font-size: 18px;
        margin-bottom: 8px;
        color: var(--text);
      }

      .card-content p {
        font-size: 14px;
        color: var(--text-secondary);
        line-height: 1.7;
        margin-bottom: 16px;
      }

      .card-tags {
        display: flex;
        gap: 8px;
        flex-wrap: wrap;
        margin-bottom: 16px;
      }

      .card-tag {
        background: var(--bg);
        color: var(--text-secondary);
        border: 1px solid var(--border);
        padding: 3px 10px;
        border-radius: 4px;
        font-size: 12px;
      }

      .card-link {
        display: inline-block;
        color: var(--primary);
        text-decoration: none;
        font-size: 14px;
        font-weight: 600;
        transition: color 0.2s;
      }

      .card-link:hover {
        color: var(--primary-hover);
        text-decoration: underline;
      }

      /* ========== 关于区域 ========== */
      .about-section {
        padding: 70px 0;
        background: var(--surface);
        border-top: 1px solid var(--border);
      }

      .about-inner {
        display: grid;
        grid-template-columns: 1fr;
        gap: 40px;
        align-items: center;
      }

      .about-text h2 {
        font-size: 28px;
        font-weight: 700;
        margin-bottom: 16px;
      }

      .about-text p {
        color: var(--text-secondary);
        margin-bottom: 16px;
        line-height: 1.8;
      }

      .stats-grid {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 20px;
        text-align: center;
      }

      .stat-item {
        background: var(--bg);
        border-radius: var(--radius);
        padding: 20px 10px;
        border: 1px solid var(--border);
      }

      .stat-number {
        font-size: 32px;
        font-weight: 700;
        color: var(--primary);
        display: block;
      }

      .stat-label {
        font-size: 13px;
        color: var(--text-secondary);
        margin-top: 4px;
      }

      /* ========== 页脚 ========== */
      .footer {
        background: var(--dark);
        color: rgba(255, 255, 255, 0.7);
        padding: 40px 0;
        text-align: center;
      }

      .footer-links {
        display: flex;
        justify-content: center;
        gap: 24px;
        margin-bottom: 20px;
        flex-wrap: wrap;
      }

      .footer-links a {
        color: rgba(255, 255, 255, 0.6);
        text-decoration: none;
        font-size: 14px;
        transition: color 0.2s;
      }

      .footer-links a:hover {
        color: white;
      }

      .footer-copy {
        font-size: 13px;
        color: rgba(255, 255, 255, 0.4);
      }

      /* ========== 响应式断点 ========== */

      /* 平板及以上 */
      @media (min-width: 768px) {
        .hero h1 {
          font-size: 52px;
        }

        .projects-grid {
          grid-template-columns: repeat(2, 1fr);
        }

        .about-inner {
          grid-template-columns: 1fr 1fr;
        }
      }

      /* 桌面 */
      @media (min-width: 1024px) {
        .projects-grid {
          grid-template-columns: repeat(3, 1fr);
        }
      }

      /* 手机：隐藏导航菜单（实际项目需加汉堡菜单 JS） */
      @media (max-width: 640px) {
        .nav-menu {
          display: none;
        }

        .hero {
          padding: 60px 0;
        }

        .hero h1 {
          font-size: 32px;
        }
      }
    </style>
  </head>
  <body>

    <!-- ========== 导航栏 ========== -->
    <header class="navbar">
      <div class="container">
        <a href="#" class="nav-logo">ZS.DEV</a>
        <nav>
          <ul class="nav-menu">
            <li><a href="#skills">技能</a></li>
            <li><a href="#projects">项目</a></li>
            <li><a href="#about">关于</a></li>
            <li><a href="#contact">联系</a></li>
          </ul>
        </nav>
      </div>
    </header>

    <!-- ========== Hero 区域 ========== -->
    <section class="hero">
      <div class="container">
        <!-- 头像（替换为实际图片） -->
        <div class="hero-avatar">Z</div>
        <h1>你好，我是张三</h1>
        <p class="subtitle">前端开发工程师</p>
        <p class="description">
          热爱构建精致、响应迅速的 Web 应用。<br />
          专注于用户体验与现代前端技术。
        </p>
        <div class="hero-buttons">
          <a href="#projects" class="btn-primary">查看我的项目</a>
          <a href="#contact" class="btn-outline">联系我</a>
        </div>
      </div>
    </section>

    <!-- ========== 技能区域 ========== -->
    <section class="skills-section" id="skills">
      <div class="container">
        <h2 class="section-title">技术栈</h2>
        <p class="section-subtitle">我熟悉的技术与工具</p>
        <div class="skills-grid">
          <span class="skill-tag">HTML5</span>
          <span class="skill-tag">CSS3</span>
          <span class="skill-tag">JavaScript</span>
          <span class="skill-tag">Vue3</span>
          <span class="skill-tag">React</span>
          <span class="skill-tag">Node.js</span>
          <span class="skill-tag">Git</span>
          <span class="skill-tag">Webpack</span>
          <span class="skill-tag">Figma</span>
          <span class="skill-tag">Python</span>
        </div>
      </div>
    </section>

    <!-- ========== 项目卡片区域 ========== -->
    <section class="projects-section" id="projects">
      <div class="container">
        <h2 class="section-title">精选项目</h2>
        <p class="section-subtitle">近期参与的项目</p>

        <div class="projects-grid">

          <!-- 项目卡片1 -->
          <div class="project-card">
            <div class="card-image blue">项目截图（可替换为 img 标签）</div>
            <div class="card-content">
              <h3>电商管理后台</h3>
              <p>
                基于 Vue3 + Element Plus 构建的后台管理系统，
                包含商品管理、订单处理、数据可视化等功能模块。
              </p>
              <div class="card-tags">
                <span class="card-tag">Vue3</span>
                <span class="card-tag">Element Plus</span>
                <span class="card-tag">ECharts</span>
              </div>
              <a href="#" class="card-link">查看详情</a>
            </div>
          </div>

          <!-- 项目卡片2 -->
          <div class="project-card">
            <div class="card-image purple">项目截图（可替换为 img 标签）</div>
            <div class="card-content">
              <h3>个人博客系统</h3>
              <p>
                使用 React + Node.js 全栈开发，支持 Markdown 写作、
                标签分类、评论互动，部署于云服务器。
              </p>
              <div class="card-tags">
                <span class="card-tag">React</span>
                <span class="card-tag">Node.js</span>
                <span class="card-tag">MongoDB</span>
              </div>
              <a href="#" class="card-link">查看详情</a>
            </div>
          </div>

          <!-- 项目卡片3 -->
          <div class="project-card">
            <div class="card-image green">项目截图（可替换为 img 标签）</div>
            <div class="card-content">
              <h3>实时天气应用</h3>
              <p>
                基于原生 JavaScript + OpenWeather API 开发，
                支持城市搜索、实时天气、7 日预报，完全响应式。
              </p>
              <div class="card-tags">
                <span class="card-tag">HTML/CSS/JS</span>
                <span class="card-tag">REST API</span>
                <span class="card-tag">响应式</span>
              </div>
              <a href="#" class="card-link">查看详情</a>
            </div>
          </div>

        </div>
      </div>
    </section>

    <!-- ========== 关于区域 ========== -->
    <section class="about-section" id="about">
      <div class="container">
        <div class="about-inner">

          <div class="about-text">
            <h2>关于我</h2>
            <p>
              我是一名有 3 年经验的前端工程师，毕业于某某大学计算机科学专业。
              热爱开源、持续学习，相信好的产品源于对细节的执着。
            </p>
            <p>
              工作之余喜欢读书、跑步和捣鼓副业项目。
              目前正在学习 Three.js 和 WebGL，探索 3D Web 的可能性。
            </p>
          </div>

          <div class="stats-grid">
            <div class="stat-item">
              <span class="stat-number">3+</span>
              <span class="stat-label">年工作经验</span>
            </div>
            <div class="stat-item">
              <span class="stat-number">20+</span>
              <span class="stat-label">完成项目</span>
            </div>
            <div class="stat-item">
              <span class="stat-number">5</span>
              <span class="stat-label">技术方向</span>
            </div>
          </div>

        </div>
      </div>
    </section>

    <!-- ========== 页脚 ========== -->
    <footer class="footer" id="contact">
      <div class="container">
        <div class="footer-links">
          <a href="mailto:zhangsan@example.com">邮件联系</a>
          <a href="https://github.com/" target="_blank">GitHub</a>
          <a href="https://juejin.cn/" target="_blank">掘金</a>
          <a href="#">下载简历</a>
        </div>
        <p class="footer-copy">2026 张三. 用 HTML + CSS 构建.</p>
      </div>
    </footer>

  </body>
</html>

```

---

## 最佳实践

### HTML 语义化

使用语义化标签让浏览器、搜索引擎、屏幕阅读器都能理解页面结构：

| 语义标签      | 用途             | 不推荐的替代                |
| --------- | -------------- | --------------------- |
| <header>  | 页面/区块的头部       | <div class="header">  |
| <nav>     | 导航链接区域         | <div class="nav">     |
| <main>    | 页面主要内容（每页唯一）   | <div class="main">    |
| <article> | 独立的内容单元（博文、评论） | <div class="article"> |
| <section> | 内容分区（需有标题）     | <div class="section"> |
| <aside>   | 侧边栏、补充内容       | <div class="sidebar"> |
| <footer>  | 页面/区块的底部       | <div class="footer">  |
| <button>  | 可点击操作按钮        | <div onclick="...">   |

### CSS 组织原则

- **BEM 命名**：`block__element--modifier`（如 `.card__title--highlighted`），避免全局样式冲突
- **避免深层选择器**：嵌套超过 3 层时考虑拆分为独立类名
- **变量集中管理**：颜色、字体、间距用 CSS 自定义属性（`--primary-color: #3b82f6`）
- **移动优先**：先写小屏样式，用 `@media (min-width: 768px)` 扩展大屏

```css
/* CSS 自定义属性示例 */
:root {
  --color-primary: #3b82f6;
  --color-text: #1f2937;
  --spacing-base: 16px;
  --border-radius: 8px;
}

.button {
  background: var(--color-primary);
  padding: var(--spacing-base);
  border-radius: var(--border-radius);
}

```

### 布局选型

| 场景        | 推荐       | 原因          |
| --------- | -------- | ----------- |
| 一维排列（行或列） | Flexbox  | 简洁、对齐方便     |
| 二维网格布局    | Grid     | 精确控制行列      |
| 文字环绕图片    | Float    | 仍是此场景的正确用法  |
| 固定/绝对定位   | Position | 浮层、工具提示、导航栏 |

### 可访问性（a11y）基础

- 图片必须有 `alt` 属性（装饰性图片用 `alt=""`）
- 表单控件必须有关联的 `<label>`
- 交互元素（按钮、链接）确保键盘可访问（`tabindex`、`focus` 样式）
- 颜色对比度满足 WCAG AA 标准（正文文字对比度 ≥ 4.5:1）

---

## 注意事项与常见错误

### HTML 注意事项

1. **标签必须正确嵌套，不能交叉**  
```html  
<!-- 错误：交叉嵌套 -->  
<b><i>文字</b></i>  
<!-- 正确：先开后关 -->  
<b><i>文字</i></b>  
```
2. **自闭合标签不需要结束标签**  
```html  
<!-- 正确写法 -->  
<img src="photo.jpg" alt="照片" />  
<br />  
<input type="text" />  
<meta charset="UTF-8" />  
```
3. **alt 属性必须写，即使图片只是装饰**  
```html  
<!-- 装饰性图片：alt 留空（但属性本身要写） -->  
<img src="decoration.png" alt="" />  
```
4. **label 和 input 要关联**，用 `for` 属性指向 input 的 `id`，点击 label 文字也能激活输入框  
```html  
<label for="email">邮箱</label>  
<input type="email" id="email" name="email" />  
```
5. **id 在同一页面中必须唯一**，class 可以重复使用
6. **不要用 HTML 标签来控制样式**（如用 `<br>` 制造间距、用 `<table>` 做非表格布局），样式交给 CSS 处理

### CSS 注意事项

1. **选择器优先级（specificity）**：当多条规则同时作用于一个元素时，优先级高的规则生效  
优先级从高到低：

  - `!important`（尽量不用）
  - 内联样式（`style=""`）
  - ID 选择器（`#id`）
  - 类选择器（`.class`）、属性选择器、伪类
  - 标签选择器（`div`）、伪元素  
```css  
/* 优先级低 */  
p { color: black; }  
/* 优先级高，覆盖上面 */  
.intro p { color: blue; }  
```
2. **盒模型加 box-sizing 避免宽度计算错误**  
```css
*,
*::before,
*::after {  
  box-sizing: border-box;  
}  
```
3. **外边距折叠（margin collapse）**：相邻的两个块级元素，上下 margin 会合并取较大值，而非相加  
```css  
/* 上面元素 margin-bottom: 20px，下面元素 margin-top: 30px */  
/* 实际间距是 30px，不是 50px */  
```
4. **z-index 只对 position 不为 static 的元素有效**  
```css  
/* 无效 */  
.box {  
  z-index: 999; /* position 是 static，z-index 不起作用 */  
}  
/* 有效 */  
.box {  
  position: relative;  
  z-index: 999;  
}  
```
5. **不要滥用 `!important`**，会破坏样式的可维护性，难以调试
6. **Flexbox 和 Grid 中的子元素**，`float` 和 `vertical-align` 会失效，不要混用
7. **颜色对比度**：文字颜色与背景颜色对比度要足够大，保证可读性（尤其是浅灰文字在白色背景上）
8. **font-family 要写备用字体**  
```css  
/* 从左到右依次尝试，最后写通用字体族 */  
font-family: "PingFang SC", "Hiragino Sans GB", "微软雅黑", sans-serif;  
```

### 调试技巧

1. 打开浏览器开发者工具（按 F12），在 Elements 面板查看 HTML 结构和 CSS 样式
2. 用 `outline: 1px solid red` 给元素加轮廓线，方便查看元素位置和大小（不占空间）
3. 在 Styles 面板可以实时修改 CSS 查看效果

---

---

## 常见陷阱

### 陷阱：CSS 盒模型导致元素实际宽度超出预期

**现象：** 设置 `width: 200px` 的元素比相邻元素宽，或加上 `padding` 后元素溢出父容器。

**原因：** 默认盒模型（`box-sizing: content-box`）中，`width` 只是内容区宽度，`padding` 和 `border` 会额外增加元素的实际占用宽度。200px 宽 + 20px padding × 2 = 实际 240px。

**解决：** 全局设置 `box-sizing: border-box`，使 `width` 包含 padding 和 border，更符合直觉。

```css
*, *::before, *::after {
  box-sizing: border-box;
}

```

### 陷阱：Flexbox / Grid 子元素 `margin: auto` 失效

**现象：** 在 Flex 或 Grid 容器的子元素上设置 `margin: 0 auto`，子元素没有居中，仍然靠左。

**原因：** Flex 容器默认 `align-items: stretch`，子元素已被拉伸对齐，`margin: auto` 在交叉轴上被覆盖。水平居中应使用容器的 `justify-content: center`，或子元素的 `margin: auto`（在 Flex 中，`margin: auto` 会吸收剩余空间，可实现居中）。

**解决：** 区分场景使用正确的居中方式。

```css
/* 方式一：容器控制 */
.container {
  display: flex;
  justify-content: center;   /* 主轴居中 */
  align-items: center;       /* 交叉轴居中 */
}

/* 方式二：子元素 margin auto（Flex 中有效） */
.child { margin: auto; }

```

### 陷阱：`position: relative` 父容器忘记设置，子元素绝对定位跑偏

**现象：** 给子元素设置 `position: absolute; top: 0; left: 0` 后，子元素跑到了页面左上角而不是父容器左上角。

**原因：** `position: absolute` 是相对于最近的"已定位祖先"（`position` 不为 `static` 的祖先）来定位的，如果没有，就相对于 `<html>` 根元素。

**解决：** 给父容器添加 `position: relative`（不改变布局流，只建立定位上下文）。

```css
.parent {
  position: relative; /* 建立定位上下文 */
}
.child {
  position: absolute;
  top: 0;
  right: 0;
}

```

---

## 参见

- [JavaScript入门](https://blog.vercanti.com/javascript-ru-men/)
- [Vue3入门](https://blog.vercanti.com/vue-3-ru-men-zhi-nan/)
- [TailwindCSS完全指南](https://blog.vercanti.com/tailwindcss-wan-quan-zhi-nan/)
- [CSS动画完全指南](https://blog.vercanti.com/css-dong-hua-wan-quan-zhi-nan/)