您請代理修改頁面,結果簡單的專案裡冒出幾個名字看不懂的檔案:index.html、style.css、script.js。也可能它們本來就在,而代理的報告只寫著 "改了樣式" - 光看這句話,看不出它到底動了什麼。

我們來看看瀏覽器接收的三項基礎技術:HTML、CSS 和 JavaScript。為了方便說明,這裡用一個不需要建置的簡單靜態頁面。實際的儲存庫裡,檔案的名稱和位置可能不一樣,所以修改前最好先請代理列出專案結構,找出負責目標元素的檔案。這篇文章不教手寫網頁,這件事交給代理就好。

頁面是瀏覽器讀取的文字

先從一個簡單的靜態頁面開始:它的原始碼就是普通的文字檔。用記事本就能打開,直接用眼睛讀。這裡不需要額外建置:瀏覽器讀取 HTML、載入相關資源,再依據它們把頁面畫到螢幕上。

這類專案的起點通常是 index.html 檔案。瀏覽器打開它、解析標記,再依照其中的連結載入樣式、腳本、圖片和字型。

瀏覽器讀取簡單靜態專案的三個檔案,並顯示完成的頁面index.htmlstyle.cssscript.js瀏覽器完成的頁面
簡單的靜態專案可能是這樣運作的:瀏覽器載入三個相關聯的檔案,然後顯示頁面

在需要建置的專案中,原始碼可能分散在各個元件裡,最終的 HTML、CSS 和 JavaScript 由專門的工具產生。下面的角色分工仍然是一張有用的地圖,但在那種專案裡,不必去找這三個名稱的檔案。

在我們的簡單範例中,三個檔案各有各的角色:

  • HTML - 頁面上有什麼:標題、段落、按鈕、圖片;
  • CSS - 看起來如何:顏色、字型、間距、圓角、平滑效果;
  • JavaScript - 會發生什麼:點擊時、輸入文字時、計時器觸發時。

下面逐一來看。

HTML:標記由什麼組成

HTML 是標記,不是繪圖。您不必描述按鈕長什麼樣子,只要說 "這裡有個按鈕",瀏覽器就會用它自己的方式畫出來。

標記的基本單位是標籤。幾乎都是成對出現:開始標籤和結束標籤,中間夾著內容。

button 開始這一行拆成三部分:開始標籤、內容和結束標籤,合起來標示為 HTML 元素<button>開始</button>HTML 元素開始標籤結束標籤內容
在這個範例中,三個部分合起來構成頁面上的一個元素

每個部分都有自己的名稱,合起來則叫做元素。這個詞之後會常用到:談到頁面時,大家比較常說 "元素",指的是標籤連同裡面的內容。

標籤名稱是英文單字的縮寫:p 來自 paragraph(段落),a 來自 anchor(錨點),img 來自 image(圖片)。不必死背,但遇到不熟的標籤時,這通常能幫您猜出它負責什麼。

結束標籤多了一條斜線。也有沒有結束標籤的元素,例如 <img> 不能包含文字或巢狀標籤,圖片位址則是透過 src 屬性取得。

標籤可以一層層巢狀,像盒子裡再放盒子,關閉時順序相反 - 先關內層,再關外層。順序弄錯了,瀏覽器不會當掉,它會試著猜您的意思。只是通常猜不對。

第二個概念是屬性。它是寫在開始標籤裡的補充說明,交代這個標籤的某些資訊:連結指向哪裡、圖片從哪裡取得、這個元素叫什麼名字。

<a href="https://example.com">打開網站</a>
<img src="cover.png" alt="封面">
<button id="play" class="btn">開始</button>

最後一行的 class 屬性再過兩分鐘就會用到:樣式會透過它套用到按鈕上。id="play" 屬性則給按鈕一個獨一無二的名字,腳本會靠這個名字找到它。

接著看一整個頁面。它比您想像的還短:

<!doctype html>
<html>
<head>
  <title>我的頁面</title>
</head>
<body>
  <h1>第一個頁面</h1>
  <p>一段普通的文字。</p>
  <button id="play" class="btn">開始</button>
