14. 在 HTML 中使用 CSS (Using HTML with CSS)

HTML 描述網頁的結構與意義。CSS,即層疊樣式表(Cascading Style Sheets),則控制網頁的呈現方式。

CSS 可以改變顏色、文字排版、間距、框線及版面,而不改變內容本身的意義。

<p class="intro">歡迎參加 HTML 課程。</p>
.intro {
  color: #005ea8;
  font-size: 1.125rem;
}

先選擇有意義的 HTML 元素,再使用 CSS 設定樣式。 將段落設計成看似標題,不會令它變成真正的標題。

14.1 HTML 與 CSS 如何配合

瀏覽器將 HTML 剖析為文件結構,再將符合的 CSS 規則套用至元素。

例如:

<h1>HTML 入門</h1>
<p>學習建立結構清晰的網頁。</p>

配合以下 CSS:

h1 {
  color: #005ea8;
}

p {
  line-height: 1.8;
}

標題會變成藍色,段落則會增加行距。

<h1> 是標題,原因是它使用了標題元素,而不是因為它的顏色或大小。

14.2 CSS 規則語法

CSS 規則包含選擇器及宣告區塊:

p {
  color: #333;
  font-size: 1rem;
}
部分用途
p選擇器:識別需要設定樣式的元素
{ ... }宣告區塊
color屬性
#333屬性值
color: #333;完整宣告

屬性與值之間使用冒號,每項宣告之後使用分號。

CSS 註解有自己的語法:

/* 改善一般段落的可讀性。 */
p {
  line-height: 1.8;
}

不要在樣式表內使用 HTML 註解分隔符號。

14.3 加入 CSS 的三種方式

CSS 可以透過以下方式加入:

  1. 外部樣式表。
  2. 內部樣式表。
  3. 行內樣式。

外部樣式表

在文件的 <head> 內參照 CSS 檔案:

<link rel="stylesheet" href="styles/main.css">

檔案只包含 CSS:

body {
  font-family: system-ui, sans-serif;
  line-height: 1.8;
}

外部樣式表通常最適合多頁專案,因為可以重用、獨立維護,並由瀏覽器快取。

內部樣式表

將 CSS 放在 <style> 內,通常位於 <head>:

<style>
  body {
    color: #222;
    background: #f5f7fa;
  }
</style>

這適合獨立範例或特定網頁的樣式。

行內樣式

使用 style 屬性,為單一元素加入宣告:

<p style="color: #005ea8; font-weight: 700;">
  必須先完成報名。
</p>

這個屬性只包含宣告,不包含選擇器或大括號。

行內樣式在某些情況下有用,但重複使用會令一致的樣式難以維護。它也不能直接表達 :hover 等選擇器或媒體查詢。

14.4 選取 HTML 元素

CSS 選擇器決定規則會影響哪些元素。

元素選擇器

p {
  margin-block: 0 1rem;
}

這會選取所有 <p> 元素。

類別選擇器

.course-card {
  padding: 1.25rem;
}

這會選取具有 course-card 類別的元素。

識別碼選擇器

#course-overview {
  border-inline-start: 4px solid #005ea8;
}

這會選取具有 id="course-overview" 的元素。

可重用的樣式應優先使用類別。

屬性選擇器

[data-level="beginner"] {
  background: #eaf2f8;
}

這會選取具有指定屬性值的元素。

後代與子元素選擇器

.course-card p {
  color: #333;
}

.course-card > h2 {
  margin-block-start: 0;
}
  • 空格會選取任何深度中符合的後代元素。
  • > 只會選取直接子元素。

選擇器應保持清晰,不要比實際需要更複雜。

14.5 層疊與特異性

多個 CSS 規則可以套用至同一元素。**層疊(cascade)**決定每個屬性最終採用哪項宣告。

例如:

p {
  color: #333;
}

.notice {
  color: #005ea8;
}
<p class="notice">繼續之前,請先儲存你的工作。</p>

在這個一般例子中,類別選擇器的特異性高於元素選擇器,因此會採用類別規則的顏色。

如果其他層疊條件相同,而且特異性相同,較後的宣告會勝出:

.notice {
  color: #333;
}

.notice {
  color: #005ea8;
}

不過,「最後一項規則一定勝出」並不是完整的解釋。層疊會考慮以下因素:

  • 樣式來源。
  • 宣告是否使用 !important。
  • 層疊層(cascade layers)。
  • 選擇器特異性。
  • 前面因素相同時的原始碼次序。

