
用 iframe 嵌入另一個網頁時,常遇到這個問題:iframe 的高度是固定的,裡面的內容比較長就出現一條捲軸,內容比較短又留下一大片空白。
iframe 不會自動跟著內容長高,因為 iframe 裡的網頁是一份獨立的文件,外層網頁在排版時並不知道它有多高。沒有設定高度時,瀏覽器預設只給 150px。
要讓 iframe 自動適應高度,先看你是哪一種情況:
- 內容是固定比例的(影片、地圖):用 CSS 的
aspect-ratio,不需要 JavaScript。 - iframe 裡的網頁跟外層是同一個網域:外層用 JavaScript 讀取內容的高度。
- iframe 裡的網頁是別的網域:要在 iframe 裡的網頁加一段程式,用
postMessage把高度傳出來。
先加上這段基本 CSS
.auto-frame {
display: block; /* 避免 iframe 下方多出一條小縫 */
width: 100%;
border: 0;
}情況一:影片、地圖這類固定比例的內容
YouTube、Google 地圖這類內容沒有固定的「內容高度」,而是會填滿整個 iframe,所以只要固定寬高比例就好:
.video-frame {
display: block;
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
border: 0;
}詳細說明請看iframe 嵌入網頁語法。
情況二:同網域,用 JavaScript 讀取內容高度
「同網域」指的是協定、網域、連接埠都相同,例如在 https://www.example.com/ 的頁面裡嵌入 https://www.example.com/news/list.html。要注意 example.com 和 www.example.com 算不同網域,http 和 https 也算不同。
同網域時,外層網頁可以直接讀到 iframe 裡的內容高度:
<iframe id="news-frame" class="auto-frame" src="/news/list.html" title="最新消息"></iframe>
<script>
const newsFrame = document.getElementById('news-frame');
newsFrame.addEventListener('load', () => {
const doc = newsFrame.contentDocument;
if (!doc) return; // 跨網域時會是 null,請改用情況三的做法
const fit = () => {
const height = doc.documentElement.getBoundingClientRect().height;
newsFrame.style.height = Math.ceil(height) + 'px';
};
fit();
// 內容有變化時 (圖片載入、展開收合) 重新調整高度
// 這裡使用 iframe 裡那份網頁的 ResizeObserver
const Observer = newsFrame.contentWindow.ResizeObserver;
new Observer(fit).observe(doc.documentElement);
});
</script>幾個重點:
- 這段
script要放在 iframe 的後面,確保 iframe 載入完成時已經在監聽。 ResizeObserver會在 iframe 裡的內容大小改變時通知,例如圖片慢慢載入、使用者展開收合選單,高度都會跟著更新。- iframe 裡點連結換頁時會再觸發一次
load,新的頁面也會自動調整。
量出來的高度不對?
- 子頁面的 CSS 如果把
html、body設成height: 100%,量到的會是 iframe 目前的高度,而不是內容的高度,要把這個設定拿掉。 - 子頁面裡有用
vh單位設定高度的元素時,iframe 變高,vh也跟著變大,可能會越長越高。會被放進 iframe 的頁面,盡量不要用vh設定高度。
情況三:跨網域,用 postMessage 傳遞高度
iframe 裡是別的網域時,瀏覽器的同源政策不允許外層讀取裡面的內容,情況二的 contentDocument 會是 null。
這時唯一的辦法,是請 iframe 裡的網頁自己回報高度:子頁面量好高度,用 postMessage 傳給外層,外層收到後再調整 iframe。所以這個方法的前提是:你能修改 iframe 裡的網頁(例如自己另一個網域的網站),或對方網站有提供這種功能。
子頁面(被嵌入的網頁)
放在子頁面的最後面,把 https://www.parent-site.com 換成外層網站的網域:
<script>
const PARENT_ORIGIN = 'https://www.parent-site.com';
if (window.parent !== window) {
const sendHeight = () => {
const height = Math.ceil(document.documentElement.getBoundingClientRect().height);
window.parent.postMessage({ type: 'frame-height', height: height }, PARENT_ORIGIN);
};
new ResizeObserver(sendHeight).observe(document.documentElement);
}
</script>ResizeObserver開始監看時會先通知一次,之後內容高度每次改變都會再送出。postMessage的第二個參數是「只把訊息送給這個網域」。子頁面會被好幾個網站嵌入時,才考慮改成'*'(高度不是機密資料,但不要用這種方式傳送其他資料)。
外層網頁
把 https://www.child-site.com 換成子頁面的網域。這段程式放在 iframe 的前面或緊接在後面,才不會漏接子頁面第一次送出的高度:
<iframe id="partner-frame" class="auto-frame" src="https://www.child-site.com/form.html" title="線上報名表"></iframe>
<script>
const CHILD_ORIGIN = 'https://www.child-site.com';
const partnerFrame = document.getElementById('partner-frame');
window.addEventListener('message', (event) => {
// 只接受子頁面網域、而且是這個 iframe 送來的訊息
if (event.origin !== CHILD_ORIGIN) return;
if (event.source !== partnerFrame.contentWindow) return;
const data = event.data;
if (!data || data.type !== 'frame-height') return;
const height = Number(data.height);
if (Number.isFinite(height) && height > 0) {
partnerFrame.style.height = Math.ceil(height) + 'px';
}
});
</script>檢查 event.origin 非常重要:任何網頁都能對你的網頁送 postMessage,不檢查來源的話,別人可以送奇怪的資料進來。收到的高度也要先確認是正常的數字,才拿來使用。
需要處理更多狀況時
多個 iframe、iframe 裡的錨點連結、捲動位置同步等等,要處理的細節會越來越多,這時可以考慮使用現成的開源套件(例如 iframe-resizer)。使用前請先確認它的授權條款是否適用你的網站。
舊版程式碼為什麼不能用了?
這篇文章舊版的程式碼,是在 iframe 載入時讀取 contentDocument.body.offsetHeight 設定高度,裡面還有判斷 window.opera、Document 這些給十幾年前的 Opera 與 IE 瀏覽器用的寫法。問題是:
- 只在載入時量一次,之後圖片載入、內容變動都不會更新。
body.offsetHeight不包含body的外距(margin),常常差幾個像素,又多出一條捲軸。- 跨網域時完全無效,而且沒有任何錯誤提示,很難發現問題出在哪裡。
用上面情況二或情況三的寫法取代即可。
其實不一定要用 iframe
如果嵌入的是自己網站的內容(例如最新消息列表),與其用 iframe 再想辦法調整高度,不如直接把內容放進頁面裡,例如用 PHP 的 include,或網站系統本身的區塊、短代碼功能。這樣沒有高度問題,搜尋引擎也會把這些內容當成這一頁的一部分;放在 iframe 裡的內容,搜尋引擎不一定會這樣處理。
延伸閱讀
- iframe 嵌入網頁語法:基本寫法、RWD 自適應寬度與網頁無法嵌入的原因
- 連結另開新視窗怎麼寫?target=_blank 與 noopener 用法(含 iframe 內連結)
- RWD 響應式網頁怎麼做?viewport 語法與 CSS 基本寫法完整教學
把訂位系統、報名表這類外部工具嵌進官網時,高度與手機版面往往是最花時間調整的地方。正威網路行銷是 25 年經驗的基隆網頁設計工作室,提供客製化網頁設計與 RWD 響應式網站,歡迎來聊聊。







發表留言
還沒有人留言,歡迎第一個分享你的想法或問題。留言經審核後才會顯示,Email 不會公開。