12. 連結外部資源 (Linking Resources)

網頁經常需要樣式表、JavaScript 檔案、圖片、字型及圖示等資源。

HTML 使用不同元素載入或參照這些資源:

資源常用 HTML 元素
外部樣式表<link rel="stylesheet">
JavaScript 檔案<script src="…">
圖片<img src="…">
網站圖示<link rel="icon">
音訊<audio>
影片<video>
導覽目的地<a href="…">

應按資源的用途選擇元素。 建立通往樣式表的超連結,不會將該樣式表套用至網頁。

12.1 資源連結與超連結

錨點元素建立可以前往目的地的連結:

<a href="styles/main.css">查看樣式表</a>

樣式表連結則要求瀏覽器載入並套用 CSS:

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

雖然兩者都使用 href,但職責不同。

<link> 通常放在 <head> 內。它是空元素,不需要結束標籤。

12.2 連結外部樣式表

將樣式表參照放在文件的 <head> 內:

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>課程指南</title>
  <link rel="stylesheet" href="styles/main.css">
</head>

各屬性的意思:

  • rel="stylesheet" 標示文件與資源之間的關係。
  • href 指定資源位置。

被參照的檔案只包含 CSS,不包含 <style> 標籤:

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

h1 {
  color: #005ea8;
}

外部樣式表可以在多個網頁之間重用,也可以由瀏覽器快取。

現代 HTML 不需要加入 type="text/css"。

12.3 多個樣式表與媒體條件

同一網頁可以載入多個樣式表:

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

當宣告的其他層疊優先條件及特異性相同時,較後的宣告會勝出。檔案排列次序不是 CSS 層疊的唯一因素。

樣式表也可以只在符合媒體條件時套用:

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

這個樣式表會在列印或產生列印預覽時套用。

media 控制樣式是否適用;不要假設它會阻止瀏覽器下載檔案。

12.4 連結 JavaScript 檔案

使用具有 src 的 <script>:

<script src="scripts/main.js" defer></script>

與 <link> 不同,<script> 需要結束標籤。

JavaScript 檔案只包含 JavaScript,不包含 <script> 標籤:

const heading = document.querySelector("h1");

if (heading) {
  console.log(heading.textContent);
}

對傳統外部指令碼而言,defer 允許瀏覽器在繼續剖析 HTML 時下載檔案。指令碼會在剖析完成後、DOMContentLoaded 事件之前執行。

多個具有 defer 的傳統指令碼,會按文件次序執行。

不要在已有 src 的 <script> 元素內加入行內 JavaScript。有需要時,使用另一個獨立的 <script> 元素。

12.5 defer、async 與模組

指令碼的載入方式會影響效能及執行次序。

寫法一般行為
沒有 async 或 defer 的傳統指令碼載入及執行期間暫停 HTML 剖析
具有 defer 的傳統外部指令碼剖析期間下載;剖析完成後按文件次序執行
具有 async 的傳統外部指令碼剖析期間下載;準備好便執行,不保證文件次序
模組指令碼預設延後執行;支援匯入及模組作用域

延後執行的指令碼

<script src="scripts/main.js" defer></script>

對需要操作網頁內容的傳統指令碼,這是實用的預設選擇。

非同步指令碼

<script src="scripts/independent-widget.js" async></script>

async 適合不依賴特定執行次序的獨立指令碼。它可能在網頁尚未完成剖析時執行。

JavaScript 模組

<script type="module" src="scripts/main.js"></script>

模組指令碼預設延後執行,因此不需要再加入 defer。如果加入 async,載入及執行行為則會有所不同。

模組專案應透過本機網頁伺服器提供,不要依賴 file: URL。模組也需要正確的伺服器 MIME 類型;跨來源載入時,還需要適當的 CORS 權限。

12.6 連結圖片

使用 <img> 顯示圖片:

<img
  src="images/classroom.jpg"
  alt="學生在課室內練習 HTML"
  width="800"
  height="450"
>

重要屬性包括:

屬性用途
src圖片位置
alt替代文字
width 和 height提供尺寸資訊,協助預留版面空間
loading載入提示,例如 lazy

對初始可視範圍下方的圖片,可以使用:

<img
  src="images/practice-session.jpg"
  alt="學習者正在編輯 HTML 文件"
  width="800"
  height="450"
  loading="lazy"
>

不要自動為首屏的主要圖片加入延遲載入,否則可能延誤重要的可見內容。

裝飾性圖片應使用 alt=""。

12.7 連結網站圖示

網站圖示通常稱為 favicon,可以出現在瀏覽器分頁及書籤中:

<link rel="icon" href="images/favicon.svg" type="image/svg+xml">

