---
# System prepended metadata

title: 四、CSS 與 JavaScript 整合入門

---

# 四、CSS 與 JavaScript 整合入門

## 4.1 HTML 與前端整合入門

### 前端三劍客的協作關係

在第一章我們曾介紹，現代網頁由三種技術構成：
- **HTML**：結構與內容（骨架）
- **CSS**：外觀與樣式（皮膚）
- **JavaScript**：互動與邏輯（大腦）

這三者不是獨立運作，而是緊密協作。

> 💡 比喻：
> - HTML = 房子的鋼筋水泥結構
> - CSS = 裝潢、油漆、家具風格
> - JavaScript = 智慧家庭系統（開關燈、自動溫控）

---

### 在 HTML 中引入 CSS 的三種方式

#### 1. 內嵌樣式 (Inline Style)

直接在標籤內使用 `style` 屬性：

```html
<p style="color: blue; font-size: 18px;">這是藍色文字</p>
```

> ⚠️ **不推薦**：難以維護，樣式與結構混在一起。

##### 完整範例
```htmlembedded=
<!DOCTYPE html>
<html lang="zh-Hant">

<head>
  <meta charset="UTF-8" />
  <title>我的網站</title>
</head>

<body>
  <p style="color: blue; font-size: 18px;">這是藍色文字</p>
</body>

</html>
```

