【 技術通報 】iPhone 嵌入 iframe 滾不動、被擋住?iOS Safari 全螢幕顯示的終極解法

iOS Safari iframe 佈局修復教學

你在 WordPress 嵌入 inline.app 訂位系統或外部網頁,結果 iPhone 使用者抱怨連連:滑不動、按鈕被擋、滾動卡死。這不是你的錯,是 iOS Safari 獨有的「計算邏輯」跟別人不一樣。這篇文章不是拿來讀的,是拿來解決問題的工具。

問題診斷:為什麼會壞掉?

▍ 1. 消失的 100vh

Safari 的 100vh 包含網址列與工具列。導致內容永遠被擋住約 50-100px,底部按鈕看得到、點不到。

▍ 2. 被沒收的滾動權限

iOS 預設將 iframe 視為固定區塊。如果 body 可以滾動,系統會優先滾動背景,導致 iframe 內部看起來像「壞掉」一樣滾不動。

解決方案:完整 HTML 實戰代碼

不需要安裝外掛,直接將以下代碼套入你的頁面:

<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
    <title>iOS Safari iframe 優化版</title>
    <style>
        :root { --app-height: 100%; }
        * { box-sizing: border-box; }
        
        html, body {
            margin: 0; padding: 0;
            width: 100%; height: 100%;
            overflow: hidden; /* 關鍵:強制鎖死 body 滾動 */
        }
        
        .iframe-container {
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            width: 100%;
            /* 多重高度回退機制 */
            height: 100%;
            height: 100vh;
            height: 100dvh;
            height: -webkit-fill-available;
            height: var(--app-height);
            overflow: hidden;
            /* 處理 iPhone 瀏海與底部安全區域 */
            padding-top: env(safe-area-inset-top, 0);
            padding-bottom: env(safe-area-inset-bottom, 0);
            /* 啟動 iOS 慣性滾動 */
            -webkit-overflow-scrolling: touch;
        }
        
        .iframe-container iframe {
            width: 100%; height: 100%;
            border: none; display: block;
        }
    </style>
</head>
<body>
    <div class="iframe-container">
        <iframe src="你的嵌入網址" frameborder="0" allowfullscreen scrolling="yes"></iframe>
    </div>
    
    <script>
        // JS 動態計算:精準取得工具列後的真實高度
        function setAppHeight() {
            const doc = document.documentElement;
            doc.style.setProperty('--app-height', `${window.innerHeight}px`);
        }
        window.addEventListener('resize', setAppHeight);
        window.addEventListener('orientationchange', () => setTimeout(setAppHeight, 100));
        setAppHeight();
        window.addEventListener('load', setAppHeight);
    </script>
</body>
</html>

技術核心:為什麼這樣寫有效?

VH vs DVH 動態高度示意圖

VH 與 DVH 的動態高度計算差異

▍ 1. 動態高度標籤(dvh)

使用現代 CSS 單位 100dvh (Dynamic Viewport Height),它會隨著工具列縮放自動調整。

▍ 2. JS 二重保險

window.innerHeight 是最誠實的值,它回傳的是「肉眼真正看得見」的高度,自動扣除 Safari 底部遮擋。

▍ 3. Body 鎖死(Overflow Hidden)

防止 body 產生多餘滾動條,確保使用者的滑動手勢 100% 傳遞給 iframe。

▍ 4. 視窗適配(Viewport Fit)

viewport-fit=cover 配合 env(safe-area-inset-*),能讓內容完美避開 iPhone 瀏海與螢幕底部的 Home 指示條。

進階:如果下方需要固定按鈕?

若要預留 60px 放置自訂按鈕,請修改 CSS:

.iframe-container {
    bottom: 60px; /* 為按鈕留位子 */
}
.bottom-button {
    position: fixed;
    bottom: 0; left: 0; right: 0; height: 60px;
    padding-bottom: env(safe-area-inset-bottom, 0);
    background: #333;
    display: flex; align-items: center; justify-content: center;
}

iOS Safari 三大坑總結(懶人包)

痛點原因終極解法
高度被擋100vh 包含工具列100dvh + JS 動態計算
完全不讓滾iOS 預設 iframe 鎖定body { overflow:hidden } + fixed
滾動卡頓缺乏慣性物理量-webkit-overflow-scrolling: touch

寫在最後:技術要能解決真實痛點

這不是一篇用來「閱讀」的文章,而是幫你掃除開發障礙的工具。現在就去貼上代碼,解決那些困擾已久的 iOS 兼容性問題。

文章分享