PNG 版本可以標示尺寸:

<link
  rel="icon"
  href="images/favicon-32.png"
  type="image/png"
  sizes="32x32"
>

宣告的類型及尺寸應與實際檔案相符。

瀏覽器快取可能令開發期間的圖示更新較慢。如果舊圖示仍然顯示,應檢查資源 URL 及快取行為。

12.8 理解資源路徑

假設專案結構如下:

website/
├── index.html
├── courses/
│   └── html-basics.html
├── styles/
│   └── main.css
├── scripts/
│   └── main.js
└── images/
    ├── classroom.jpg
    └── favicon.svg

從 index.html 出發:

<link rel="stylesheet" href="styles/main.css">
<script src="scripts/main.js" defer></script>
<img src="images/classroom.jpg" alt="一間空置課室">

從 courses/html-basics.html 出發:

<link rel="stylesheet" href="../styles/main.css">
<script src="../scripts/main.js" defer></script>
<img src="../images/classroom.jpg" alt="一間空置課室">

HTML 中一般的相對 URL,會根據文件的基底 URL 解析;通常就是文件本身的 URL。

外部 CSS 內的 URL

外部樣式表中的相對 URL,會根據樣式表的 URL解析,而不是 HTML 網頁的位置:

/* 位於 styles/main.css */
.banner {
  background-image: url("../images/classroom.jpg");
}

這項分別是資源路徑失效的常見原因。

12.9 <base> 元素

<base> 可以改變文件內相對 URL 的解析方式:

<base href="https://example.com/learning/">

使用這個基底 URL 時:

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

會解析為:

https://example.com/learning/styles/main.css

應小心使用 <base>:

  • 它會影響整份文件內的相對連結及資源參照。
  • 它可能改變 href="#requirements" 等片段連結的行為。
  • 應放在需要依靠它解析相對 URL 的元素之前。
  • 一份文件最多使用一個 <base>。

大部分初學者專案都不需要它。

12.10 資源載入提示

載入提示可以幫助瀏覽器提早處理重要資源,但應有選擇地使用。

預先載入:preload

preload 要求瀏覽器提早取得目前網頁需要的資源:

<link
  rel="preload"
  href="fonts/course-sans.woff2"
  as="font"
  type="font/woff2"
  crossorigin
>

as 值描述資源類型。

預先載入本身不會套用樣式表、執行指令碼或使用字型。網頁仍然需要以適當方式參照該資源。

字型預先載入需要與實際使用時相符的 CORS 行為,通常透過 crossorigin 指定,即使是同來源字型也一樣。

預先連線:preconnect

preconnect 要求瀏覽器預先準備通往某個來源的連線:

<link rel="preconnect" href="https://cdn.example.com">

如果網頁很快便會向該來源請求重要資源,這可能有所幫助。

不要預先載入每個檔案,也不要向每個網域預先連線。不必要的提示可能浪費頻寬及連線資源。

12.11 外部資源、安全與私隱

第三方資源會增加額外依賴。

應考慮:

  • 提供者是否可信。
  • 資源是否必要。
  • 請求會透露哪些訪客資訊。
  • 提供者無法使用時,網頁是否仍然可用。
  • 資源版本是否可能在未預期的情況下改變。

HTTPS 網頁應使用 HTTPS 資源。視乎資源類型及瀏覽器政策,不安全的 HTTP 資源可能被封鎖或自動升級。

子資源完整性:SRI

對適用的外部指令碼及樣式表,**子資源完整性(Subresource Integrity,SRI)**讓瀏覽器將取得的內容與預期的密碼學雜湊值比較。

它使用 integrity 屬性。跨來源 SRI 也需要適當的 CORS 支援,通常包括元素上的 crossorigin="anonymous",以及相容的伺服器回應。

必須使用與確切檔案版本相符的雜湊值。錯誤的雜湊值會令瀏覽器拒絕該資源。

不要虛構雜湊值,也不要複製其他版本的雜湊值。

12.12 完整範例:資源連結參考頁

以下獨立網頁使用內嵌 CSS,不需要附屬檔案便能呈現。它將多檔案專案所需的資源標記顯示為參考文字,不會實際載入所列出的外部檔案。