##### 範例展示
![截圖 2026-01-07 下午3.26.32](https://hackmd.io/_uploads/H1vAqFsVbx.png)

---

#### 2. 內部樣式表 (Internal CSS)

在 `<head>` 區塊內使用 `<style>` 標籤：

##### 完整範例
```html
<!DOCTYPE html>
<html lang="zh-Hant">

<head>
  <meta charset="UTF-8" />
  <title>我的網站</title>
  <style>
    p {
      color: blue;
      font-size: 18px;
    }
  </style>
</head>

<body>
  <p>這是藍色文字</p>
</body>

</html>
```

> 💡 適合單頁小型網站或原型測試。

---

#### 3. 外部樣式表 (External CSS) - 推薦

將 CSS 獨立成 `.css` 檔案，再用 `<link>` 引入：

**index.html:**
```html
<head>
  <link rel="stylesheet" href="style.css">
</head>
```

**style.css:**
```css
p {
  color: blue;
}
```

> ✅ **最佳實務**：結構與樣式分離，易於維護與重複使用。
##### 檔案結構
![具有兩份檔案](https://hackmd.io/_uploads/SJv6oYiNZx.png)

##### 範例截圖
![完整範例結構](https://hackmd.io/_uploads/S1QasFiE-g.png)

---

### 在 HTML 中引入 JavaScript 的方式

#### 1. 內嵌 JavaScript (Inline)

直接在標籤內使用事件屬性：

##### 完整範例
```html
<!DOCTYPE html>
<html lang="zh-Hant">

<head>
  <meta charset="UTF-8" />
  <title>我的網站</title>
</head>

<body>

  <body>
    <button onclick="alert('Hello!')">點我</button>
  </body>
</body>

</html>
```

> ⚠️ **不推薦**：邏輯分散，難以除錯與維護。


##### 範例截圖
![截圖 2026-01-07 下午3.32.32](https://hackmd.io/_uploads/H1pSntiVWl.png)

---

#### 2. 內部 JavaScript

在 HTML 內使用 `<script>` 標籤：

##### 完整範例
```html
<!DOCTYPE html>
<html lang="zh-Hant">

<head>
  <meta charset="UTF-8" />
  <title>我的網站</title>
</head>

<body>
  <button id="myBtn">點我</button>

  <script>
    document.getElementById('myBtn').onclick = function () {
      alert('Hello!');
    };
  </script>
</body>

</html>
```

---

#### 3. 外部 JavaScript - 推薦

將 JavaScript 獨立成 `.js` 檔案：

**index.html:**
```html
<body>
  <button id="myBtn">點我</button>
  <script src="script.js"></script>
</body>
```

**script.js:**
```javascript
document.getElementById('myBtn').addEventListener('click', function() {
  alert('Hello!');
});
```

> ✅ **最佳實務**：結構、樣式、邏輯完全分離。


##### 檔案結構
![截圖 2026-01-07 下午3.44.36](https://hackmd.io/_uploads/S1qXycjNZx.png)


##### 範例截圖
![截圖 2026-01-07 下午3.44.51](https://hackmd.io/_uploads/r1MNkcjV-x.png)



---

### 載入順序的重要性

1.  **CSS 放在 `<head>`**：確保網頁解析時就已經有樣式，避免「內容閃爍」。
2.  **JavaScript 放在 `<body>` 結尾**：確保 HTML 元素（DOM）已經載入完成，程式碼才能正確抓取並操作元素。


![截圖 2026-01-07 下午5.04.32](https://hackmd.io/_uploads/SJJrGsiVWe.png)



<br/>

## 4.2 基礎 CSS 入門學習

### CSS 語法結構

```css
選擇器 {
  屬性: 值;
  屬性: 值;
}
```

**範例：**
```css
h1 {
  color: red;
  font-size: 24px;
}
```

### 常見選擇器

1.  **元素選擇器 (Tag Selector)**：選取所有特定標籤。
    ```css
    p { color: gray; }
    ```
2.  **類別選擇器 (Class Selector)**：選取有特定 Class 的元素 (最常用)。
    ```css
    .highlight { background-color: yellow; }
    ```
3.  **ID 選擇器 (ID Selector)**：選取特定 ID 的唯獨元素。
    ```css
    #header { padding: 20px; }
    ```

### 盒模型 (Box Model)

每個元素都是一個盒子，由內而外包含：
1.  **Content** (內容)
2.  **Padding** (內距)
3.  **Border** (邊框)
4.  **Margin** (外距)


![盒模型 (Box Model)](https://hackmd.io/_uploads/SkiFOoj4be.jpg)

```css
.card {
  width: 300px;
  padding: 20px;      /* 內容與邊框的距離 */
  border: 1px solid #ddd;
  margin: 30px;       /* 盒子與外部的距離 */
}
```

#### 2. 盒子的尺寸計算：`box-sizing`

這是一個新手常遇到的坑：**設定了寬度 100px，加了內距 20px，結果盒子變成了 140px？**

這是因為 CSS 預設的計算方式 (`content-box`) 是：
> 總寬度 = width + padding + border

為了直覺好管理，現代網頁開發習慣將它改為 `border-box`：
> 總寬度 = width (padding 和 border 會被包在裡面，不會撐大盒子)

**✅ 最佳實務：全域重置**
建議在所有 CSS 檔案的最開頭加上這段程式碼：

```css
*, *::before, *::after {
  box-sizing: border-box; /* 讓你設多少寬度就是多少 */
}
```

![box-sizing](https://hackmd.io/_uploads/SkFbsoiEZx.jpg)



### CSS 常用屬性與單位速查

在排版之前，我們先熟悉幾個最常用的 CSS 設定：

#### 1. 尺寸單位 (Units)
網頁上不只有 `px` (像素)，還有依比例縮放的單位。

*   **`px` (像素)**：絕對單位，固定大小。適合：邊框粗細、最小寬度。
    *   `width: 200px;`
*   **`%` (百分比)**：主要相對於**父元素**的大小。適合：響應式寬度。
    *   `width: 50%;` (父元素的一半寬)
*   **`rem`**：相對於**根元素 (html)** 的字體大小。適合：字體大小、間距。
    *   `font-size: 1.2rem;` (若預設是 16px，1.2rem 就是 19.2px)

> 💡 **小撇步**：現在主流建議字體大小用 `rem`，這樣使用者調整瀏覽器預設字體時，網頁才會跟著放大，符合無障礙設計！

#### 2. 文字排版 (Typography)
讓文字更好讀的關鍵屬性。

```css
p {
  font-family: Arial, sans-serif; /* 字體：先找 Arial，沒有就用系統無襯線字體 */
  font-weight: bold;              /* 粗細：bold (粗體) 或 normal (正常) */
  line-height: 1.6;               /* 行高：建議 1.5 ~ 1.8 倍，太擠很難讀 */
  text-align: center;             /* 對齊：left (預設), center, right */
  color: #333;                    /* 顏色：建議不要用純黑 (#000)，用深灰較不刺眼 */
}
```

#### 3. 背景處理 (Background)

```css
.banner {
  background-color: #f0f0f0;            /* 背景色 */
  background-image: url('bg.jpg');      /* 背景圖 */
  background-size: cover;               /* ⭐️ 重要：讓圖片自動填滿且裁切 */
  background-position: center;          /* 圖片居中 */
}
```

#### 4. 邊框與游標 (Border & Cursor)

讓介面更精緻、互動性更好的細節：

*   **`border-radius` (圓角)**：讓方形變圓潤。
    *   `border-radius: 10px;` (微圓角)
    *   `border-radius: 50%;` (變圓形，常用於頭像)
*   **`cursor` (游標型態)**：當滑鼠移上去時的樣子。
    *   `cursor: pointer;` (變成手指形狀，表示可點擊，按鈕必備！)
    *   `cursor: not-allowed;` (禁止符號)

#### 5. 顯示模式 (Display)
HTML 標籤天生有兩種個性：

| 模式 | 特性 | 常見標籤 |
| :--- | :--- | :--- |
| **`block` (區塊)** | 獨佔一行，可以設定寬高 | `<div>`, `<p>`, `<h1>`, `<section>` |
| **`inline` (行內)** | 和其他人擠在同一行，**不能**設定寬高 | `<span>`, `<a>` |
| **`inline-block`** | 擠在同一行，但**可以**設定寬高 | `<img>`, `<button>` |
| **`none` (隱藏)** | 元素完全消失，不佔據空間 | (常用於互動顯示/隱藏) |

> 如果你想讓 `<a>` 連結變成一顆有寬高的大按鈕，記得設 `display: inline-block;` 或 `display: block;`！

```css
a.button {
  display: inline-block; /* 這樣才能設定 padding 和 width */
  padding: 10px 20px;
}
```


### Flexbox 排版基礎

**Flexbox (彈性盒模型)** 是現代 CSS 最重要的排版系統，專門用來解決「對齊」與「分佈」的問題。

要精通 Flexbox，你只需要掌握兩個角色和三個關鍵屬性。

#### 1. 兩個角色：容器與項目

*   **Flex Container (容器)**：外層的爸爸。只要設了 `display: flex;`，它就變成了 Flex 容器。
*   **Flex Item (項目)**：內層的兒子。容器內的**直屬**子元素會自動變成 Flex 項目，聽從容器的指揮進行排列。

#### 2. 決定排列方向：`flex-direction` (主軸方向)

Flexbox 預設是「橫向」排列，但你可以改成「直向」。這條排列的線，我們稱為**主軸 (Main Axis)**。

```css
.container {
  display: flex;
  
  /* 決定主軸方向 */
  flex-direction: row;          /* (預設值) 橫向排列：從左到右 */
  /* flex-direction: column;       直向排列：從上到下 */
  /* flex-direction: row-reverse;  橫向反轉：從右到左 */
}
```

> 💡 **重要觀念**：「主軸」是你設定的方向，「交錯軸」則是跟它垂直的那個方向。

#### 3. 主軸對齊：`justify-content`

決定項目在「主軸」上如何分佈 (例如：靠左、居中、分散)。

```css
.container {
  display: flex;
  justify-content: flex-start;    /* (預設) 靠起點對齊 (通常是左邊) */
  justify-content: center;        /* 居中對齊 */
  justify-content: flex-end;      /* 靠終點對齊 (通常是右邊) */
  justify-content: space-between; /* 左右貼齊邊緣，中間平均分配空白 (導覽列最常用！) */
  justify-content: space-around;  /* 每個項目周圍都有相等空白 */
}
```

#### 4. 交錯軸對齊：`align-items`

決定項目在「交錯軸」(垂直於主軸的方向) 上如何對齊 (例如：上下置中)。

```css
.container {
  display: flex;
  align-items: stretch;     /* (預設) 拉伸：自動填滿容器高度 */
  align-items: center;      /* 置中：垂直居中 (最常用！) */
  align-items: flex-start;  /* 靠上對齊 */
  align-items: flex-end;    /* 靠下對齊 */
}
```

#### 5. 自動換行：`flex-wrap`

預設情況下，Flexbox 會強迫所有項目擠在同一行 (就算擠爆也不換行)。如果你希望滿了就自動換到下一行，要開啟這個屬性。

```css
.container {
  display: flex;
  flex-wrap: nowrap; /* (預設) 不換行，硬擠 */
  flex-wrap: wrap;   /* 自動換行，適合做卡片列表 */
}
```

#### 🚀 Flexbox 速查範例：完美置中

這是面試最常考、開發最常用的程式碼：

```css
.center-box {
  display: flex;
  justify-content: center; /* 水平置中 */
  align-items: center;     /* 垂直置中 */
  height: 300px;           /* 需有高度才看得到垂直置中效果 */
}
```



<br/>

## 4.3 基礎 JavaScript 入門學習

### JavaScript 能做什麼？
-   **DOM 操作**：修改網頁內容或樣式。
-   **事件監聽**：偵測點擊、輸入、滾動等行為。

### 變數宣告

推薦使用 `const` (常數) 與 `let` (變數)。

```javascript
const myName = "小明";  // 不會變的資料
let count = 0;          // 會變動的資料
```

### 函式 (Functions) 與 邏輯控制

要想寫出有「邏輯」的程式，這兩個觀念必不可少。

#### 1. 函式 (Function)
將一段程式碼包起來，改個名字，以便重複使用。

```javascript
function sayHello() {
  alert("你好！");
}

// 呼叫函式
sayHello();
```

#### 2. 條件判斷 (If...Else)
讓程式根據情況做不同的事。

```javascript
if (count > 10) {
  console.log("數量太多了！");
} else {
  console.log("數量正常");
}
```

### 選取 DOM 元素

```javascript
// 透過 ID 選取
const title = document.getElementById('title');

// 透過 CSS 選擇器選取 (推薦)
const btn = document.querySelector('.btn-primary');
```

### 修改內容與樣式

```javascript
title.textContent = "Hello World";      // 修改文字
title.style.color = "red";             // 修改樣式 (不推薦大量使用)

// Class 操作 (推薦)
title.classList.add("active");         // 新增 Class
title.classList.remove("active");      // 移除 Class
title.classList.toggle("active");      // 切換 (有就移除，無就新增)
title.classList.contains("active");    // 檢查是否有該 Class (回傳 true/false)

// 表單輸入值
// 假設有個 <input id="name">
const input = document.getElementById('name');
console.log(input.value);              // 取得使用者輸入的內容
```

### 動態新增與移除元素 (Dynamic DOM)

進階應用常用到：用程式碼「無中生有」做出 HTML。

```javascript
// 1. 建立新元素
const newDiv = document.createElement('div');
newDiv.textContent = "我是新來的！";

// 2. 放入畫面中 (加入到 body 的最後面)
document.body.appendChild(newDiv);

// 3. 移除元素
newDiv.remove();
```

### 事件監聽 (Event Listener)

```javascript
btn.addEventListener('click', function() {
  console.log("按鈕被點擊了！");
});
```

<br/>

## 4.4 前端進階整合應用

現在我們將所學整合，實作兩個常見的小專案。

### 專案一：互動式問答卡片

#### 功能需求
- 顯示一個問題與「顯示答案」按鈕。
- 點擊按鈕後，展開答案區域，並將按鈕文字改為「隱藏答案」。
- 再次點擊則收起答案。

**HTML:**
```html
<div class="qa-card">
  <h3>HTML 是什麼縮寫？</h3>
  <button id="toggleBtn">顯示答案</button>
  <div id="answer" class="hidden">
    <p>HyperText Markup Language</p>
  </div>
</div>
```

**CSS:**
```css
.qa-card {
  border: 1px solid #ccc;
  padding: 20px;
  border-radius: 8px;
  width: 300px;
}
.hidden {
  display: none; /* 隱藏元素 */
}
```

**JavaScript:**
```javascript
const btn = document.getElementById('toggleBtn');
const answer = document.getElementById('answer');

btn.addEventListener('click', function() {
  // 切換 hidden class (有就移除，無就新增)
  answer.classList.toggle('hidden');

  // 根據狀態修改按鈕文字
  if (answer.classList.contains('hidden')) {
    btn.textContent = '顯示答案';
  } else {
    btn.textContent = '隱藏答案';
  }
});
```



| 點擊前 | 點擊後 |
| -------- | -------- |
| ![截圖 2026-01-07 下午5.53.49](https://hackmd.io/_uploads/ByFUpsi4Wl.png)     | ![截圖 2026-01-07 下午5.54.00](https://hackmd.io/_uploads/B1YU6sj4Zg.png)     |




---

### 專案二：動態待辦清單 (Todo List)

比起前一個專案，這個專案需要動態「新增」與「刪除」HTML 元素。

> 💡 這是學習 DOM 操作最重要的練習之一！

**HTML:**
```html
<div class="todo-app">
  <h2>我的待辦清單</h2>
  <div class="input-group">
    <input type="text" id="itemInput" placeholder="輸入待辦事項...">
    <button id="addBtn">新增</button>
  </div>
  <ul id="list">
    <!-- JavaScript 會將項目加在這裡 -->
  </ul>
</div>
```

**CSS:**
```css
.todo-app {
  width: 400px;
  margin: 20px auto;
  padding: 20px;
  border: 1px solid #eee;
  border-radius: 10px;
}
.list-item {
  display: flex;
  justify-content: space-between; /* 文字靠左，按鈕靠右 */
  padding: 10px;
  border-bottom: 1px solid #eee;
}
.delete-btn {
  background-color: #ff4d4d;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
```

**JavaScript:**
```javascript
// 1. 選取元素
const input = document.getElementById('itemInput');
const addBtn = document.getElementById('addBtn');
const list = document.getElementById('list');

// 2. 定義「新增項目」的函式
function addItem() {
  const text = input.value.trim(); // 取得輸入內容並去除空白

  // 如果內容是空的，不執行
  if (text === "") {
    alert("請輸入內容！");
    return;
  }

  // A. 建立新的 li 元素
  const li = document.createElement('li');
  li.className = 'list-item';

  // B. 建立內容文字
  const span = document.createElement('span');
  span.textContent = text;
  
  // 點擊文字可以切換「完成」樣式
  span.addEventListener('click', function() {
    span.style.textDecoration = 
      span.style.textDecoration === 'line-through' ? 'none' : 'line-through';
  });

  // C. 建立刪除按鈕
  const delBtn = document.createElement('button');
  delBtn.textContent = '刪除';
  delBtn.className = 'delete-btn';

  // 賦予刪除功能
  delBtn.addEventListener('click', function() {
    li.remove(); // 移除這個 li 元素
  });

  // D. 組裝元素 (把 span 和 button 放進 li)
  li.appendChild(span);
  li.appendChild(delBtn);

  // E. 把 li 放進清單中
  list.appendChild(li);

  // F. 清空輸入框
  input.value = "";
  input.focus();
}

// 3. 綁定事件
addBtn.addEventListener('click', addItem);

// 讓 Enter 鍵也能新增
input.addEventListener('keypress', function(e) {
  if (e.key === 'Enter') {
    addItem();
  }
});
```


| 操作前 | 操作後 |
| -------- | -------- |
| ![截圖 2026-01-07 下午5.56.12](https://hackmd.io/_uploads/HkfeRjsV-g.png)     | ![截圖 2026-01-07 下午5.56.26](https://hackmd.io/_uploads/SyXlRosNZe.png)     |




---

### 最佳實務總結

1.  **關注點分離**：HTML 負責結構，CSS 負責樣式，JS 負責邏輯。
2.  **避免 innerHTML**：使用 `createElement` 和 `textContent` 更安全且效能更好，也能保留事件監聽器。
3.  **使用 Class 切換樣式**：盡量不要用 JS 直接改 `style`，而是透過 `classList.toggle()` 來切換 CSS class。

<br/>

## 本章練習題

**1. 在網頁開發的前端三劍客中，負責處理「互動與邏輯」的是哪一項技術？**
- A) HTML
- B) CSS
- C) JavaScript
- D) SQL

<details>
<summary>點選查看答案</summary>
答案: C) JavaScript

**解析：**
HTML 負責結構，CSS 負責外觀樣式，JavaScript 負責互動與邏輯控制。SQL 則是資料庫查詢語言，屬於後端範疇。
</details>

**2. 在 CSS 盒模型 (Box Model) 中，位於「內容 (Content)」與「邊框 (Border)」之間的區域稱為什麼？**
- A) Margin (外距)
- B) Padding (內距)
- C) Outline (輪廓)
- D) Width (寬度)

<details>
<summary>點選查看答案</summary>
答案: B) Padding (內距)

**解析：**
由內而外的順序為：Content (內容) -> Padding (內距) -> Border (邊框) -> Margin (外距)。
</details>

**3. 若要選取 HTML 中 `<div id="header">` 這個元素，應該使用哪一個 CSS 選擇器？**
- A) `.header`
- B) `header`
- C) `*header`
- D) `#header`