</body>
</html>

頁面分成兩部分:<head> 是幕後資訊,放分頁標題和樣式連結;<body> 則是讀者在螢幕上看到的一切。第一行只是告訴瀏覽器,眼前是現代的 HTML。

頁面的巢狀結構:html 裡面放著含分頁標題的 head,以及含螢幕上所有可見內容的 body<html></html><head></head><body></body><title>我的頁面</title><h1>, <p>, <button>, <img>
盒子裡的盒子:head 和 body 放在 html 裡面,其他一切又放在它們裡面

這張圖點出標記最主要的特性:頁面上的一切都放在某個東西裡面。<body> 在 <html> 裡,按鈕在 <body> 裡,文字在按鈕裡。檔案裡一層層的縮排也是這麼來的:它不是為了好看,而是標出誰包在誰裡面。

實際的結論很簡單。瀏覽器分頁的標題和樣式的引入都寫在 <head> 裡,螢幕上完全看不到。其他一切都在 <body> 裡。當代理在報告裡寫 "在 body 中加了一個區塊",說的正是第二個盒子:新東西出現在頁面上,而不是幕後的部分。

HTML 的標籤超過一百個,但實際頁面裡翻來覆去用的幾乎都是那幾個:

標籤作用
<h1> ... <h6>標題,從最主要的到最小的
<p>一段文字
<a>連結,位址放在 href 屬性裡
<img>圖片,檔案路徑放在 src 屬性裡
<button>按鈕
<ul> 和 <li>清單和清單項目
<div>區塊容器,裝其他元素的盒子
<span>行內的一小段文字,用來單獨標出

最後兩個本身沒有任何含義,也不畫出任何東西。它們是空盒子,方便樣式和腳本抓取 - 也正因如此,每個頁面裡它們的數量都最多。

CSS:頁面如何獲得外觀

光有標記的頁面看起來很陽春:白底黑字、灰色的系統按鈕,所有東西都貼著左邊。它和一個設計過的頁面之間的差距,大部分是 CSS 補上的。

CSS 由規則組成。一條規則回答兩個問題:套用到什麼上,以及改變什麼。

.btn {
  background: #6c5ce7;    /* 背景顏色 */
  color: #ffffff;         /* 文字顏色 */
  padding: 12px 24px;     /* 內部間距 */
  border-radius: 12px;    /* 圓角 */
}

第一行是選擇器:它指出規則作用在哪些元素上。接著大括號裡是一組組 "屬性: 值",每組以分號結尾。

btn 前面的點代表類別(class)。還記得按鈕上的 class="btn" 屬性嗎?就是它發揮了作用:您在標記裡給元素掛上一個記號,在樣式裡再指向這個記號。同一個記號可以掛在十個按鈕上 - 一條規則就能讓十個按鈕長得一模一樣。

CSS 的屬性有好幾百個,但要讀懂別人的檔案、看出裡面在做什麼,認得幾個就夠了:

  • color - 文字顏色,background - 背景的顏色或圖片;
  • font-size 和 font-family - 字型大小和字型家族;
  • padding - 元素內側的留白,margin - 外側的留白,也就是和相鄰元素之間的距離;
  • border-radius - 圓角,"高級感" 有一半靠它;
  • transition - 平滑效果:不是一下子跳過去,而是在 0.2 秒內慢慢變化。

規則最常放在獨立的檔案裡,頁面則透過幕後部分的一行程式碼得知它的存在:

<head>
  <link rel="stylesheet" href="style.css">
</head>

把這一行拿掉,樣式檔就不會載入。文字和元素還留在標記裡,但原本的版面和外觀可能會消失,有時頁面甚至會變得不好用。

同一份標記出現兩次:左邊沒有樣式,只有文字和灰色的方形按鈕;右邊是相同的元素,加上了間距、顏色和圓角僅 HTMLHTML 加 CSS
元素完全相同,順序也一樣。改變的只有顏色、間距和形狀

圖中左右兩邊是同一個頁面:標題、兩行文字、一個按鈕。沒有任何元素增加或消失 - 在這個範例裡,只修改了樣式檔。

