# 網頁設計入門指南
## 今日目標
這堂課將手把手帶你認識 **網頁設計基本 3 要素**:
- HTML
- CSS
- JavaScript (JS)
親手做出一個**互動式個人介紹頁面**,包含:
- 你的名字、照片與技能標籤
- 漂亮的 CSS 樣式
- 可以切換深色模式的按鈕
- 點擊技能標籤會有動態效果
最後將網頁發佈到網路上,就可以將你的網頁分享給其他人啦~
---
## 第一部分:暖身
- ### 網站的構成三要素
想像你在蓋一棟房子:
```
🏗️ HTML → 骨架(牆壁、門、窗戶在哪裡)
🎨 CSS → 裝潢(顏色、大小、字型、間距)
⚙️ JS → 電器(讓東西會動、會互動)
```
三者分工合作,少了任何一個,網頁就不完整。
- ### 開發人員工具(DevTools)
內建於瀏覽器中的網頁開發測試與除錯工具,以下是開啟方式:
**Windows/Linux:**
- `F12` 或 `Ctrl` + `Shift` + `I`
- 點右鍵 -> 「檢查 (Inspect)」
**macOS:**
- `Cmd` + `Option` + `I`
- 點右鍵 -> 「檢閱元件」
>注意:若使用 Safari 須先進行額外設定
>1. 選單列點選 Safari → 設定
>1. 切換到 「進階」 頁籤
>1. 勾選底部的 「顯示網頁開發者功能」
---
## 第二部分:HTML — 蓋骨架
- ### HTML 的邏輯:元素(element)
```html
<標籤名稱>內容</標籤名稱>
```
- 用「標籤」來描述內容的用途,形成一個**元素**
- 標籤通常有**開頭**和**結尾**,把內容夾在中間
- 內容可以包含**多個元素**。
---
- ### 實作一:建立完整 HTML 結構
打開 VS Code 創建 `index.html` 檔案,並將以下程式碼貼上:
```html=
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Personal Website</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<h1>My Personal Website</h1>
<button id="darkToggle">🌙 深色模式</button>
<div class="card">
<img src="https://i.pravatar.cc/150?" alt="我的照片">
<h1>你的名字</h1>
<p class="bio">熱愛設計的工程師</p>
<h3>Skill Tags</h3>
<ul class="skills">
<li class="skill-tag">Python</li>
<li class="skill-tag">C++</li>
<li class="skill-tag">UI 設計</li>
</ul>
<p class="skill-msg"></p>
<a href="mailto:your@email.com" class="btn">聯絡我</a>
</div>
</body>
</html>
```
在檔案總管點開 `index.html` 檔案,進入瀏覽器後就能看到文字和圖片出現了!
:::info
*若想要在修改程式碼的過程中,即時更新網頁狀態,可以在 VS Code 的延伸模組中安裝 `Live Server`。*
:::
---
- ### DOM (Document Object Model)
瀏覽器把 HTML 解析後,轉換成一棵「可操作的樹狀結構」,CSS 和 Javascript 便能透過它尋找指定的元素並修改。
- #### HTML 結構:
<img src="https://hackmd.io/_uploads/SyjJgKs6Ze.png" width="90%" style="border: 1px solid black; border-radius: 8px;">
- #### DOM 示意圖:
<img src="https://hackmd.io/_uploads/ryeXZvqTbe.png" width="75%" style="border: 1px solid black; border-radius: 8px;">
- ### 標籤速查表
- #### 結構標籤:
| 標籤 | 用途 |
|------|------|
| `html` | 整個網頁的**根元素** |
| `head` | 網頁設定與資訊 |
| `body` | 使用者看到的內容 |
- #### 設定常用標籤:
| 標籤 | 用途 | 範例 |
|------|------|------|
| `title` | 網頁標題名稱 | `<title>標題</title>` |
| `link` | 連接外部資源 (如 CSS) | `<link rel="用途/關係" href="來源">` |
| `script` | 載入並執行 JavaScript | `<script src="來源"></script>` |
| `meta` | 其他設定 | `<meta 屬性="值">` |
- #### 內文常用標籤
| 標籤 | 用途 | 範例 |
|------|------|------|
| `<h1>` ~ `<h6>` | 標題(數字越大越小) | `<h1>大標題</h1>` |
| `<p>` | 段落文字 | `<p>這是一段文字</p>` |
| `<img>` | 圖片 | `<img src="圖片網址" alt="描述">` |
| `<a>` | 連結 | `<a href="網址">點我</a>` |
| `<button>` | 按鈕 | `<button>按我</button>` |
| `<ul>` + `<li>` | 無序清單 | `<ul><li>項目</li></ul>` |
| `<div>` | 容器(打包用) | `<div>...</div>` |
:::info
*所有標籤的完整說明可至 [MDN Web Docs](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements) 查看*
:::
- ### `class` 與 `id`
用來幫元素「標記身分」,讓你可以用 CSS 或 JavaScript 去選取它們。
```html
<div class="card"> <!-- 可重複使用-->
<button id="darkBtn"> <!-- 唯一識別 -->
```
- `class` → 可重複使用的「分類標籤」
- `id` → 全頁唯一的「身份證」
---
## 第三部分:CSS — 上色與裝潢
現在雖然已經有了基本的骨架,但出來的結果還很醜!!沒關係,接下來交給裝潢大師 CSS 來進行美化和排版~
- ### CSS 的語法邏輯
```css
選擇器 {
屬性: 值;
}
```
**選擇器類別:**
| 類別 | 範例 | 結果 |
|-----------|----------|------|
| 標籤 | `h1 {...}` | 所有 `<h1>` 標籤 |
| class | `.card {...}` | class="card" | `.card { padding: 20px; }` |
| id | `#darkToggle {...}` | id="darkToggle" |
| 虛擬類別 | `.card:hover {...}` | 游標停放的 card |
**多重條件選擇器:**
| 類別 | 寫法 | 範例 | 結果 |
|-----------|-----------|----------|------|
| 複合選擇器 | 相連 | `body.card {...}` | 標籤為 `<body>` **且** class="card" |
| 後代選擇器 | 空格隔開 | `.card h1 {...}` | class="card" **內容裡的** `<h1>` 標籤 |
---
- ### ✍️ 實作二:讓頁面好看起來
先在 `index.html` 的 `<head>` 內容中添加一行程式碼,讓他可以讀取 CSS 檔。
```html
<link rel="stylesheet" href="style.css">
```
接著創建 `style.css` 檔案,並將以下程式碼貼上:
:::spoiler 程式碼
```css=
/* ── 全域重置與字型 ── */
* {
box-sizing: border-box;
transition: background-color 0.3s, color 0.3s;
}
body {
background-color: #f0f4f8;
font-family: sans-serif;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 16px;
min-height: 100vh;
}
/* ── 深色模式切換按鈕 ── */
#darkToggle {
background: white;
border: 2px solid #e2e8f0;
border-radius: 8px;
padding: 8px 16px;
cursor: pointer;
font-size: 14px;
margin-bottom: 24px;
}
/* ── 卡片容器 ── */
.card {
background-color: white;
border-radius: 16px;
padding: 40px;
max-width: 420px;
width: 100%;
text-align: center;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
/* ── 頭像 ── */
.card img {
width: 120px;
height: 120px;
border-radius: 50%;
object-fit: cover;
margin-bottom: 16px;
}
/* ── 名字與介紹 ── */
.card h1 {
font-size: 28px;
color: #1a202c;
margin: 0 0 8px 0;
}
.bio {
color: #718096;
font-size: 16px;
margin-bottom: 24px;
}
/* ── 技能標籤 ── */
.skills {
list-style: none;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
margin: 0 0 16px 0;
}
.skill-tag {
background-color: #ebf4ff;
color: #3182ce;
padding: 6px 14px;
border-radius: 20px;
font-size: 14px;
cursor: pointer;
user-select: none;
}
.skill-tag:hover {
background-color: #bee3f8;
}
/* ── 被選中的技能標籤(JS 會加上這個 class) ── */
.skill-tag.active {
background-color: #3182ce;
color: white;
transform: scale(1.05);
}
/* ── 點擊提示文字 ── */
.skill-msg {
font-size: 14px;
color: #3182ce;
min-height: 20px;
margin-bottom: 12px;
}
/* ── 聯絡按鈕 ── */
.btn {
display: inline-block;
background-color: #3182ce;
color: white;
text-decoration: none;
padding: 12px 32px;
border-radius: 8px;
font-size: 16px;
margin-top: 8px;
}
.btn:hover {
background-color: #2b6cb0;
}
/* ── 深色模式(JS 會幫 body 加上 dark class) ── */
body.dark {
background-color: #1a202c;
}
body.dark .card {
background-color: #2d3748;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
}
body.dark h1 {
color: white;
}
body.dark .card h1 {
color: #f7fafc;
}
body.dark .card h3 {
color: #f7fafc;
}
body.dark .bio {
color: #a0aec0;
}
body.dark #darkToggle {
background: #2d3748;
color: #f7fafc;
border-color: #4a5568;
}
```
:::
可以嘗試刪除或修改一些屬性,觀察變化。
:::info
**注意**:`.skill-tag.active` 和 `body.dark` 這些樣式現在還沒有效果,因為需要 JS 來將元素動態加上對應的 class。**這就是 CSS 和 JS 合作的方式!**
:::
---
- ### CSS 核心概念說明
- #### 盒子模型(Box Model)
每個 HTML 元素都是一個盒子:

- margin -> 外距(元素與外界距離)
- border -> 邊框
- padding -> 內距(內容內側空間)
- 藍色部分為內容
- #### 顏色
在 CSS 中,顏色的常用寫法為十六進制的 RGB,以 `#RRGGBB` 的結構來表示。
每個顏色的範圍:`00 ~ FF`(0~255)
---
## 第四部分:JavaScript — 讓頁面動起來
- ### JS 是什麼?
如果你學過 Python,JS 的邏輯你基本也能看得懂——只是語法不一樣,而且 JS 是在**瀏覽器裡跑的**,可以直接操控網頁上的元素。
**python 寫法:**
```python
name = "Billy"
print("Hello, " + name)
```
**JavaScript 寫法:(幾乎一樣的邏輯!)**
```javascript
const name = "Billy";
console.log("Hello, " + name);
```
> *對 `const`, `let`, `var 三種變數型態的差別有興趣可以自行上網查。`*
---
- ### 核心概念:DOM 操作
JS 可以透過 DOM 的樹狀結構,**找到任何元素並修改它**。
**搜尋:**
```javascript
// 用 id 找元素(回傳單一元素)
document.getElementById("darkToggle");
// 用 class 找元素所有元素(回傳即時更新陣列)(較少使用)
document.getElementsByClassName('.skill-tag');
// 透過 CSS 方式找所有元素(回傳靜態陣列)
document.querySelectorAll(".skill-tag.active");
```
**修改:**
```javascript
// 修改文字內容
element.textContent = "新的文字";
// 移除元素
element.remove();
// 新增 / 移除 class(最常用!)
element.classList.add("active");
element.classList.remove("active");
element.classList.toggle("active"); // 有就移除,沒有就加上
```
---
- ### ✍️ 實作三:深色模式切換
先在 `index.html` 的 `<head>` 內容中添加一行程式碼,讓他可以讀取 JavaScript 檔。
```html
<script src="script.js" defer></script>
```
創建 `script.js` 檔案,並將以下程式碼貼上:
```javascript=
// 找到按鈕元素
const darkBtn = document.getElementById("darkToggle");
// 監聽點擊事件
darkBtn.addEventListener("click", function() {
// 切換 body 的 dark class
document.body.classList.toggle("dark");
// 更新按鈕文字
if (document.body.classList.contains("dark")) {
darkBtn.textContent = "☀️ 淺色模式";
} else {
darkBtn.textContent = "🌙 深色模式";
}
});
```
**試試看**:點擊「深色模式」按鈕,頁面應該要切換!
> **關鍵觀念**:JS 做的事很簡單——**幫元素加上或移除 class**。真正讓畫面改變的是 CSS 裡的 `body.dark` 規則。**CSS 負責「長什麼樣」,JS 負責「什麼時候變」**。
**語法補充:**
- `element.addEventListener(事件, 函式)`:監聽此元素上發生的事件,並執行對應函數。
- `function(參數) {...}`:匿名函式——直接定義函式,不需額外命名。
- `element.classList.contains("class")`:判斷此元素是否包含特定 class。
---
- ### ✍️ 實作四:點擊技能標籤互動
繼續在 `script.js` 新增以下程式碼:
```javascript=
// 找到所有卡片元素
const cards = document.querySelectorAll(".card");
// 對每一張卡片都加上事件監聽
cards.forEach(function(card) {
// 找到所有技能標籤與訊息元素
const skillTags = card.querySelectorAll(".skill-tag");
const skillMsg = card.querySelector(".skill-msg");
// 幫每一個標籤都加上點擊事件
skillTags.forEach(function(tag) {
tag.addEventListener("click", function() {
// 先移除所有標籤的 active class
skillTags.forEach(function(t) {
t.classList.remove("active");
});
// 幫被點擊的標籤加上 active class
tag.classList.add("active");
// 顯示提示訊息
skillMsg.textContent = "對「" + tag.textContent + "」有興趣!";
});
});
});
```
**試試看**:點擊不同的技能標籤,看看有什麼反應!
**語法補充:**
- `NodeList.forEach(函式)`:對 NodeList(`querySelectorAll` 回傳的陣列)中每個元素執行指定的函式。
---
## 第五部分:發布上線(GitHub Pages)
可參考前面社課的 [教材](https://hackmd.io/Ms_RrqttSpWe1_iXO-SLhA?view#建立你的-GitHub-Pages)
1. ### 建立 Repository
1. 進入 Repository 頁面
2. 點選 "New" 建立新儲存庫
3. 設定 Repository 名稱,並確認儲存庫為 Public
2. ### 上傳網站檔案
1. 點選 "uploading an existing file"
2. 上傳前面製作的三個檔案
3. ### 開啟 GitHub Pages 設定
1. 進入該專案的 "Settings" 頁面
2. 在左側選單點選 "Pages"
3. 在 "Build and deployment" 下的 Source 選擇 `Deploy from a branch`
4. 在 Branch 處選擇 `main` 並選擇 `/(root)` 資料夾,點選 "Save"
最後網址會是 `https://GitHub帳號.github.io/repository名稱`。
例如:https://boxun-shih.github.io/Website_Example/
---
## 程式碼參考範例
- https://github.com/xujk0217/xujk0217.github.io
- https://github.com/xujk0217/GDG-Member-Wall