首頁
學習紀錄
遊戲心得影視Life書單案件檔案
Side Projects委託作品與二創互動實驗場
Kurau
百百 BLOG
首頁
學習紀錄
遊戲心得影視Life書單案件檔案
Side Projects委託作品與二創互動實驗場
Kurau

Kurau Blog

「隨心而寫,真真假假,都是我」

一個記錄生活、輸出興趣的個人空間。
遊戲、影視、閱讀、學習……每一段體驗都值得留下文字。

頁面導覽

  • 學習紀錄
  • 遊戲心得
  • 影視Life
  • 書單
  • 委託作品與二創
  • Kurau
  • 合作邀請

找到我

歡迎來 Discord 找我聊天!

“曾經發生的事不可能忘記,只是暫時想不起來而已。”-《神隱少女》

© 2026 Kurau All rights reserved

前端基礎

iframe 嵌入

By Kurau·2024-02-29·Updated 2026-05-09·5 分鐘閱讀

iframe 嵌入

TL;DR
iframe 兩大痛點:無法自動抓內容高度 + 跨域時無法直接存取 DOM。前者用 iframe-resizer 解,後者用 postMessage 解。

基本使用

<iframe
  src="https://example.com"
  width="100%"
  height="500"
  loading="lazy"
  referrerpolicy="strict-origin-when-cross-origin"
  sandbox="allow-scripts allow-same-origin"
></iframe>
html
屬性建議
  • loading="lazy" — iframe 進入視窗才載入,省巨量頻寬
  • frameborder 已 deprecated,改用 CSS border: 0
  • sandbox 列白名單,不寫就完全限制(連 JS 都不能跑)

痛點 1:高度自適應

原生 iframe 無法自動調整高度 —— 因為瀏覽器要保護跨域內容,父頁面看不到 iframe 內部 DOM 高度。

同源情況(可以自己讀高度)

const iframe = document.querySelector('iframe');
iframe.addEventListener('load', () => {
  const height = iframe.contentWindow.document.body.scrollHeight;
  iframe.style.height = height + 'px';
});
javascript

跨域情況(必須用套件 / postMessage)

直接讀 contentWindow.document 會被 Same-Origin Policy 擋下。解法:

React 推薦套件:iframe-resizer-react

import IframeResizer from 'iframe-resizer-react';

<IframeResizer
  src="https://example.com"
  style={{ width: '100%', minHeight: '500px' }}
  checkOrigin={false}    // 跨域時設 false
/>
tsx

運作原理:套件會在 iframe 內注入一個 script,內部監聽尺寸變化後用 postMessage 通知父頁面更新高度。


痛點 2:跨域通訊 — postMessage

iframe 內外無法直接互相讀 DOM,但可以用 postMessage 安全傳訊息。

父頁面 → iframe

const iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage(
  { type: 'INIT', payload: { theme: 'dark' } },
  'https://target-origin.com'    // ⚠️ 永遠寫明確 origin,別用 '*'
);
javascript

iframe → 父頁面

window.parent.postMessage({ type: 'READY' }, 'https://parent-origin.com');
javascript

雙方接收

window.addEventListener('message', (event) => {
  // ⚠️ 必須驗證來源,否則任何人都能傳訊息進來
  if (event.origin !== 'https://trusted-origin.com') return;
  if (event.data.type === 'READY') {
    // ...
  }
});
javascript
安全鐵則
  1. 永遠驗證 event.origin — 不驗證 = 任何網站都能傳惡意訊息
  2. 發送時寫明 targetOrigin — 用 '*' 等於把訊息廣播給任何能載入該 iframe 的網站
  3. 永遠驗證資料結構 — 收到的 event.data 可能是任何東西,要驗 schema

痛點 3:scroll bar 雙重出現

iframe 內容超出時會出現自己的 scroll bar,父頁面也可能出現 → 雙 scroll bar 體驗很糟。

解法

<iframe scrolling="no" style="overflow: hidden;"></iframe>
html

搭配 iframe-resizer 自動調高度,iframe 內就不會超出 → 沒 scroll bar。


安全性:sandbox 屬性

預設 iframe 是「全權限」(可以執行 JS、開新分頁、讀 cookies 等)。sandbox 開白名單模式:

<iframe sandbox></iframe>                                <!-- 完全限制 -->
<iframe sandbox="allow-scripts"></iframe>                <!-- 只允許 JS -->
<iframe sandbox="allow-scripts allow-same-origin"></iframe>  <!-- 加上同源 -->
html
常用值允許
allow-scripts執行 JS
allow-same-origin視為同源(才能讀自己 cookies / localStorage)
allow-forms提交表單
allow-popups開新視窗 / target=_blank
allow-top-navigation改變父頁面 URL(少用,易被濫用 )
矛盾組合
同時開 allow-scripts + allow-same-origin 等於完全沒沙盒效果(因為內部 JS 可以呼叫 parent.postMessage(...) 後讀 cookies)。實務上要互信才這樣設。

防止自己被別人嵌入

如果你不希望別人用 iframe 嵌入你的網站(防 clickjacking):

# 舊寫法
X-Frame-Options: DENY

# 現代寫法(更彈性)
Content-Security-Policy: frame-ancestors 'self' https://trusted-partner.com
http

何時 / 不該用 iframe

適合
  • 嵌入第三方內容:YouTube、Google Maps、CodePen
  • legacy 系統包裝:把舊系統當「黑盒子」嵌進新系統
  • 沙盒執行使用者程式碼:Codepen / StackBlitz 模式
不適合
  • 同站元件複用 — 用 React 元件就好
  • SEO 重要的內容 — Google 對 iframe 內容索引有限
  • 行動裝置主要互動 — touch 事件穿透問題多

目錄

    ◆ 相關文章

    • html link作法

      2026-05-09
    • SCSS 編譯 前綴問題

      2026-05-09
    • 拖曳事件 (DragEvent)

      2026-05-09
    • 監聽 passive 屬性

      2026-05-09
    ← 上一篇github 大小寫問題下一篇 →Memory Leak (記憶體管理)

    ◆ 關於作者

    Kurau

    個人寫作 / 創作的 SoT,記錄遊戲、影視、學習與生活。

    更多 Kurau 的文章