這是一張幫助尋找的地圖,不是一道技術上的高牆。為了新的版面,代理有時需要修改 HTML 裡的類別或容器,而一條不恰當的 CSS 規則可能蓋住按鈕,讓它點不到。所以做完視覺上的修改後,要看 diff、打開頁面,檢查受影響的操作。

JavaScript:有動作時會發生什麼

HTML 和 CSS 已經能把頁面顯示出來,還能加上平滑的轉場或動畫。但我們範例中的按鈕還沒有自己的行為:按下去,分數不會變。

頁面上的各種邏輯通常由 JavaScript 加進來。按鈕在 HTML 裡已經有了獨一無二的名字 id="play"。接下來的流程很簡單:找到元素、等待事件、改變某些東西。

// 依照 id 找到按鈕
const button = document.getElementById("play");
let score = 0;

// 監聽事件:點擊時要做什麼
button.addEventListener("click", function () {
  score = score + 1;
  button.textContent = "分數: " + score;
});

第一次點擊,按鈕上的文字會變成 "分數: 1",第二次變成 "分數: 2"。如果什麼都沒發生,先檢查 HTML 裡寫的是不是 id="play",而腳本裡用的是不是同一個名字 play。

這裡有三個細節。const 和 let 用來宣告變數 - 一個有名字、裝著值的盒子。addEventListener 讓頁面監聽某個事件:點擊、輸入文字、滑鼠移上去。大括號裡放的是函式 - 事件發生時要執行的一段程式碼。

注意最後一行:腳本改了按鈕上的文字。這一點很重要 - JavaScript 能在頁面運作時同時改變標記和樣式。它可以加入段落、隱藏區塊、替按鈕換顏色。所以各層之間的界線不是一道牆,而是一種分工。

實務上,如果元素會對資料做出反應、處理點擊或做計算,就從 JavaScript 開始找。淡入、變色和簡單的移動,常常是 CSS 做的。這只是起點,不是最後的診斷:修改後請自己打開頁面,檢查外觀和操作 - 光看一張截圖是不夠的。

一個按鈕,三個檔案

把前面的內容全部套到同一個元素上。"開始" 按鈕同時存在於三個檔案裡,每個檔案各管各的部分。

<button id="play" class="btn">開始</button>
.btn {
  background: #6c5ce7;
  border-radius: 12px;
}
const playButton = document.getElementById("play");

playButton.addEventListener("click", function () {
  playButton.textContent = "遊戲已開始";
});

只要檔案都有正確引入,點擊後按鈕上的文字就會從 "開始" 變成 "遊戲已開始"。這樣範例就能實際驗證,不必憑空想像一個不存在的函式。

接下來是最有用的部分 - 一次拿掉一行,會發生什麼事:

  • 拿掉 HTML - 什麼都沒了:沒有東西可以上樣式、也沒有東西可以讓它動起來;
  • 拿掉 CSS - 按鈕還在,也能用,只是看起來像九〇年代的灰色系統按鈕;
  • 拿掉 JS - 按鈕很漂亮,但是死的。按得下去,然後什麼都不會發生。

由此可以得到一張交代任務時用的簡單地圖。如果您不滿意的是看起來的樣子,就從樣式開始找。如果不滿意的是發生的事,就從腳本開始。如果元素根本不存在,就從標記開始。記得,只是 "開始":實際的修改可能牽動相鄰的那一層,所以代理的結論要透過 diff 和瀏覽器來檢查。

專案資料夾裡有什麼

簡單頁面最常見的檔案組合是這樣:

index.html    標記,進入點
style.css     樣式
script.js     行為

它們靠標記裡的兩行串在一起。樣式在幕後部分引入,腳本則放在最後面、</body> 關閉之前,這樣它開始執行時,所有元素都已經存在了:

<head>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- 頁面標記 -->
  <script src="script.js"></script>
</body>

也有不一樣的情況。大型專案裡有幾十個檔案,分放在 css/、js/ 這類資料夾裡,旁邊還有圖片和字型。也可能剛好相反,整個專案只有一個檔案 - 這種情況下面馬上會談。標記、樣式和邏輯的角色依然存在,只是檔名和引入方式可能不同。

