<iframe> 將另一份 HTML 文件嵌入目前網頁。
它建立巢狀瀏覽環境(nested browsing context):一份具有自身內容、導覽及可能包含程式碼的獨立文件。
常見用途包括:
- 第三方影片播放器。
- 地圖。
- 外部小工具。
- 文件預覽。
- 隔離的示範內容。
<iframe
src="course-preview.html"
title="課程預覽"
width="640"
height="360"
></iframe>iframe 不只是視覺容器。 它會載入獨立文件,因此需要考慮無障礙功能、安全、私隱及效能。
29.1 基本語法
iframe 需要開始標籤及結束標籤:
<iframe
src="course-preview.html"
title="課程預覽"
></iframe>它不是空元素。
一般 HTML 中,不要使用自行關閉語法:
<!-- HTML 中的錯誤寫法:這不會關閉 iframe。 -->
<iframe src="course-preview.html" />嵌入文件不會成為父頁面 DOM 中的一般子內容。它具有自己的文件結構。
29.2 重要屬性
| 屬性 | 用途 |
|---|---|
src | 要嵌入的文件 URL |
srcdoc | 行內嵌入文件的 HTML 原始碼 |
title | 為框架提供描述性識別 |
width / height | 顯示尺寸,以 CSS 像素為單位 |
loading | 要求立即或延遲載入 |
sandbox | 對嵌入文件施加限制 |
allow | 設定特定瀏覽器功能的權限 |
referrerpolicy | 控制取得框架時傳送的來源頁面資訊 |
name | 為瀏覽環境命名,供導覽目標使用 |
allowfullscreen | 允許全螢幕請求,但仍受適用政策限制 |
只使用嵌入內容實際需要的屬性。
frameborder、marginwidth 和 marginheight 等屬性已過時。呈現樣式應使用 CSS。
29.3 src 屬性
src 識別要載入的文件:
<iframe
src="course-preview.html"
title="HTML 課程預覽"
></iframe>URL 可以是相對或絕對路徑。
遠端網頁不一定允許嵌入,可能因以下原因拒絕:
- 安全回應標頭。
- 身分驗證要求。
- 瀏覽器私隱限制。
- 你的網頁安全政策。
- 其他伺服器或網絡情況。
對第三方服務,應使用其文件指定的嵌入 URL,而不是假設一般網頁 URL 可以使用。
例如,影片服務的觀看頁面與嵌入播放器 URL 可能不同。
29.4 為框架提供描述性標題
提供簡潔標題,識別框架用途:
<iframe
src="map.html"
title="顯示培訓中心位置的地圖"
></iframe>避免沒有幫助的標題,例如:
- 「Iframe」
- 「嵌入內容」
- 「網頁」
有意義的標題能幫助輔助技術使用者區分框架,並決定是否進入。
不過,iframe 的標題不會令內部內容自動符合無障礙需要。嵌入文件仍然需要適當標題、標籤、文字替代、鍵盤操作及其他無障礙功能。
iframe 的 title 屬性與嵌入文件的 <title> 元素用途不同。如果你能控制嵌入頁面,應同時提供兩者。
29.5 替代方式與後備內容
不要依靠 iframe 標籤之間的內容,在現代瀏覽器中提供可見後備內容:
<!-- 這不是可靠的可見後備內容。 -->
<iframe src="course-preview.html" title="課程預覽">
<p>暫時無法使用預覽。</p>
</iframe>應將有用替代方式放在 iframe 之外:
<p>
<a href="course-preview.html">直接開啟課程預覽</a>。
</p>
<iframe
src="course-preview.html"
title="課程預覽"
></iframe>地圖也應在一般 HTML 中提供地址及交通指引。
影片應提供相關字幕、文字稿或其他無障礙替代內容。
不要讓 iframe 成為取得重要資訊的唯一方式。
29.6 使用 srcdoc 提供行內文件
srcdoc 直接提供 HTML:
<iframe
title="標題及段落範例"
sandbox
srcdoc="<!doctype html>
<html lang="zh-Hant-HK">
<head>
<meta charset="utf-8">
<title>HTML 範例</title>
</head>
<body>
<h1>你好</h1>
<p>這是一份獨立文件。</p>
</body>
</html>"
></iframe>因為 HTML 放在屬性內,引號及其他相關字元必須適當轉義。
重要事項包括:
- 瀏覽器支援且存在
srcdoc時,它會優先於src。 srcdoc文件中的相對 URL,通常根據嵌入它的文件 URL 解析。- 沒有適當沙箱限制時,
srcdoc文件可以與父頁面共享來源。 - 將不可信 HTML 指派給
srcdoc,可能造成注入漏洞。
不要將 srcdoc 視為安全顯示任意使用者內容的方式。應採取適當的內容清理及隔離措施。
29.7 sandbox 屬性
sandbox 限制嵌入文件:
<iframe
src="static-preview.html"
title="靜態課程預覽"
sandbox
></iframe>空的 sandbox 會套用整套沙箱限制。其中包括限制執行程式碼、提交表單、開啟彈出視窗及導覽頂層頁面,並將文件視為具有不透明來源(opaque origin)。
可以使用權限關鍵字,選擇性放寬限制:
| 關鍵字 | 放寬的限制 |
|---|---|
allow-scripts | 執行程式碼 |
allow-forms | 提交表單 |
allow-same-origin | 保留資源原本的來源 |
allow-popups | 開啟輔助瀏覽環境 |
allow-downloads | 啟動下載 |
allow-top-navigation-by-user-activation | 使用者啟動操作後導覽頂層頁面 |
例如:
<iframe
src="interactive-preview.html"
title="互動課程預覽"
sandbox="allow-scripts"
></iframe>這允許執行程式碼,同時保留其他沙箱限制。
只授予嵌入內容實際需要的能力。 應測試結果,因為沙箱限制可能停用嵌入頁面預期使用的功能。
沙箱不會阻止所有網絡請求,也不會令任意內容變得無害。
29.8 需要特別注意的沙箱組合
對以下組合應特別小心:
sandbox="allow-scripts allow-same-origin"allow-same-origin 不會令遠端網頁與你的頁面共享來源。它只是讓嵌入資源保留原本的來源,而不是取得不透明來源。
不過,如果嵌入文件本來就與父頁面同來源,同時允許執行程式碼及同來源存取,可能讓它存取嵌入元素、移除 sandbox 屬性,然後重新載入以解除限制。
因此:
- 不要將這個組合用作不可信同來源內容的安全邊界。
- 考慮從獨立來源提供不可信內容。
- 檢查完整隔離設計,而不是只依靠一個屬性。
沙箱是有用工具,但不能取代審慎的信任判斷。
29.9 使用 allow 設定權限
allow 透過權限政策(Permissions Policy),控制特定瀏覽器功能的存取:
<iframe
src="video-player.html"
title="HTML 入門影片播放器"
allow="fullscreen"
></iframe>其他功能可以包括攝影機、麥克風及地理位置。
除非應用程式需要,否則不要授予這些權限。
重要區別包括:
allow設定功能權限。sandbox限制文件能力。- 兩者不能互相取代。
- 回應標頭及瀏覽器政策也可以限制權限。
- 允許功能,不會繞過必要的使用者授權提示。
全螢幕設定也可能使用布林屬性 allowfullscreen:
<iframe
src="video-player.html"
title="HTML 入門影片播放器"
allowfullscreen
></iframe>應使用服務提供者建議的設定,再檢查每項要求的能力是否必要。
29.10 同來源限制
同來源政策通常會阻止父頁面讀取或修改跨來源 iframe 的文件。
來源由通訊協定、主機及連接埠的組合決定。
對允許存取的同來源框架,程式碼可能如下:
const frame = document.getElementById("preview");
frame.addEventListener("load", () => {
const documentInsideFrame = frame.contentDocument;
if (documentInsideFrame) {
console.log(documentInsideFrame.title);
}
});跨來源或受到適當沙箱限制的框架,會限制這類文件存取。
合作文件需要跨來源通訊時,應使用 postMessage,並:
- 可行情況下,明確指定預期的目標來源。
- 檢查收到訊息的
origin。 - 檢查其
source。 - 驗證訊息結構及內容。
不要只因訊息透過 message 事件到達,就信任它。
29.11 私隱、來源頁面資訊與嵌入政策
第三方 iframe 可能在訪客操作之前就發起請求。
這些請求可能透露訪客的 IP 地址,並涉及 Cookie 或其他儲存機制,但仍受瀏覽器限制。
對非必要外部內容,應考慮由使用者啟動嵌入載入。
可以限制傳送的來源頁面資訊:
<iframe
src="external-preview.html"
title="外部課程預覽"
referrerpolicy="no-referrer"
></iframe>這本身不會令請求匿名,也不會阻止追蹤。
兩個內容安全政策指令處理不同的嵌入問題:
| 指令 | 控制 |
|---|---|
frame-src | 你的頁面可以載入哪些框架資源 |
frame-ancestors | 哪些頁面可以嵌入你的文件 |
例如,回應標頭可以禁止其他頁面以框架嵌入文件:
Content-Security-Policy: frame-ancestors 'none'frame-ancestors 必須透過 HTTP 回應標頭提供,不支援放在 CSP <meta> 元素內。
較舊的 X-Frame-Options 回應標頭也可以限制嵌入。
不要嘗試繞過其他網站的嵌入限制。
29.12 響應式尺寸與延遲載入
使用 CSS 控制框架版面:
.video-frame {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
border: 0;
}文件或應用程式預覽可能更適合使用明確高度:
.document-frame {
display: block;
width: 100%;
height: 30rem;
border: 1px solid #767676;
}父頁面的 CSS 不會自動套用至 iframe 內的文件。
iframe 也不會自動調整至內部文件的內容高度。這類行為可能需要雙方協調的程式碼。
對螢幕範圍之外的內容,可以要求延遲載入:
<iframe
src="course-preview.html"
title="課程預覽"
loading="lazy"
width="640"
height="360"
></iframe>loading="lazy" 是由瀏覽器管理的載入提示,不保證完全沒有初始請求。應預留足夠版面空間,減少內容載入時的位移。
29.13 完整範例:沙箱 HTML 預覽
以下獨立網頁在具有沙箱限制的 iframe 內,顯示簡短行內文件。
它不使用外部資源,也不授予任何沙箱例外權限。iframe 用來示範文件分離,而不是互動應用程式。
id: hong-kong-html-iframes
name: 內嵌框架 — 沙箱 HTML 預覽
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>
<style>
*,
*::before,
*::after {
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,
h3 {
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 > h2 {
margin-block-start: 0;
}
.note {
padding: 1rem;
border-inline-start: 4px solid #005ea8;
background: #eaf2f8;
}
.preview-frame {
display: block;
width: 100%;
height: 22rem;
border: 1px solid #767676;
background: white;
}
a {
color: #005ea8;
text-decoration: underline;
text-underline-offset: 0.2em;
}
:focus-visible {
outline: 3px solid #005ea8;
outline-offset: 3px;
}
[id] {
scroll-margin-block-start: 1rem;
}
</style>
</head>
<body>
<main>
<h1>沙箱 HTML 預覽</h1>
<p class="note">
下方預覽是一份獨立 HTML 文件。
空的 sandbox 屬性會套用限制,
不授予任何例外權限。
</p>
<p>
頁面亦提供相同內容的文字版本。
</p>
<section aria-labelledby="preview-heading">
<h2 id="preview-heading">嵌入預覽</h2>
<p>
你也可以
<a href="#text-version">閱讀下方的文字版本</a>。
</p>
<iframe
class="preview-frame"
title="HTML 入門課程預覽"
width="640"
height="352"
sandbox
srcdoc="<!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>
<style>
body {
margin: 0;
padding: 1.25rem;
color: #222;
background: #fff;
font-family: system-ui, sans-serif;
line-height: 1.8;
}
h1 {
color: #005ea8;
font-size: 1.5rem;
line-height: 1.4;
}
</style>
</head>
<body>
<h1>HTML 入門課程</h1>
<p>學習建立清晰、符合無障礙需要的網頁。</p>
<ul>
<li>使用有意義的標題組織內容。</li>
<li>為表單控制元素提供標籤。</li>
<li>為有意義的圖片加入文字替代。</li>
</ul>
</body>
</html>"
></iframe>
</section>
<section aria-labelledby="text-version">
<h2 id="text-version">預覽的文字版本</h2>
<h3>HTML 入門課程</h3>
<p>學習建立清晰、符合無障礙需要的網頁。</p>
<ul>
<li>使用有意義的標題組織內容。</li>
<li>為表單控制元素提供標籤。</li>
<li>為有意義的圖片加入文字替代。</li>
</ul>
</section>
</main>
</body>
</html>在這個範例中:
srcdoc提供完整嵌入文件。- iframe 具有描述性的
title。 - 嵌入文件具有自己的語言及文件標題。
- 空的
sandbox套用限制,不授予例外權限。 - 內部文件定義自己的樣式。
- CSS 讓框架符合父頁面的可用寬度。
- 框架之外提供相同內容。
- 不需要程式碼或第三方請求。
預覽高度是固定的。如果內部內容增加或文字放大,框架可能需要捲動;外部文字版本仍然可用。
29.14 常見錯誤
| 錯誤 | 較好的做法 |
|---|---|
| 在 HTML 中使用 iframe 自行關閉語法 | 明確寫出結束標籤 |
| 省略描述性標題 | 識別框架用途 |
| 以為標題能修復無障礙內容問題 | 讓嵌入文件本身也符合無障礙需要 |
| 將重要後備文字放在 iframe 標籤之間 | 將替代內容放在 iframe 之外 |
| 未經檢查就嵌入一般服務 URL | 使用文件指定的嵌入 URL |
| 授予所有沙箱例外權限 | 只允許必要能力 |
| 將程式碼加同來源存取視為可靠隔離 | 檢查來源及沙箱設計 |
將 allow 和 sandbox 視為相同功能 | 分別設定權限及限制 |
將不可信 HTML 注入 srcdoc | 適當清理及隔離內容 |
| 以為父頁面 CSS 會套用至框架內容 | 分別設定嵌入文件樣式 |
| 未經驗證就信任跨來源訊息 | 檢查來源、發送視窗及訊息資料 |
將 iframe 的 load 事件當成成功證明 | 驗證實際內容及可用性 |
| 立即載入非必要第三方嵌入內容 | 考慮延遲或由使用者啟動載入 |
| 使用過時呈現屬性 | 使用 CSS |
本章總結: <iframe> 嵌入的是獨立文件,而不是一般子內容。應提供描述性標題、無障礙替代內容及適當尺寸。嵌入外部或不可信內容之前,應檢查沙箱限制、功能權限、來源邊界、私隱及載入行為。