一般行內宣告通常優先於一般作者樣式表規則,但並不是無法被覆寫。

不要將 !important 當作日常修正方法。 應檢查互相衝突的規則,並盡可能簡化樣式結構。

14.6 繼承

部分 CSS 屬性會從父元素傳至後代元素。

例如:

body {
  color: #222;
  font-family: system-ui, sans-serif;
  line-height: 1.8;
}

除非其他規則覆寫,否則段落及許多後代元素會繼承這些文字設定。

外邊距、內邊距及框線等屬性通常不會繼承:

section {
  border: 1px solid #767676;
}

這不會自動令每個子元素都有自己的框線。

表單控制項可能有瀏覽器預設的字型。要讓它們使用周圍的文字樣式,可以設定:

button,
input,
select,
textarea {
  font: inherit;
}

14.7 盒模型

CSS 將元素視為由四個主要區域組成的盒子:

  1. 內容(content):文字、圖片或其他內容。
  2. 內邊距(padding):內容與框線之間的空間。
  3. 框線(border):圍繞內容及內邊距的邊界。
  4. 外邊距(margin):框線外的空間。
.course-card {
  padding: 1.25rem;
  border: 1px solid #767676;
  margin-block: 1.5rem;
}

預設情況下,宣告的寬度通常適用於內容區域。內邊距及框線會加在該寬度之外。

常見的基礎設定會改變這項行為:

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

使用 border-box 時,宣告的寬度包含內邊距及框線,外邊距則仍然位於外部。

部分區塊元素的垂直外邊距可能會合併,因此相鄰的外邊距不一定直接相加。

14.8 單位與清晰的尺寸設定

常見 CSS 單位包括:

單位意思
pxCSS 像素
rem相對於根元素的字型大小
em用於字型大小時,相對於父元素;用於許多其他屬性時,相對於元素本身的字型大小
%相對於某個參考值,實際參考取決於屬性
ch根據字型中「0」字元的前進寬度
vw可視區域寬度的百分之一

例如:

body {
  font-size: 1rem;
  line-height: 1.8;
}

main {
  max-width: 48rem;
  margin-inline: auto;
  padding: 2rem 1rem;
}

不帶單位的 line-height 很實用,因為後代元素會繼承倍率,而不是固定的行高長度。

避免過長的文字行及固定高度的文字容器。讀者放大文字後,不應失去內容。

14.9 使用 Flexbox 與 Grid 排版

使用 CSS 安排網頁內容,不要使用表格或重複空格排版。

Flexbox

Flexbox 適合主要沿單一軸線排列項目:

.course-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

允許換行後,空間不足的項目可以移至下一行。

Grid

Grid 適合將內容排列成橫列與直欄:

.course-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

