如何通过JS或CSS检测iOS 15 Safari中地址栏的位置(顶部/底部)
iOS 15+ Safari 地址栏位置检测方案
核心原理
iOS 15及以上版本的Safari地址栏位置变化,会直接反映在视口高度差、安全区域变量的数值差异上,基于这个特征可以分别用CSS配合JS实现检测。
CSS 适配方案
你可以直接利用env()安全区域变量适配不同位置的地址栏,不需要额外判断逻辑:
/* 底部固定元素自动适配地址栏高度 */ .fixed-bottom-element { /* env(safe-area-inset-bottom)会自动包含底部地址栏的高度 */ bottom: calc(16px + env(safe-area-inset-bottom)); }
如果需要根据地址栏位置做差异化样式,可以配合JS注入的属性实现:
/* 底部地址栏时的样式 */ :root[address-bar-pos="bottom"] .some-element { margin-bottom: 60px; } /* 顶部地址栏时的样式 */ :root[address-bar-pos="top"] .some-element { margin-bottom: 20px; }
JS 检测方案
通过计算浏览器外高度和内高度的差值,可以准确判断地址栏位置,代码如下:
function getSafariAddressBarPos() { // 前置校验:仅iOS 15+ Safari执行检测 const ua = navigator.userAgent; const isIOS = /iPhone|iPad|iPod/.test(ua) && !window.MSStream; const isSafari = /Safari/.test(ua) && !/CriOS|Chrome/.test(ua); const iosVer = parseFloat((ua.match(/OS (\d+)_(\d+)/) || []).slice(1,3).join('.')) || 0; if (!isIOS || !isSafari || iosVer < 15) return null; const heightDiff = window.outerHeight - window.innerHeight; const safeAreaBottom = parseInt(getComputedStyle(document.documentElement).getPropertyValue('env(safe-area-inset-bottom)')) || 0; // 底部地址栏时高度差超过90px,且安全区域底部高度大于40px(排除手势条的34px) return heightDiff > 90 && safeAreaBottom > 40 ? 'bottom' : 'top'; } // 监听地址栏位置变化事件 ['resize', 'visibilitychange'].forEach(evt => { window.addEventListener(evt, () => { const pos = getSafariAddressBarPos(); if (!pos) return; // 将结果写入根元素属性,供CSS使用 document.documentElement.setAttribute('address-bar-pos', pos); // 后续业务逻辑处理 }); });
注意事项
- 用户滑动页面触发地址栏悬浮缩小的时候,检测结果会临时失效,等地址栏恢复固定状态后会自动更新
- 横竖屏切换时会自动触发
resize事件,不需要额外适配
内容的提问来源于stack exchange,提问作者Wei Yan
相关产品推荐
相关产品推荐

