RWD 網頁¶
開始之前¶
任務目標
在這個章節中,我們會完成:
- 了解 RWD 網頁設計的概念與重要性
- 深入理解 Bootstrap Grid 系統
- 優化文章列表與詳細頁面的響應式設計
- 學習響應式設計的測試方法
什麼是 RWD?¶
RWD (Responsive Web Design,響應式網頁設計) 是一種網頁設計方法,讓網站能夠自動適應不同裝置的螢幕尺寸和解析度。
為什麼需要 RWD?¶
| 原因 | 說明 |
|---|---|
| 多裝置時代 | 使用者可能用手機、平板、電腦瀏覽網站 |
| 提升使用體驗 | 不需要縮放或左右滑動就能閱讀內容 |
| SEO 優化 | Google 偏好響應式網站 |
| 維護成本低 | 不需要維護多個版本的網站 |
| 提高轉換率 | 好的行動體驗能提高使用者停留時間 |
RWD 的三大核心技術¶
1. Fluid Grid(流動格線)¶
使用百分比而非固定像素來定義寬度:
/* 傳統固定寬度 */
.container {
width: 960px;
}
/* 響應式流動寬度 */
.container {
width: 100%;
max-width: 1200px;
}
2. Flexible Images(彈性圖片)¶
讓圖片能根據容器大小縮放:
3. Media Queries(媒體查詢)¶
根據螢幕尺寸套用不同的 CSS 樣式:
/* 小螢幕 */
@media (max-width: 767px) {
.sidebar {
display: none;
}
}
/* 大螢幕 */
@media (min-width: 768px) {
.sidebar {
display: block;
}
}
Viewport 設定
要讓 RWD 正常運作,必須在 HTML 的 <head> 中加入 viewport meta tag:
這行設定告訴瀏覽器:
width=device-width: 網頁寬度等於裝置寬度initial-scale=1.0: 初始縮放比例為 1:1
我們在 templates/base.html 中已經加入了這個設定。
Bootstrap Grid 系統¶
Bootstrap 使用 12 欄位格線系統 來實現響應式佈局,這是 Bootstrap 最強大的功能之一。
Grid 基本結構¶
<div class="container"> <!-- (1)! -->
<div class="row"> <!-- (2)! -->
<div class="col-md-6">欄位 1</div> <!-- (3)! -->
<div class="col-md-6">欄位 2</div>
</div>
</div>
- 容器: 固定寬度(container) 或 全寬(container-fluid)
- 列: 包含欄位的橫排
- 欄位: 內容區塊,總和為 12
斷點 (Breakpoints)¶
Bootstrap 5 定義了六個響應式斷點:
| 斷點 | Class 前綴 | 螢幕寬度 | 裝置類型 |
|---|---|---|---|
| Extra small | (無) | <576px | 手機 (直向) |
| Small | sm |
≥576px | 手機 (橫向) |
| Medium | md |
≥768px | 平板 |
| Large | lg |
≥992px | 桌機 |
| Extra large | xl |
≥1200px | 大桌機 |
| Extra extra large | xxl |
≥1400px | 超大桌機 |
Grid 使用範例¶
相同寬度欄位¶
<div class="row">
<div class="col">欄位 1</div>
<div class="col">欄位 2</div>
<div class="col">欄位 3</div>
</div>
三個欄位會自動平分空間(各佔 4 欄)。
指定欄位寬度¶
響應式欄位¶
<div class="row">
<div class="col-12 col-md-6 col-lg-4">
<!-- 手機: 12 欄 (全寬)
平板: 6 欄 (半寬)
桌機: 4 欄 (三分之一) -->
</div>
</div>
Grid Class 命名規則
col-{breakpoint}-{columns}
col-12: 所有尺寸都佔 12 欄(全寬)col-md-6: 中等螢幕以上佔 6 欄col-lg-4: 大螢幕以上佔 4 欄
沒有指定的斷點會使用較小斷點的設定。
實際體驗 Grid 系統¶
讓我們建立一個完整的 HTML 檔案,直接在瀏覽器中體驗 Bootstrap Grid 的響應式效果:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Bootstrap Grid 系統展示" />
<meta name="keywords" content="Bootstrap, Grid, RWD" />
<title>Bootstrap Grid 系統展示</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet" />
<style>
.demo-box {
background-color: #0d6efd;
color: white;
padding: 20px;
margin-bottom: 15px;
border-radius: 5px;
text-align: center;
font-weight: bold;
}
.demo-box-secondary {
background-color: #6c757d;
}
.demo-box-success {
background-color: #198754;
}
.demo-box-warning {
background-color: #ffc107;
color: #000;
}
</style>
</head>
<body>
<div class="container my-5">
<h1 class="text-center mb-5">
Bootstrap Grid 系統展示
</h1>
<p class="text-center text-muted mb-4">
試著調整瀏覽器視窗大小,觀察欄位如何自動調整!
</p>
<!-- 範例 1: 相同寬度 -->
<h2 class="mb-3">
範例 1: 自動平分欄位
</h2>
<div class="row mb-5">
<div class="col">
<div class="demo-box">
欄位 1
</div>
</div>
<div class="col">
<div class="demo-box demo-box-secondary">
欄位 2
</div>
</div>
<div class="col">
<div class="demo-box demo-box-success">
欄位 3
</div>
</div>
</div>
<!-- 範例 2: 固定欄位寬度 -->
<h2 class="mb-3">
範例 2: 主內容 + 側邊欄 (8:4)
</h2>
<div class="row mb-5">
<div class="col-8">
<div class="demo-box">
主要內容 (8/12)
</div>
</div>
<div class="col-4">
<div class="demo-box demo-box-secondary">
側邊欄 (4/12)
</div>
</div>
</div>
<!-- 範例 3: 響應式欄位 -->
<h2 class="mb-3">
範例 3: 響應式卡片網格
</h2>
<p class="text-muted">
手機: 1 欄 | 平板: 2 欄 | 桌機: 4 欄
</p>
<div class="row mb-5">
<div class="col-12 col-md-6 col-lg-3">
<div class="demo-box">
卡片 1
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="demo-box demo-box-secondary">
卡片 2
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="demo-box demo-box-success">
卡片 3
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="demo-box demo-box-warning">
卡片 4
</div>
</div>
</div>
<!-- 範例 4: 文章卡片佈局 -->
<h2 class="mb-3">
範例 4: 文章列表佈局
</h2>
<p class="text-muted">
手機: 1 欄 | 小螢幕: 2 欄 | 桌機: 3 欄 | 大螨幕: 4 欄
</p>
<div class="row mb-5">
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">
文章標題 1
</h5>
<p class="card-text">
這是文章的簡短描述內容...
</p>
<a href="#" class="btn btn-primary btn-sm">閱讀更多</a>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">
文章標題 2
</h5>
<p class="card-text">
這是文章的簡短描述內容...
</p>
<a href="#" class="btn btn-primary btn-sm">閱讀更多</a>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">
文章標題 3
</h5>
<p class="card-text">
這是文章的簡短描述內容...
</p>
<a href="#" class="btn btn-primary btn-sm">閱讀更多</a>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">
文章標題 4
</h5>
<p class="card-text">
這是文章的簡短描述內容...
</p>
<a href="#" class="btn btn-primary btn-sm">閱讀更多</a>
</div>
</div>
</div>
</div>
<!-- 目前螢幕尺寸指示器 -->
<div class="alert alert-info text-center">
<strong>目前螢幕尺寸:</strong>
<span class="d-inline d-sm-none">Extra Small (<576px)</span>
<span class="d-none d-sm-inline d-md-none">Small (≥576px)</span>
<span class="d-none d-md-inline d-lg-none">Medium (≥768px)</span>
<span class="d-none d-lg-inline d-xl-none">Large (≥992px)</span>
<span class="d-none d-xl-inline d-xxl-none">Extra Large (≥1200px)</span>
<span class="d-none d-xxl-inline">Extra Extra Large (≥1400px)</span>
</div>
</div>
<!-- Bootstrap JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
如何使用這個範例
步驟:
- 複製上面的完整程式碼
- 建立一個新檔案
grid_demo.html - 貼上程式碼並儲存
- 用瀏覽器打開這個檔案
- 調整瀏覽器視窗大小,觀察欄位如何自動調整!
你會看到:
- 視窗寬度改變時,欄位會自動重新排列
- 底部的指示器會顯示目前的螢幕尺寸
- 不同範例展示了不同的 Grid 使用方式
這就是 RWD 的威力!一套程式碼,適應所有裝置。
優化文章卡片元件¶
讓我們進一步優化 article_card.html,加入更多響應式設計:
<div class="col-12 col-sm-6 col-md-6 col-lg-4 col-xl-3 mb-4"> <!-- (1)! -->
<div class="card h-100">
<div class="card-body d-flex flex-column"> <!-- (2)! -->
<h5 class="card-title">
{{ article.title }}
</h5>
<h6 class="card-subtitle mb-2 text-muted">
{{ article.author.name }}
</h6>
<p class="card-text flex-grow-1"> <!-- (3)! -->
{{ article.content|truncatewords:30 }}
</p>
</div>
<div class="card-footer bg-transparent">
<div class="d-flex justify-content-between align-items-center"> <!-- (4)! -->
<small class="text-muted">
{{ article.created_at|date:"Y-m-d" }} <!-- (5)! -->
</small>
<a href="{% url 'article_detail' article.id %}"
class="btn btn-primary btn-sm">
閱讀更多
</a>
</div>
</div>
</div>
</div>
- 響應式欄位設定: 手機 1 欄、小螢幕 2 欄、中螢幕 2 欄、大螢幕 3 欄、超大螢幕 4 欄
- 使用 Flexbox 垂直排列卡片內容
- 內容區塊自動擴展 (
flex-grow-1),推送按鈕到底部 - 使用 Flexbox 水平排列頁尾元素
- 在小螢幕上只顯示日期,不顯示時間
響應式佈局說明
不同螢幕尺寸的顯示效果:
| 螢幕尺寸 | 每列卡片數 | 欄位設定 | 裝置類型 |
|---|---|---|---|
| Extra small (<576px) | 1 欄 | col-12 |
手機直向 |
| Small (≥576px) | 2 欄 | col-sm-6 |
手機橫向 |
| Medium (≥768px) | 2 欄 | col-md-6 |
平板 |
| Large (≥992px) | 3 欄 | col-lg-4 |
桌機 |
| Extra large (≥1200px) | 4 欄 | col-xl-3 |
大桌機 |
這就是 col-12 col-sm-6 col-md-6 col-lg-4 col-xl-3 的完整含義:隨著螢幕變大,每列能容納的卡片數量逐漸增加,提供最佳的閱讀體驗。
優化文章詳細頁¶
優化 article_detail.html 的響應式設計,加入更多響應式調整:
{% extends "blog/base.html" %}
{% block title %}
{{ article.title }} - Django 大冒險
{% endblock title %}
{% block blog_content %}
<nav aria-label="breadcrumb" class="d-none d-md-block"> <!-- (1)! -->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'article_list' %}">文章列表</a>
</li>
<li class="breadcrumb-item active">
{{ article.title }}
</li>
</ol>
</nav>
<article class="card">
<div class="card-body">
<h1 class="card-title fs-3 fs-md-2 fs-lg-1"> <!-- (2)! -->
{{ article.title }}
</h1>
<div class="d-flex flex-column flex-md-row align-items-md-center mb-3 text-muted"> <!-- (3)! -->
<span class="me-md-3 mb-2 mb-md-0"> <!-- (4)! -->
<i class="bi bi-person"></i>
作者:{{ article.author.name }}
</span>
<span>
<i class="bi bi-calendar"></i>
發布時間:{{ article.created_at|date:"Y-m-d H:i" }}
</span>
</div>
{% if article.tags.exists %}
<div class="mb-3">
{% for tag in article.tags.all %}
<span class="badge bg-secondary me-1 mb-1">{{ tag.name }}</span> <!-- (5)! -->
{% endfor %}
</div>
{% endif %}
<hr />
<div class="article-content fs-6 fs-md-5"> <!-- (6)! -->
{{ article.content|linebreaks }}
</div>
</div>
<div class="card-footer bg-light">
<div class="d-flex justify-content-between align-items-center">
<a href="{% url 'article_list' %}"
class="btn btn-outline-secondary btn-sm">
<span class="d-none d-sm-inline"> <!-- (7)! -->
<i class="bi bi-arrow-left"></i> 返回列表
</span>
<span class="d-inline d-sm-none"> <!-- (8)! -->
<i class="bi bi-arrow-left"></i>
</span>
</a>
<small class="text-muted d-none d-md-inline"> <!-- (9)! -->
最後更新:{{ article.updated_at|date:"Y-m-d" }}
</small>
</div>
</div>
</article>
{% endblock blog_content %}
- 麵包屑在中螢幕以上才顯示
- 響應式標題大小:手機
fs-3,中螢幕fs-2,大螢幕fs-1 - Flexbox:手機垂直排列,平板以上水平排列
- 在平板以上才有右側間距和下方間距
- 標籤自動換行 (
mb-1) - 響應式文字大小:手機
fs-6,中螢幕以上fs-5 - 在小螢幕以上顯示完整文字
- 在小螢幕顯示簡化版本(只有圖示)
- 更新時間只在中螢幕以上顯示
Bootstrap 顯示工具類別
Bootstrap 提供了方便的顯示/隱藏工具類別:
d-none: 隱藏元素d-{breakpoint}-block: 在指定斷點以上顯示為 blockd-{breakpoint}-inline: 在指定斷點以上顯示為 inlined-{breakpoint}-none: 在指定斷點以上隱藏
範例:
d-none d-md-block: 預設隱藏,中螢幕以上顯示d-block d-md-none: 預設顯示,中螢幕以上隱藏
響應式導覽列¶
我們的 base.html 已經使用了響應式導覽列,讓我們檢視它的運作原理:
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<span class="navbar-brand">Django 大冒險</span> <!-- (1)! -->
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNav"> <!-- (2)! -->
<span class="navbar-toggler-icon"></span> <!-- (3)! -->
</button>
<div class="collapse navbar-collapse" id="navbarNav"> <!-- (4)! -->
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'article_list' %}">文章列表</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'admin:index' %}">管理後台</a>
</li>
</ul>
</div>
</div>
</nav>
- 品牌名稱,在所有尺寸都顯示
- 漢堡選單按鈕,在小螢幕顯示
- 漢堡圖示(三條線)
- 可收合的選單內容
導覽列運作方式¶
- 大螢幕 (≥992px):
- 選單項目水平排列
-
漢堡按鈕隱藏
-
小螢幕 (<992px):
- 選單收合,只顯示品牌 logo 和漢堡按鈕
- 點擊漢堡按鈕展開垂直選單
navbar-expand-* 說明
navbar-expand-{breakpoint} 控制導覽列何時從收合變成展開:
navbar-expand-sm: 在 ≥576px 展開navbar-expand-md: 在 ≥768px 展開navbar-expand-lg: 在 ≥992px 展開(我們使用這個)navbar-expand-xl: 在 ≥1200px 展開
測試響應式設計¶
使用瀏覽器開發者工具¶
所有現代瀏覽器都內建響應式設計模式:
Chrome / Edge¶
- 按
F12開啟開發者工具 - 按
Ctrl+Shift+M(Mac:Cmd+Shift+M) 切換裝置模式 - 選擇不同裝置或自訂尺寸
Firefox¶
- 按
F12開啟開發者工具 - 按
Ctrl+Shift+M(Mac:Cmd+Option+M) 切換響應式設計模式
Safari¶
- 開啟「開發」選單(偏好設定 → 進階 → 顯示「開發」選單)
- 「開發」→「進入響應式設計模式」
常見測試尺寸¶
| 裝置 | 寬度 × 高度 |
|---|---|
| iPhone SE | 375 × 667 |
| iPhone 12 Pro | 390 × 844 |
| iPad | 768 × 1024 |
| iPad Pro | 1024 × 1366 |
| Desktop HD | 1920 × 1080 |
測試檢查清單¶
測試響應式網站時,應該檢查:
- 文字是否清晰可讀(沒有太小)
- 按鈕是否夠大,方便點擊
- 圖片是否正確縮放
- 導覽列是否正常運作
- 表單是否易於填寫
- 內容是否需要左右捲動(應該避免)
- 欄位在不同尺寸下是否正確排列
- 隱藏/顯示的元素是否符合預期
響應式設計最佳實踐¶
1. 行動優先 (Mobile First)¶
先設計手機版,再擴展到大螢幕:
/* 預設樣式(手機) */
.card {
width: 100%;
}
/* 平板以上 */
@media (min-width: 768px) {
.card {
width: 50%;
}
}
/* 桌機以上 */
@media (min-width: 992px) {
.card {
width: 33.333%;
}
}
2. 觸控友善¶
手機使用者用手指點擊,按鈕應該夠大:
Bootstrap 的按鈕預設已經符合這個標準。
3. 適當的文字大小¶
/* 手機最小 16px,避免自動縮放 */
body {
font-size: 16px;
}
/* 標題在大螢幕可以更大 */
@media (min-width: 992px) {
h1 {
font-size: 3rem;
}
}
4. 優化圖片¶
<!-- 使用 srcset 提供不同尺寸的圖片 -->
<img
src="image-800w.jpg"
srcset="image-400w.jpg 400w, image-800w.jpg 800w, image-1200w.jpg 1200w"
sizes="(max-width: 768px) 100vw, 50vw"
alt="說明文字"
/>
5. 避免固定寬度¶
/* 不好 */
.container {
width: 960px;
}
/* 好 */
.container {
max-width: 1200px;
width: 100%;
padding: 0 15px;
}
Bootstrap 的 .container 已經處理好這些細節。
常見問題¶
RWD 和 Adaptive Design 有什麼不同?¶
- RWD (響應式設計): 使用流動格線和 media queries,在所有尺寸都能平滑適應
- Adaptive Design (自適應設計): 為特定尺寸設計不同版本(如手機版、平板版、桌機版)
RWD 更靈活,維護成本較低,是目前的主流方式。
要支援哪些螢幕尺寸?¶
建議至少支援:
- 手機: 375px - 428px
- 平板: 768px - 1024px
- 桌機: 1200px 以上
但 RWD 的優勢就是能適應任何尺寸,不需要精確為每個裝置設計。
Bootstrap Grid 一定要用嗎?¶
不一定。現代 CSS 也提供了強大的佈局工具:
- Flexbox: 一維佈局
- CSS Grid: 二維佈局
但 Bootstrap Grid 提供了:
- 現成的響應式斷點
- 跨瀏覽器相容性
- 快速開發
對於大多數專案,Bootstrap Grid 是很好的選擇。
如何處理表格的響應式?¶
表格在小螢幕上很難顯示,有幾種解決方案:
-
水平捲動:
-
轉換為卡片式佈局 (手機上)
- 隱藏次要欄位 (使用
d-none d-md-table-cell)
任務結束¶
完成!
恭喜你完成了這個章節!現在你已經:
- 了解 RWD 網頁設計的概念與重要性
- 深入理解 Bootstrap Grid 系統
- 優化文章列表與詳細頁面的響應式設計
- 學習響應式設計的測試方法
補充說明
響應式設計是現代網頁開發的必備技能。掌握 RWD 後:
- 網站能在任何裝置上提供良好體驗
- 提升網站的可訪問性和 SEO
- 降低開發和維護成本
在實際專案中,建議:
- 行動優先: 先設計手機版,再擴展到桌機版
- 測試多種裝置: 不只測試常見尺寸,也要測試極端情況
- 考慮觸控操作: 按鈕要夠大,間距要適當
- 優化效能: 手機通常網速較慢,要注意載入時間
下一步可以學習:
- CSS Flexbox 和 Grid 的進階應用
- 使用 Lighthouse 測試效能和可訪問性
- 圖片優化技術(WebP、lazy loading)
- Progressive Web App (PWA)