UrsaKit 封面圖:說明 HTML 文件的結構

HTML 是一門寬容的語言,而這正是標記錯誤能存活下來的原因:瀏覽器會默默修好你寫的東西,於是頁面看起來正常,文件卻不是你想的那個樣子。這篇講一份文件真正需要的結構、哪些部分可選但重要,以及那些幾週後才變成版面問題的錯誤。

文中每個範例都可以在 UrsaKit 的 HTML 網上工具 上試,它會邊打字邊在沙箱預覽中渲染你的標記。

01瀏覽器很寬容,這才是問題

把沒關閉的 <div>、儲存格對不上的表格,或巢狀在段落裡的段落丟給瀏覽器,它不會報錯——它會猜。HTML 解析算法之所以被規定得如此詳細,正是因為這些猜測必須在每個瀏覽器上一致。

實際的缺點是:你拿到的 DOM 不一定是你寫的 DOM。<p> 裡再放 <p> 會讓第一個段落提前結束,<table> 裡的 <div> 會被移到表格外面,<ul> 裡不合法的巢狀會變成文字節點。

唯一可靠的方式是檢查渲染後的 DOM,而不是原始檔。每個瀏覽器的開發者工具都能看到解析後的樹。

02每份文件都需要的五行

<!doctype html>
<html lang="zh-Hant">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>頁面標題</title>
  </head>
  <body>
    <h1>一個標題,說明這個頁面</h1>
  </body>
</html>

每一行都有它在你拿掉之前看不見的作用:

  • <!doctype html> 讓瀏覽器離開 quirks mode。少了它,盒模型、百分比高度與行高都會走舊規則。
  • lang 告訴屏幕閱讀器該用哪種發音,也讓瀏覽器正確斷字。請填真實的語言標籤,例如 zh-Hant 或 es。
  • charset 必須放在 head 的第一位。放錯位置或寫錯,所有非 ASCII 字元都會變成亂碼。
  • viewport 是頁面對流動裝置友善的關鍵;少了它,手機會以模擬的 980 像素寬度渲染。
  • title 是分頁、書籤與搜尋結果上的標籤。

一個頁面只留一個 h1。

h1 是這個頁面的主題。如果每一區都用 h1 開頭,搜尋引擎與屏幕閱讀器用戶都無法判斷頁面在講什麼。區段用 h2,區段裡的小節用 h3。

03head 與 body 的分工

head 放的是關於文件的資訊,body 放的是用戶看到的內容。把兩者混在一起,是困惑最常見的來源之一。

屬於 head屬於 body
title、meta、linkh1–h6、p、ul
整頁適用的 style用戶會閱讀或點擊的元素
加上 defer 的 script放在 body 結尾的 script
favicon 與 preload 提示template 與 noscript 備援

放在 head 的內容不會被渲染;該放 head 卻寫在 body 的標記會被搬移或忽略。如果某個樣式表連結看起來完全沒作用,先確認它是不是跑進 body 了。

04空元素與跳脫

有些元素沒有內容、也沒有結束標籤,稱為空元素。寫出 </img> 是解析錯誤,只是瀏覽器願意忍受。

<img src="/logo.png" alt="UrsaKit 標誌" width="1161" height="389" />
<input type="email" name="email" required />
<br />
<hr />
<meta charset="utf-8" />

兩條規則就涵蓋了大多數跳脫錯誤:

  • & 會開始一個實體。 想顯示字面上的 & 就寫 &amp;,否則 & 可能被當成字元引用的開頭而改變文字。
  • 屬性裡的引號。 屬性值用雙引號包起來,內部的雙引號寫成 &quot;,或把該屬性改用單引號。

圖片一定要同時設定 width 與 height。瀏覽器會在檔案下載完成前先保留空間,避免版面位移破壞閱讀位置與 Core Web Vitals。

05語意元素到底改變了什麼

section、article、nav 與 div 渲染出來都是沒有預設樣式的區塊。選哪一個不影響畫素,所以很多團隊乾脆全部用 div。但這個交換是有代價的:

  • 屏幕閱讀器只能在標記有定義地標時,才能在地標之間跳轉。
  • 爬蟲靠標題與地標判斷頁面的主要內容在哪裡。
  • 你自己的 CSS 與測試會得到 nav ul 這種選擇器,而不是 .wrapper-3 ul。
元素用在哪
header / footer頁面或區段的開頭與結尾內容
nav一組導覽連結
main唯一的內容主體,每頁一次
article單獨拿出來也說得通的內容
section有自己標題的主題群組
div只是為了樣式而存在的容器

06七個值得修掉的標記錯誤

錯誤實際發生什麼修正
沒有 doctypeQuirks mode 改變盒模型與高度規則加上 <!doctype html>
lang 缺少或錯誤發音與斷字都不正確填真實的語言標籤
charset 不在 head 第一位非 ASCII 文字變亂碼把 meta charset 放最前面
<table> 裡放 <div>div 被移到表格外用 thead、tbody、tr、td
p 裡放區塊元素段落提前結束先關段落,再開區塊
head 裡的 script 沒加 defer解析要等下載並執行完加上 defer 或移到結尾
id 重複getElementById 與 label 只會抓到第一個保持 id 唯一

07不用建置流程就能測標記

  1. 貼上完整文件或片段 — HTML 工具 兩者都收。片段會自動包成最小文件,方便單獨檢查一個元件。
  2. 邊打字邊看預覽 — 預覽在沙箱框架中渲染,腳本可以執行,卻不會碰到工具本身的頁面。
  3. 比對 DOM,而不是你的原始碼 — 看起來不對時,直接在預覽裡檢查元素。瀏覽器會修標記,只有解析後的樹能告訴你真正建出了什麼。
  4. 接著處理樣式 — 結構對了之後,把同一份標記帶進 CSS 網上編輯器 調版面,或在 JavaScript 網上執行器 上跑行為。

從一開始就把結構寫對,比事後發現某個版面 bug 其實是 HTML bug 便宜得多。

常見問題

還需要寫 doctype 嗎?

要。少了它,瀏覽器會進入 quirks mode,盒模型與行高改用舊規則,版面會以很難追查的方式壞掉。

html、head、body 可以省略嗎?

瀏覽器會自己補上,但請明確寫出來。隱含的元素在原始碼裡看不見,除錯比多打四個標籤更慢。

lang 屬性會改變什麼?

它告訴屏幕閱讀器該用哪種語言發音、讓瀏覽器正確斷字與引用,也幫助搜尋引擎判斷頁面語言。

script 標籤該放哪裡?

放在 head 裡並加上 defer,或放在 body 結尾。直接放在 head 的 script 會在下載與執行完成前阻塞解析。

HTML 可以用自我閉合標籤嗎?

對 img、br 這類空元素來說,結尾斜線會被忽略,所以 img src="x" / 合法但沒有意義;加在非空元素上則是解析錯誤。

語意化標記會改變外觀嗎?

不會。section、article 與 div 渲染結果完全相同。語意改變的是輔助科技與爬蟲理解到的內容,也讓 CSS 與 JavaScript 有更明確的掛鉤。

返回文章列表

相關文章

相關工具