@media (min-width: 48rem) {
  .course-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

窄螢幕會顯示一欄,較寬螢幕則顯示兩欄。

保持 HTML 原始碼次序合理。使用 CSS 改變視覺排列,可能令顯示版面、閱讀次序及鍵盤導覽不一致。

14.10 響應式樣式

響應式 CSS 根據可用空間及使用者偏好調整呈現方式。

加入可視區域中繼資料:

<meta name="viewport" content="width=device-width, initial-scale=1">

不要停用縮放功能。

設計需要改變時,可以使用媒體查詢:

.page-title {
  font-size: 2rem;
}

@media (min-width: 48rem) {
  .page-title {
    font-size: 2.5rem;
  }
}

一般內容圖片可以設定:

img {
  max-width: 100%;
  height: auto;
}

這有助圖片配合容器寬度,同時保持比例。

響應式設計不只關乎螢幕寬度。也應測試放大的文字、較長內容及不同輸入方式。

14.11 互動狀態與無障礙功能

連結及控制項的樣式應清楚表達其互動用途:

a {
  color: #005ea8;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-thickness: 0.15em;
}

a:focus-visible,
button:focus-visible {
  outline: 3px solid #005ea8;
  outline-offset: 4px;
}

不要移除焦點提示,除非提供有效的替代樣式。

也應注意:

  • 不要只依靠顏色表達意義。
  • 文字及控制項應有足夠對比。
  • 重要資訊不應只在滑鼠懸停時提供。
  • 加入動畫時,尊重使用者減少動態效果的偏好。
  • 確保控制項可以使用鍵盤操作。

CSS 可以改變外觀,但不能將沒有適當語意的元素變成完整的無障礙控制項。

14.12 隱藏內容

不同 CSS 技巧具有不同效果。

.unavailable-panel {
  display: none;
}

display: none 會將元素移出版面,通常也會從無障礙樹中移除。

相比之下:

.transparent-panel {
  opacity: 0;
}

opacity: 0 只會令內容在視覺上透明。它仍然可以佔據版面空間、供輔助技術存取,而且可能保持可互動。

對目前不應呈現的內容,HTML 的 hidden 屬性通常很合適:

<div hidden>額外課程詳情</div>

應小心,避免 CSS 意外覆寫它的隱藏行為。

這些方式都不能保護私人資訊。傳送至瀏覽器的隱藏內容,仍然可以被檢查。

14.13 配合語言的樣式

在 HTML 中使用 lang 標示語言,再按需要以 CSS 調整外觀:

<p lang="zh-Hant-HK">清晰的文字排版有助閱讀。</p>
:lang(zh-Hant) {
  line-height: 1.8;
}

:lang() 選擇器能識別繼承的語言設定;屬性選擇器則只會檢查元素本身的 lang 屬性。

邏輯屬性可以令樣式更容易配合不同書寫方式:

.notice {
  border-inline-start: 4px solid #005ea8;
  padding-inline: 1rem;
  margin-block: 1rem;
}

padding-inline 及 margin-block 等屬性會跟隨文字方向及書寫模式,而不是固定假設實體的左、右、上、下。

14.14 完整範例:響應式課程網頁

以下獨立網頁結合語意化 HTML、可重用的 CSS 類別、響應式網格、配合語言的文字排版,以及可見的鍵盤焦點提示。

主要內容使用香港繁體中文,英文摘要有自己的語言設定。

id: hong-kong-html-with-css
name: HTML 與 CSS — 響應式課程網頁
type: html
content: |-
  <!doctype html>
  <html lang="zh-Hant-HK">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>HTML 與 CSS | 課程指南</title>
    <style>
      *,
      *::before,
      *::after {
        box-sizing: border-box;
      }

      body {
        margin: 0;
        color: #222;
        background: #f5f7fa;
        font-family: system-ui, sans-serif;
        font-size: 1rem;
        line-height: 1.7;
      }

      main {
        max-width: 56rem;
        margin-inline: auto;
        padding: 2rem 1rem;
      }

      h1,
      h2 {
        color: #005ea8;
        line-height: 1.3;
      }

      h1 {
        margin-block: 0 1rem;
        font-size: 2rem;
      }

      h2 {
        margin-block: 0 1rem;
        font-size: 1.5rem;
      }

      p {
        margin-block: 0 1rem;
      }

      .page-intro {
        max-width: 40rem;
        font-size: 1.125rem;
      }

      .course-navigation {
        margin-block: 1.5rem;
        padding: 1rem 1.25rem;
        border: 1px solid #767676;
        border-radius: 0.5rem;
        background: white;
      }

      .course-navigation ul {
        margin-block: 0;
        padding-inline-start: 1.25rem;
      }

      .course-navigation li {
        margin-block: 0.5rem;
      }

      .course-grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        gap: 1.5rem;
        margin-block: 1.5rem;
      }

      .course-card {
        min-width: 0;
        padding: 1.25rem;
        border: 1px solid #767676;
        border-radius: 0.5rem;
        background: white;
        overflow-wrap: anywhere;
      }

      .course-card > :last-child {
        margin-block-end: 0;
      }

      .notice {
        padding: 1rem;
        border-inline-start: 4px solid #005ea8;
        background: #eaf2f8;
      }

      a {
        color: #005ea8;
        text-decoration: underline;
        text-underline-offset: 0.2em;
      }

      a:hover {
        text-decoration-thickness: 0.15em;
      }

      a:focus-visible {
        outline: 3px solid #005ea8;
        outline-offset: 4px;
      }

      :lang(zh-Hant) {
        line-height: 1.8;
      }

      h1:lang(zh-Hant),
      h2:lang(zh-Hant) {
        line-height: 1.4;
      }

      [id] {
        scroll-margin-block-start: 1rem;
      }

      @media (min-width: 48rem) {
        h1 {
          font-size: 2.5rem;
        }

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

      @media print {
        body {
          color: black;
          background: white;
        }

        main {
          max-width: none;
          padding: 0;
        }

        .course-navigation {
          display: none;
        }

        .course-grid {
          grid-template-columns: minmax(0, 1fr);
        }

        .course-card {
          break-inside: avoid;
        }
      }
    </style>
  </head>
  <body>
    <main>
      <header>
        <h1>探索 HTML 與 CSS</h1>
        <p class="page-intro">
          HTML 賦予內容結構及意義。
          CSS 則令內容清晰可讀,並能配合不同環境。
        </p>
      </header>

      <nav class="course-navigation" aria-label="本頁目錄">
        <ul>
          <li><a href="#html-course">HTML 基礎</a></li>
          <li><a href="#css-course">CSS 基礎</a></li>
          <li><a href="#learning-note">學習提示</a></li>
        </ul>
      </nav>

      <div class="course-grid">
        <section class="course-card" aria-labelledby="html-course">
          <h2 id="html-course">HTML 基礎</h2>
          <p>選擇能描述內容用途的元素。</p>
          <ul>
            <li>標題與段落</li>
            <li>連結與清單</li>
            <li>表格與屬性</li>
          </ul>
          <p>
            <a href="#learning-note">閱讀學習提示</a>
          </p>
        </section>

        <section class="course-card" aria-labelledby="css-course">
          <h2 id="css-course">CSS 基礎</h2>
          <p>
            套用可重用的樣式,
            同時保留內容本身的意義。
          </p>
          <ul>
            <li>選擇器與層疊</li>
            <li>文字排版與盒模型</li>
            <li>響應式版面</li>
          </ul>
          <p class="notice">
            <strong>練習提示:</strong>
            調整視窗大小,並測試鍵盤導覽。
          </p>
        </section>
      </div>

      <section
        class="course-card"
        aria-labelledby="learning-note"
      >
        <h2 id="learning-note">學習提示</h2>
        <p>
          先使用合適的 HTML 元素建立內容結構,
          再透過 CSS 設定字型、間距、顏色及版面。
        </p>
        <p>
          放大文字或縮小視窗後,
          內容仍應清晰可讀,連結也應能使用鍵盤操作。
        </p>
        <p lang="en-HK">
          Choose semantic HTML first, then use CSS
          to make the content readable and responsive.
        </p>
      </section>
    </main>
  </body>
  </html>

在這個範例中:

  • 語意化標題、導覽、章節及清單定義內容結構。
  • 類別提供可重用的樣式掛鈎。
  • 空間足夠時,Grid 由一欄變成兩欄。
  • 所有螢幕尺寸都保留相同的原始碼次序。
  • 中文文字使用配合語言的行距。
  • 列印樣式隱藏導覽,同時保留主要內容。
  • 不需要 JavaScript。

在多檔案專案中,可以將 CSS 移至 styles/main.css,並以以下標記取代 <style> 區塊:

<link rel="stylesheet" href="styles/main.css">

14.15 排解 CSS 問題

如果樣式沒有顯示:

  1. 在 **Network(網絡)**面板確認樣式表已載入。
  2. 檢查選擇器是否符合實際 HTML。
  3. 在元素的 **Styles(樣式)**面板檢查被覆寫的宣告。
  4. 查看 Computed(計算後樣式),了解最終值。
  5. 檢查無效的屬性、值或遺漏的大括號。
  6. 確認媒體條件符合目前環境。
  7. 如果仍在使用舊樣式表,檢查快取。

開發者工具中被劃掉的宣告,通常表示另一項宣告取得了優先權。

14.16 常見錯誤

錯誤較好的做法
只按預設外觀選擇 HTML 元素按意義選擇,再設定樣式
使用表格或重複空格排版使用 Flexbox 或 Grid
在整個網站重複行內樣式使用可重用類別及樣式表
以為最後一項 CSS 規則一定勝出了解層疊及特異性
以為內邊距及框線會繼承明確設定相關盒子的樣式
使用 !important 修正所有衝突檢查並簡化規則
移除鍵盤焦點外框提供可見的替代提示
為會改變的文字設定固定高度允許內容增長
改變視覺次序卻沒有測試保持合理的閱讀及焦點次序
只使用顏色表示狀態加入文字或其他清晰提示
將隱藏內容視為安全在伺服器端實施安全控制

本章總結: 使用 CSS 清晰、響應式地呈現語意化 HTML。理解選擇器、層疊、繼承及盒模型,優先使用可重用樣式,並測試不同尺寸下的可讀性、鍵盤操作及版面。

Scroll to Top