當樣式和腳本寫在頁面裡

三個檔案是最常見的配置,但不是唯一的一種。同一段 CSS 可以放在三個不同的地方,這三種您遲早都會遇到。

第一種您已經看過了:獨立檔案加上一行 <link>。第二種是直接寫在標記裡的 <style> 區塊,不另外開檔案:

<head>
  <style>
    .btn {
      background: #6c5ce7;
      border-radius: 12px;
    }
  </style>
</head>

裡面的內容完全一樣:選擇器、大括號、"屬性: 值"。變的只有存放的位置。頁面只有一個、沒必要替它另開檔案時,就會這樣寫。

第三個地方是行內樣式,也就是 inline styles。屬性直接掛在元素上,寫在 style 屬性裡:

<button class="btn" style="background: #e17055; font-size: 20px">開始</button>

這裡不需要選擇器:規則作用在哪個元素上已經很清楚 - 就是寫著它的那個元素。所以沒有大括號,類別名稱前也沒有點,只有用分號隔開的 "屬性: 值",全部寫在同一行。

這種寫法只在第一次時方便,之後缺點就來了。規則只作用在單一元素上:十個按鈕就是十份複本,之後要改就得十個全改。一般的行內樣式,優先順序通常高於檔案裡的一般規則。您用 style 替按鈕上了色,後來在 style.css 裡改同一個屬性,卻怎麼也想不通顏色為什麼不變。因此 style 屬性是最先要檢查的地方之一;詳細的優先順序規則現在還用不到。

腳本也是一樣,只是位置有兩種。獨立檔案透過 <script src="..."> 引入,也可以把程式碼直接寫在標籤之間:

<script>
  document.getElementById("play").addEventListener("click", function () {
    alert("遊戲已開始");
  });
</script>

整理成一張小表,方便日後查閱:

內容放在哪裡在 HTML 裡長怎樣
樣式獨立檔案<link rel="stylesheet" href="style.css">
樣式頁面裡的區塊<style> ... </style>
樣式直接寫在元素上style="color: red"
腳本獨立檔案<script src="script.js"></script>
腳本頁面裡的區塊<script> ... </script>

最極端的情況是全部擠在一起:標記、<style> 區塊和 <script> 區塊都住在同一個 index.html 裡。這沒什麼好怕的,小頁面這樣寫反而更簡單:只有一個檔案,用瀏覽器打開就能動,路上什麼都不會弄丟。麻煩是後來才開始的:頁面越長越大,要在這一大串內容裡找東西就很吃力。這時通常會把內容拆到不同檔案,於是就成了那熟悉的三件組。

在請代理 "改樣式" 之前,先弄清楚樣式放在哪裡。如果專案裡只有一個 index.html,可能根本沒有 style.css 檔案,修改會落在標記裡面。如果元素改不動,請代理檢查三件事:需要的樣式檔有沒有引入、選擇器對不對得上,以及有沒有行內 style 或優先順序更高的規則。這樣不必猜是誰的錯,也能縮小搜尋範圍。

和 Claude Code 搭配時怎麼運作

現在您就明白,代理接手一個頁面時發生了什麼:

  • 在簡單的靜態專案中,代理可以自己寫好 HTML、CSS 和 JavaScript 並把它們串起來。換成別的專案,先請它列出結構,說出負責目標元素的是哪些檔案;
  • 寫入之前能看到什麼,取決於設定和工作模式。如果代理事先顯示修改提案,請看一遍;無論如何,寫入之後都要檢查 diff 和最終的檔案。style.css 這個名字提示了檔案的角色,但什麼也不保證;
  • 視覺上的修改,要用眼睛看、實際點一點受影響的元素來檢查;行為上的修改,要靠實際操作來檢查。截圖看不出計數器已經不會計數了;
  • 如果有東西壞了,請描述觀察到的現象,而不是您猜測出問題的那一層:"修改後按鈕看得到,但點了沒反應"。這樣代理就會去檢查 HTML、CSS 和 JavaScript 之間的關聯。