<details>
<summary>點選查看答案</summary>
答案: D) `#header`

**解析：**
- `#` 用於 ID 選擇器 (對應 `id=""`)
- `.` 用於類別選擇器 (對應 `class=""`)
- 無符號直接寫標籤名用於元素選擇器
</details>

**4. 在 JavaScript 中，建議使用哪一種方式來監聽按鈕的點擊事件？**
- A) 在 HTML 中寫 `<button onclick="...">`
- B) 在 CSS 中寫 `button:active { ... }`
- C) 使用 `element.addEventListener('click', ...)`
- D) 使用 `element.click = ...`

<details>
<summary>點選查看答案</summary>
答案: C) 使用 `element.addEventListener('click', ...)`

**解析：**
- A) 是內嵌寫法，不推薦。
- B) 是 CSS 偽類，只能改變樣式，不能執行邏輯。
- C) 是標準且推薦的事件監聽方式，可同時綁定多個事件且結構分離。
</details>

**5. 若要使用 JavaScript 動態建立一個新的 `<div>` 元素，應該使用哪個方法？**
- A) `document.createElement('div')`
- B) `document.newElement('div')`
- C) `document.add('div')`
- D) `document.make('div')`

<details>
<summary>點選查看答案</summary>
答案: A) `document.createElement('div')`

