這一課完成後:你會把樣式獨立放進 styles.css,知道 selector、property、value、class、box model 在做什麼,並讓上一課的頁面具備基本排版與 responsive 行為。

先不要重做 HTML,沿用上一課

打開上一課的:

web-basics-playground/

你的 index.html 不需要和範例一模一樣,但應該至少有標題、段落、幾個 section、清單、連結與圖片。

現在新增:

styles.css

專案大致會變成:

web-basics-playground/
├─ index.html
├─ styles.css
└─ images/
   └─ profile.jpg

第一件事:把 CSS 接到 HTML

在 <head> 裡加入:

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

這行的意思是:這份 HTML 文件要載入 styles.css 當作 stylesheet。

如果你之後移動 CSS 檔案,href 也要跟著改,因為它仍然是一條路徑。

先做一個最明顯的測試

在 styles.css 輸入:

body {
  background: #f4f4f4;
}

儲存,重新整理瀏覽器。如果背景變成淡灰色,CSS 已經成功載入。

如果完全沒變,先檢查三件事:檔案有沒有儲存、href 路徑對不對、檔名是不是其實叫 styles.css.txt。

一條 CSS rule 可以拆成三個核心部分

p {
  color: #444;
}
p → selector
color → property
#444 → value

selector 決定要選誰;property 決定要改哪種樣式;value 決定改成什麼。

這個模型會一直重複:

選到元素 → 指定屬性 → 給值

先把整頁的字和背景整理乾淨

加入:

body {
  margin: 0;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  line-height: 1.6;
  color: #1f2937;
  background: #f7f7f8;
}

font-family 決定字體;這裡優先使用系統字體,不需要先載入外部字型。

line-height 控制行距;color 是文字顏色;background 是背景。

margin: 0 則把瀏覽器預設留在 body 外圍的空白拿掉,讓後面的版面由我們自己控制。

CSS 不是只有 tag selector

如果你寫:

p {
  color: #444;
}

所有 p 都會被選到。但真實網站很少只靠標籤名稱做所有設計。

HTML 可以用 class 標出「這些元素在設計上屬於同一種角色」。例如:

<section class="card">
  <h2>我現在在學什麼</h2>
  <p>HTML、CSS、JavaScript。</p>
</section>

CSS 就可以寫:

.card {
  background: white;
}

前面的 . 表示 class selector。

HTML:class="card"
CSS:.card { ... }

先建立一個頁面容器

在 HTML 裡,把主要內容包進:

<main class="page">
  ...你的主要內容...
</main>

然後寫:

.page {
  width: min(100% - 32px, 800px);
  margin: 0 auto;
  padding: 48px 0;
}

這幾行做了三件事:

限制最大寬度 → 讓內容不要在大螢幕拉得太寬
margin: 0 auto → 左右自動置中
padding → 上下留出呼吸空間

width: min(100% - 32px, 800px) 可以先理解成:「小螢幕保留左右 16px;大螢幕最多 800px。」

Box model:你看到的每個區塊都像一個盒子

CSS 很多排版問題最後都回到 box model:

content → padding → border → margin

content 是內容本身;padding 是內容和邊界之間的內距;border 是邊界;margin 是元素和外面其他元素之間的距離。

讓剛才的 card 變得像一張卡片:

.card {
  background: white;
  padding: 24px;
  border: 1px solid #e5e7eb;
  border-radius: 16px;
  margin-top: 20px;
}

這時候你看到的「卡片感」,其實主要就是背景、內距、邊框、圓角與外距共同形成。

padding 跟 margin 不要混著猜

一個簡單判斷:

我要讓內容離自己的邊界遠一點 → padding
我要讓這個元素離別的元素遠一點 → margin

不是所有情況都能靠一句話解完,但這個模型足夠幫你避免一開始完全亂試。

讓圖片不要把版面炸掉

對頁面上的圖片加一個 class:

<img class="profile-image" src="images/profile.jpg" alt="我的個人介紹圖片" />

再寫:

.profile-image {
  width: 100%;
  max-width: 360px;
  height: auto;
  display: block;
  border-radius: 16px;
}

width: 100% 讓圖片在容器太小時跟著縮;max-width 避免它在大螢幕無限放大;height: auto 保持原本比例。

Typography 不只是 font-size

可以先整理標題:

h1 {
  margin: 0;
  font-size: clamp(2rem, 6vw, 4rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
}

h2 {
  margin-top: 0;
  font-size: 1.35rem;
}

clamp() 可以讓字體在一個最小值和最大值之間,依畫面寬度自然變化。

現在不用背它完整語法,只要知道:responsive 並不一定等於寫很多 media queries。

顏色最好有角色,不要每個地方隨機挑

例如可以先定義:

:root {
  --text: #1f2937;
  --muted: #6b7280;
  --surface: #ffffff;
  --border: #e5e7eb;
  --accent: #2563eb;
}

然後使用:

body {
  color: var(--text);
}

.card {
  background: var(--surface);
  border-color: var(--border);
}

a {
  color: var(--accent);
}

這些 --text、--accent 是 CSS custom properties。現在先用它們理解一件事:設計系統通常不是「這裡藍一點,那裡灰一點」,而是讓顏色有固定角色。

Hover 是狀態,不是另一個元素

讓連結在滑鼠移上去時改變:

a:hover {
  text-decoration-thickness: 2px;
}

:hover 是 pseudo-class。它描述的是元素目前處於某個狀態。

之後你還會遇到 :focus、:checked、:disabled 等狀態,但現在知道這個概念就夠。

不要把所有 layout 都交給 margin

如果你有一組卡片,例如:

<div class="cards">
  <section class="card">...</section>
  <section class="card">...</section>
</div>

可以使用 Grid:

.cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}

display: grid 表示這個容器要用 Grid layout;grid-template-columns 這裡建立兩個等寬欄;gap 控制欄位之間的距離。

這比「第一張卡 margin-right: 20px,第二張又另外調」更接近真正的 layout 思維。

讓它在手機不要硬塞兩欄

加入:

@media (max-width: 640px) {
  .cards {
    grid-template-columns: 1fr;
  }

  .page {
    padding-top: 28px;
  }
}

這就是 media query:當 viewport 寬度不超過 640px 時,套用裡面的規則。

寬螢幕 → 2 欄
窄螢幕 → 1 欄

Responsive 的核心不是「做手機版」,而是讓內容在不同可用空間下仍然合理。

用 DevTools 改 CSS,比一直存檔更快

在瀏覽器打開 Developer Tools,選取某個元素,你可以直接看到它套用了哪些 CSS,也可以臨時修改 property/value。

這些修改重新整理就會消失,所以它不是正式改檔;但非常適合快速試:

在 DevTools 試 → 找到合理值 → 回 VS Code 正式修改

之後遇到「為什麼這個 margin 沒有效果」時,DevTools 會比盲猜快很多。

為什麼有時候我明明寫了,卻沒生效?

CSS 有 cascade 和 specificity。現在先掌握最基本的一層:

p {
  color: gray;
}

.intro {
  color: black;
}

如果某個 paragraph 同時有 class="intro",較具體的 .intro 規則通常會勝出。

另外,後面出現的規則也可能覆蓋前面同等優先級的規則。

先不要急著用 !important 解所有問題。看到樣式衝突時,先用 DevTools 看是哪條規則真的贏了。

把上一課的頁面整理成一個完整版本

你可以把主要結構整理成:

<body>
  <main class="page">
    <header class="hero">
      <p class="eyebrow">Web Basics</p>
      <h1>我的第一個網站</h1>
      <p class="intro">我正在學 HTML、CSS 和 JavaScript。</p>
    </header>

    <div class="cards">
      <section class="card">
        <h2>我正在學什麼</h2>
        <ul>
          <li>HTML</li>
          <li>CSS</li>
          <li>JavaScript</li>
        </ul>
      </section>

      <section class="card">
        <h2>我的工具</h2>
        <p>我正在使用 VS Code 寫這個網站。</p>
      </section>
    </div>
  </main>
</body>

注意:我們沒有為了 CSS 把語意結構全部丟掉。HTML 還是負責「這是 header、section、heading、list」;class 只是再加上一層設計用的 hook。

小挑戰:不要照著抄出同一張頁面

需求 1:保留上一課至少兩個有語意的 section。

需求 2:建立並正確載入 styles.css。

需求 3:至少使用一個 class selector。

需求 4:至少有一個使用 padding、border、border-radius 的區塊。

需求 5:圖片不能超出容器寬度。

需求 6:至少使用一次 Grid 或 Flexbox 做真正的 layout。

需求 7:在窄螢幕下,版面不能出現明顯水平捲動。

需求 8:用 DevTools 臨時改過至少一個 CSS value,再回檔案正式保存。

最後收斂:CSS 到底在做什麼?

到這裡,最重要的心理模型是:

HTML 提供結構與語意
CSS 選取元素 → 套用視覺規則 → 形成版面

CSS 不是「把字改成藍色」的工具而已。真正進入網站設計後,你會不斷處理尺寸、間距、排列、狀態、不同 viewport,以及多條規則如何一起作用。

下一課會加入 JavaScript。從那時候開始,頁面不只會「長得不一樣」,還會開始根據資料和邏輯做事。

完成條件:你的頁面已經把樣式獨立到 styles.css,能使用 class、box model 與至少一種 layout system,並且在窄螢幕下仍然可閱讀。