id: hong-kong-html-linking-resources
name: 連結外部資源 — 專案參考頁
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 專案參考</title>

    <!-- 內嵌 CSS 讓這個教學範例保持獨立。 -->
    <style>
      * {
        box-sizing: border-box;
      }

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

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

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

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

      section > :last-child {
        margin-block-end: 0;
      }

      pre {
        max-width: 100%;
        overflow-x: auto;
        padding: 1rem;
        border: 1px solid #767676;
        border-radius: 0.25rem;
        background: #edf1f5;
        line-height: 1.6;
      }

      code {
        font-family: ui-monospace, monospace;
      }

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

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

      .note {
        padding: 1rem;
        border-inline-start: 4px solid #005ea8;
        background: #eaf2f8;
      }
    </style>
  </head>
  <body>
    <main>
      <h1>連結專案資源</h1>
      <p>
        使用正確的元素,將 HTML 連接至樣式表、
        指令碼及圖片。
      </p>

      <p class="note">
        以下程式碼只作參考,並未載入所列出的外部檔案。
        實際使用時,請先建立對應檔案並檢查路徑。
      </p>

      <nav aria-label="本頁目錄">
        <ul>
          <li><a href="#project-files">專案檔案</a></li>
          <li><a href="#head-resources">head 內的資源</a></li>
          <li><a href="#image-resource">圖片資源</a></li>
        </ul>
      </nav>

      <section>
        <h2 id="project-files">專案檔案</h2>
        <pre tabindex="0" aria-label="專案資料夾結構"><code>website/
  ├── index.html
  ├── styles/
  │   └── main.css
  ├── scripts/
  │   └── main.js
  └── images/
      ├── classroom.jpg
      └── favicon.svg</code></pre>
        <p>
          以下例子假設這些檔案已存在,
          而 HTML 網頁是 <code>index.html</code>。
        </p>
      </section>

      <section>
        <h2 id="head-resources">head 內的資源</h2>
        <p>
          將以下參照放在文件的
          <code><head></code> 內。
        </p>
        <pre tabindex="0" aria-label="資源連結程式碼"><code><link rel="stylesheet" href="styles/main.css">

  <link rel="icon"
        href="images/favicon.svg"
        type="image/svg+xml">

  <script src="scripts/main.js" defer></script></code></pre>
        <p>
          樣式表提供 CSS,圖示識別網站,
          而延後執行的指令碼會在 HTML 剖析完成後執行。
        </p>
      </section>

      <section>
        <h2 id="image-resource">圖片資源</h2>
        <p>將圖片放在網頁內容中合適的位置。</p>
        <pre tabindex="0" aria-label="圖片標記"><code><img
    src="images/classroom.jpg"
    alt="學生在課室內練習 HTML"
    width="800"
    height="450"
  ></code></pre>
        <p>
          尺寸應與實際圖片相符,
          替代文字則應配合圖片的用途。
        </p>
      </section>
    </main>
  </body>
  </html>

在這個範例中:

  • 資源標記經過 HTML 跳脫處理,只顯示為文字,不會執行。
  • 不會請求不存在的外部檔案。
  • 頁內導覽不需要 JavaScript。
  • 可捲動的程式碼範例可以取得鍵盤焦點。
  • 資料夾結構說明相對路徑如何解析。

在實際的多檔案專案中,可以將網頁 CSS 移至樣式表,並以適當的樣式表連結取代內嵌 <style> 區塊。

12.13 排解資源載入問題

如果資源無法載入:

  1. 檢查檔案名稱、副檔名及大小寫。
  2. 從正確的基底位置解析路徑。
  3. 確認檔案存在於伺服器上。
  4. 在瀏覽器的 **Network(網絡)**面板檢查失敗的請求。
  5. 在 **Console(主控台)**檢查指令碼、CORS 或安全錯誤。
  6. 確認伺服器傳送正確的內容類型。
  7. 檢查快取是否仍在提供舊版本。

不存在的資源有時會收到 HTML 錯誤頁,而不是預期的 CSS 或 JavaScript。不要只看 URL,也應檢查回應內容。

12.14 常見錯誤

錯誤較好的做法
使用 <a> 套用 CSS使用 <link rel="stylesheet">
遺漏 rel="stylesheet"標示資源關係
在 CSS 檔案內加入 <style> 標籤只寫 CSS
在 JavaScript 檔案內加入 <script> 標籤只寫 JavaScript
將 script 元素寫成自我結束標籤加入 </script>
對依賴執行次序的指令碼使用 async使用適當的延後執行或模組模式
按 HTML 位置解析 CSS 圖片路徑按樣式表 URL 解析
以為 preload 會套用或執行資源同時提供正常的使用參照
加入大量不必要的載入提示只優化已確認的重要資源
在 HTTPS 網頁連結不安全資源使用 HTTPS
使用錯誤的完整性雜湊值配合確切資源版本
忽略第三方私隱及可用性問題加入前先評估依賴

本章總結: 使用 <link> 連結樣式表、<script> 連結指令碼,以及 <img> 顯示圖片。理解相對路徑及載入行為,選擇可信的依賴,並使用瀏覽器開發者工具排解失敗的請求。

Scroll to Top