**解析：**
`document.createElement(tagName)` 是標準的 DOM API，用於建立新的元素節點。
</details>

**6. 為了符合無障礙設計並讓文字大小能隨瀏覽器設定縮放，建議使用哪種單位來設定 `font-size`？**
- A) px (像素)
- B) rem
- C) cm (公分)
- D) vh (視窗高度)

<details>
<summary>點選查看答案</summary>
答案: B) rem

**解析：**
`rem` 是相對於根元素 (root element) 的字體大小，能響應使用者在瀏覽器設定的預設字體大小，是目前最推薦的文字單位。
</details>

**7. 若希望某個元素在網頁上「完全消失」且「不佔據任何空間」，應設定什麼 CSS？**
- A) `opacity: 0;` (透明度為 0)
- B) `visibility: hidden;` (隱藏可見度)
- C) `display: none;` (不顯示)
- D) `background-color: transparent;` (背景透明)

<details>
<summary>點選查看答案</summary>
答案: C) `display: none;`

**解析：**
- `display: none;` 會讓元素從排版中完全移除，不佔空間。
- `opacity: 0` 和 `visibility: hidden` 雖然看不見，但元素原本的位置仍會被保留 (佔空間)。
</details>

**8. 在 `display: flex;` 的容器中，若要將子元素「水平置中」排列，應使用哪個屬性？**
- A) `align-items: center;`
- B) `text-align: center;`
- C) `padding: center;`
- D) `justify-content: center;`

