CSS env(safe-area-inset-bottom) 完全指南:從基礎到 iOS 26 最新變化
什麼是 env(safe-area-inset-bottom)
env(safe-area-inset-bottom) 是一個 CSS 環境變數函式,用來取得裝置視埠底部的安全區域內邊距。這個屬性主要用於避免網頁內容被裝置的不規則邊界、瀏海(notch)或底部手勢導航列(如 iPhone 的 Home Indicator)遮蔽。
核心概念
- 安全區域:裝置螢幕上不會被系統 UI 元素(如狀態列、瀏海、底部指示條)遮蔽的可視區域
- 內邊距值:以像素(px)為單位,表示從視埠底部到安全區域底部的距離
- 動態特性:值會根據裝置型號、方向和瀏覽器狀態動態變化
基本使用方法
1. 啟用安全區域支援
首先需要在 HTML 的 <head> 中加入正確的 viewport meta 標籤:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">關鍵是 viewport-fit=cover 參數,它允許內容延伸到整個螢幕,包括安全區域。
2. 基本語法和相容性寫法
.footer { padding-bottom: env(safe-area-inset-bottom); /* 向下相容 iOS 11.0 - 11.2 */ padding-bottom: constant(safe-area-inset-bottom);}3. 實際應用範例
底部導覽列適配:
.bottom-nav { position: fixed; bottom: 0; left: 0; right: 0; height: 60px; background-color: #fff;
/* 核心適配程式碼 */ padding-bottom: env(safe-area-inset-bottom); /* 確保總高度包含安全區域 */ height: calc(60px + env(safe-area-inset-bottom));}使用 max() 函式提供最小邊距:
.sticky-button { position: fixed; bottom: max(16px, env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%);}iOS 26 帶來的新挑戰
隨著 iOS 26 的發布(2025年9月15日),許多開發者回報 safe-area-inset-bottom 出現了新的問題:
主要問題
- 固定元素位置偏移:在 Safari 中,當頁面捲動導致網址列收縮時,
position: fixed元素的位置會出現不正確的偏移 - 鍵盤問題依然存在:當虛擬鍵盤出現時,
safe-area-inset-bottom值不會更新,導致鍵盤上方出現不必要的空隙 - 視埠計算異常:在某些情況下,視埠的位置計算會出現垂直偏移
iOS 26 問題的解決方案
1. 鍵盤遮蔽問題的現代解決方案
.safe-area-bottom { /* 只在沒有輸入框聚焦時套用 safe-area-inset-bottom */ :root:not(:has(input:focus-visible, textarea:focus-visible, [contenteditable]:focus-visible)) & { padding-bottom: env(safe-area-inset-bottom, 0); }}這個解決方案使用 CSS :has() 偽類來偵測是否有輸入元素處於聚焦狀態,如果有則不套用安全區域內邊距。
2. 固定元素位置修正
針對 iOS 26 中固定元素位置偏移的問題,可以嘗試以下方案:
/* 方案一:使用 JavaScript 觸發捲動修正 */.fixed-element { position: fixed; bottom: env(safe-area-inset-bottom);}
/* 搭配 JavaScript */window.addEventListener('resize', () => { // 觸發一次微小捲動來修正位置 window.scrollBy(0, 1); window.scrollBy(0, -1);});/* 方案二:限制捲動容器(有副作用) */html, body { height: 100%; overflow: hidden;}
.scroll-container { height: 100%; overflow-y: auto;}進階使用技巧
1. 結合新的視埠單位
iOS 26 更好地支援了動態視埠單位,可以結合使用:
.full-height-container { /* 使用動態視埠高度 */ height: 100dvh; /* 底部安全區域處理 */ padding-bottom: env(safe-area-inset-bottom);}2. 在不同方向下的處理
.responsive-footer { padding-bottom: env(safe-area-inset-bottom);
/* 橫向時的特殊處理 */ @media (orientation: landscape) { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }}3. 使用 CSS 自訂屬性
:root { --safe-bottom: env(safe-area-inset-bottom, 0px); --safe-top: env(safe-area-inset-top, 0px);}
.container { padding-top: var(--safe-top); padding-bottom: var(--safe-bottom);}JavaScript 中的應用
偵測安全區域值
// 取得計算後的安全區域值function getSafeAreaInsets() { const computedStyle = getComputedStyle(document.documentElement);
return { top: computedStyle.getPropertyValue('--safe-area-inset-top') || '0px', right: computedStyle.getPropertyValue('--safe-area-inset-right') || '0px', bottom: computedStyle.getPropertyValue('--safe-area-inset-bottom') || '0px', left: computedStyle.getPropertyValue('--safe-area-inset-left') || '0px' };}
// 監聽視埠變化window.addEventListener('resize', () => { const insets = getSafeAreaInsets(); console.log('底部安全區域:', insets.bottom);});React 中的使用
import React, { useEffect, useState } from 'react';
const SafeAreaComponent = () => { const [safeAreaBottom, setSafeAreaBottom] = useState('0px');
useEffect(() => { const updateSafeArea = () => { const bottom = getComputedStyle(document.documentElement) .getPropertyValue('--safe-area-inset-bottom') || '0px'; setSafeAreaBottom(bottom); };
window.addEventListener('resize', updateSafeArea); updateSafeArea();
return () => window.removeEventListener('resize', updateSafeArea); }, []);
return ( <div style={{ paddingBottom: `env(safe-area-inset-bottom, ${safeAreaBottom})` }} > 內容區域 </div> );};Tailwind CSS 設定
如果使用 Tailwind CSS,可以在設定檔中加入安全區域支援:
module.exports = { theme: { extend: { padding: { 'safe-bottom': 'env(safe-area-inset-bottom)', 'safe-top': 'env(safe-area-inset-top)', 'safe-left': 'env(safe-area-inset-left)', 'safe-right': 'env(safe-area-inset-right)', }, spacing: { 'safe-bottom': 'env(safe-area-inset-bottom)', } } }}使用時:
<div class="pb-safe-bottom"> <nav class="fixed bottom-0 pb-safe-bottom"> 底部導覽 </nav></div>瀏覽器相容性和注意事項
支援程度
- iOS Safari: 11.0+ (使用
env()), 11.0-11.2 (使用constant()) - Android Chrome: 69+
- 桌面瀏覽器: 普遍支援但值通常為 0
常見問題排查
-
值始終為 0:
- 檢查是否加入了
viewport-fit=cover - 確認裝置是否有不規則邊界(瀏海、圓角等)
- 在 PWA 模式下測試
- 檢查是否加入了
-
iOS 26 特定問題:
- 使用上述提到的鍵盤解決方案
- 避免同時使用多個視埠修正技巧
- 考慮使用動態視埠單位替代方案
-
效能問題:
- 避免頻繁重新計算安全區域值
- 使用 CSS 自訂屬性減少重複計算
最佳實務
-
漸進增強:
.footer {padding-bottom: 16px; /* 基礎邊距 */padding-bottom: max(16px, env(safe-area-inset-bottom)); /* 增強 */} -
測試策略:
- 在真實裝置上測試,不僅僅依賴模擬器
- 測試不同的瀏覽器狀態(全螢幕、普通模式、PWA 模式)
- 驗證橫豎螢幕切換時的表現
-
向下相容:
.safe-element {padding-bottom: 20px; /* 後備方案 */padding-bottom: constant(safe-area-inset-bottom); /* iOS 11.0-11.2 */padding-bottom: env(safe-area-inset-bottom); /* 現代瀏覽器 */}
總結
env(safe-area-inset-bottom) 是現代行動端網頁開發的重要工具,能夠有效解決不規則螢幕裝置上的內容遮蔽問題。雖然 iOS 26 帶來了一些新的挑戰,但透過合理使用新的 CSS 特性和解決方案,我們仍然可以創造出優秀的跨裝置使用者體驗。
隨著行動裝置設計的不斷創新,掌握安全區域的處理方法對前端工程師來說越來越重要。建議開發者:
- 保持對 iOS 和 Android 更新的關注
- 在真實裝置上進行充分測試
- 採用漸進增強的策略確保向下相容性
- 關注新的 CSS 特性如動態視埠單位的發展
透過正確使用 env(safe-area-inset-bottom),我們可以確保網頁內容在各種裝置上都能獲得最佳的顯示效果和使用者體驗。
回報錯字、失效連結,或告訴我你想看的延伸主題。