<details>
<summary>點選查看答案</summary>
答案: D) `justify-content: center;`

**解析：**
在預設的 Flex 模式下 (橫向排列)，`justify-content` 控制主軸 (水平) 的對齊，`align-items` 控制交錯軸 (垂直) 的對齊。
</details>

**9. 在 JavaScript 中，若宣告一個變數後「不打算」也「不應該」再修改其數值，應使用哪個關鍵字？**
- A) `var`
- B) `let`
- C) `const`
- D) `static`

<details>
<summary>點選查看答案</summary>
答案: C) `const`

**解析：**
`const` (constant) 用於宣告常數，一旦賦值後就不能再重新賦值 (Reassign)，這能提高程式的穩定性與可讀性。
</details>

**10. 若要製作一個按鈕，點擊時能「切換」選單的顯示與隱藏狀態 (有就移除 class，沒有就新增)，最推薦使用哪個方法？**
- A) `classList.add()`
- B) `classList.remove()`
- C) `classList.toggle()`
- D) `classList.switch()`

<details>
<summary>點選查看答案</summary>
答案: C) `classList.toggle()`

**解析：**
`classList.toggle('className')` 會自動偵測：若元素已有該 class 則移除，若沒有則新增，非常適合用於開關式 (On/Off) 的互動功能。
</details>
