npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

safe-area-adapter

v1.0.6

Published

A tool for adapting H5 pages to bottom safe areas on mobile devices

Readme

H5 底部安全区域适配工具 (Safe Area Adapter)

这个工具用于解决H5页面在各种移动设备上底部安全区域的适配问题,特别是针对全面屏设备(如iPhone X及以上机型)和自定义WebView环境。通过智能检测设备环境、自动适配元素样式,让开发者不必为不同设备编写复杂的兼容代码。

功能特点

  • 多重检测机制:

    • 自动检测UA参数中的 bheight值作为底部安全区域高度
    • 支持通过URL参数指定安全区域高度
    • 智能检测iOS环境变量
    • 支持通过URL参数 hideBottom=1禁用底部安全区域适配
  • iOS设备智能适配:

    • 自动检测并使用iOS原生的 safe-area-inset-bottom环境变量
    • 自动添加 viewport-fit=cover元标签以启用iOS安全区域支持
    • 当环境变量不可用时,平滑回退到默认安全区域高度
  • 全面的布局支持:

    • 支持固定定位(position: fixed)元素
    • 支持粘性定位(position: sticky)元素
    • 支持自定义选择器和条件
  • 智能DOM处理:

    • 自动处理页面已有元素
    • 使用MutationObserver实时监控并处理动态添加的DOM元素
    • 优雅处理屏幕尺寸和窗口大小变化
  • 防冲突设计:

    • 检测已有内边距,避免重复适配
    • 支持取消适配并精确还原原始样式
    • 提供元素级别的控制属性
  • 开发者友好:

    • 完全可配置的初始化选项
    • 支持TypeScript,提供完整类型定义
    • 同时支持CommonJS和ES Module两种模块系统
    • 轻量级设计,核心代码不依赖第三方库

安装

使用npm/yarn/pnpm安装

# npm
npm install h5-safe-area-adapter

# yarn
yarn add h5-safe-area-adapter

# pnpm
pnpm add h5-safe-area-adapter

直接引入

也可以直接在HTML页面中引入:

<!-- 推荐:使用优化后的UMD打包版本 -->
<script src="./dist/browser/safe-area-adapter.min.js"></script>
<script>
  SafeAreaAdapter.default.init();
</script>

<!-- ESM方式 -->
<script type="module">
  import SafeAreaAdapter from './dist/esm/index.js';

  SafeAreaAdapter.init();
</script>

使用方法

快速开始

方法一:在HTML中直接引入

<!-- 1. 引入脚本 -->
<script src="dist/cjs/index.js"></script>

<!-- 2. 初始化适配器 -->
<script>
  // 使用默认配置初始化
  SafeAreaAdapter.init();
</script>

方法二:在现代前端项目中使用

// ESM方式
import SafeAreaAdapter from 'h5-safe-area-adapter';

// 或CommonJS方式
const SafeAreaAdapter = require('h5-safe-area-adapter');

// 初始化适配器
SafeAreaAdapter.init();

基础配置

初始化时可以传入自定义配置:

// 使用自定义配置初始化
SafeAreaAdapter.init({
  debug: true, // 开启调试日志
  defaultSafeAreaHeight: 34, // 设置默认安全区域高度
  maskColor: '#ffffff', // 设置遮挡层颜色
  forceAdaptation: false, // 是否强制适配
  checkIOSEnv: true, // 是否检测iOS环境变量
  safeAreaAttribute: 'data-safe-area-adapter' // 自定义属性名
});

常见使用场景

场景一:适配底部固定导航栏

<style>
  .bottom-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 50px;
    background: #fff;
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
  }
</style>

<div class="bottom-nav">
  <!-- 导航内容 -->
</div>

<script>
  // 导航栏会自动被适配,无需额外标记
  SafeAreaAdapter.init();
</script>

场景二:强制适配特定元素

<style>
  .floating-button {
    position: fixed;
    right: 20px;
    bottom: 20px; /* 非零底部距离,默认不会被自动适配 */
  }
</style>

<!-- 添加data-force-safe-area属性强制适配 -->
<button class="floating-button" data-force-safe-area>悬浮按钮</button>

<script>
  SafeAreaAdapter.init();
</script>

场景三:跳过特定元素的适配

<style>
  .bottom-element {
    position: fixed;
    bottom: 0;
  }
</style>

<!-- 添加data-skip-safe-area属性跳过适配 -->
<div class="bottom-element" data-skip-safe-area>不需要适配的元素</div>

<script>
  SafeAreaAdapter.init();
</script>

场景四:动态切换暗黑模式

// 初始化时设置白色遮挡层
SafeAreaAdapter.init({ maskColor: '#ffffff' });

// 当切换到暗黑模式时
function enableDarkMode() {
  // 刷新适配器并设置暗色遮挡层
  SafeAreaAdapter.refresh({
    maskColor: '#121212'
  });
}

// 当切换回亮色模式时
function disableDarkMode() {
  SafeAreaAdapter.refresh({
    maskColor: '#ffffff'
  });
}

场景五:SPA路由切换后重新适配

// 在Vue Router的全局导航守卫中
router.afterEach(() => {
  // 等待DOM更新后重新应用适配
  setTimeout(() => {
    SafeAreaAdapter.refresh();
  }, 100);
});

// 在React Router中
function RouteChangeHandler() {
  useEffect(() => {
    SafeAreaAdapter.refresh();
  }, [location.pathname]); // 当路径变化时刷新适配

  return <>{children}</>;
}

场景六:检测URL参数来禁用底部适配

对于某些特殊页面或临时需要禁用适配的场景,我们可以利用 hideBottom=1 URL 参数:

// 初始化适配器 - 会自动检测URL参数
SafeAreaAdapter.init({ debug: true }).then(result => {
  if (result.source === 'url_param_disabled') {
    console.log('通过URL参数禁用了底部安全区域适配');
  } else if (!result.active) {
    console.log('适配器未激活,原因:', result.source);
  } else {
    console.log('适配器已激活,安全区域高度:', result.safeAreaHeight);
  }
});

元素适配控制

对于需要特别控制的元素,可以使用以下属性:

  • data-force-safe-area: 强制对该元素进行安全区域适配,无论其位置如何
    • 如果属性值设为 "false" 或 "0"(如 data-force-safe-area="false"),则不会进行强制适配
  • data-skip-safe-area: 跳过对该元素的安全区域适配
    • 如果属性值设为 "false" 或 "0"(如 data-skip-safe-area="false"),则不会跳过适配

例如:

<!-- 强制对该元素进行安全区域适配 -->
<div class="footer" data-force-safe-area>底部导航栏</div>

<!-- 设置属性值为false,不进行强制适配 -->
<div class="footer" data-force-safe-area="false">不需要强制适配的底部元素</div>

<!-- 跳过对该元素的安全区域适配 -->
<div class="bottom-element" data-skip-safe-area>不需要适配的底部元素</div>

<!-- 设置跳过属性值为false,仍然进行适配 -->
<div class="bottom-element" data-skip-safe-area="false">需要适配的底部元素</div>

API 完整使用示例

下面是对所有API方法的详细使用示例:

// 初始化安全区域适配器
SafeAreaAdapter.init({ debug: true }).then(result => {
  console.log('适配器是否激活:', result.active);
  console.log('安全区域高度:', result.safeAreaHeight + 'px');
  console.log('高度来源:', result.source); // 'url', 'ua', 'env', 'default', 'none'
  console.log('使用的配置:', result.config);

  if (result.error) {
    console.error('初始化错误:', result.error);
  }
});

// 获取当前安全区域高度
const safeAreaHeight = SafeAreaAdapter.getSafeAreaHeight();
console.log(`当前安全区域高度: ${safeAreaHeight}px`);

// 获取当前配置
const config = SafeAreaAdapter.getConfig();
console.log('当前配置:', config);

// 检查适配器是否激活
const isActive = SafeAreaAdapter.isActive();
console.log('适配器是否激活:', isActive);

// 手动刷新安全区域适配(支持传入新配置)
SafeAreaAdapter.refresh({
  maskColor: '#000000', // 更新遮挡层颜色为黑色
  debug: false // 关闭调试日志
}).then(result => {
  console.log('适配器刷新结果:', result);
});

// 对特定元素应用安全区域适配
const myElement = document.querySelector('.my-bottom-element');
if (myElement) {
  SafeAreaAdapter.applySafeAreaToElement(myElement);
  console.log('已为特定元素应用安全区域适配');
}

// 取消所有安全区域适配,还原原始样式
document.getElementById('cancelBtn').addEventListener('click', () => {
  SafeAreaAdapter.cancel();
  console.log('已取消所有安全区域适配');
});

// 强制应用安全区域适配(即使已有足够内边距)
document.getElementById('forceApplyBtn').addEventListener('click', () => {
  SafeAreaAdapter.forceApply({
    defaultSafeAreaHeight: 50 // 同时可以更新配置
  }).then(result => {
    console.log('强制适配结果:', result);
  });
});

TypeScript类型支持

该库提供完整的TypeScript类型定义,可以在TypeScript项目中获得完整的类型检查和代码提示:

import SafeAreaAdapter from 'h5-safe-area-adapter';
import { SafeAreaAdapterConfig } from 'h5-safe-area-adapter/dist/types';

// 配置选项带有类型提示
const config: SafeAreaAdapterConfig = {
  debug: true,
  defaultSafeAreaHeight: 34,
  maskColor: '#ffffff'
};

// 初始化结果也有类型定义
const result = await SafeAreaAdapter.init(config);
console.log(result.active); // boolean
console.log(result.safeAreaHeight); // number
console.log(result.source); // string

适配机制

  1. 自动检测页面是否已有足够的底部内边距:

    • 如果检测到body已有大于等于安全区域高度的底部内边距,则不进行任何适配
    • 这有助于避免与第三方业务样式冲突,保持页面原有布局
  2. 区分适配器添加的样式与第三方样式:

    • 使用特殊属性标记由适配器添加的样式
    • 便于后续取消适配时准确还原原始样式
  3. 强制适配选项:

    • 当需要覆盖现有内边距时,可以使用强制适配选项
    • 通过 SafeAreaAdapter.forceApply()方法调用
  4. 元素适配方式:

    • 对于普通设备:直接修改元素的 bottom值,增加安全区域高度
    • 对于支持iOS环境变量的设备:使用 env(safe-area-inset-bottom)进行适配
    • 保存元素的原始样式,以便取消适配时还原

工作原理详解

安全区域高度检测流程

SafeAreaAdapter使用多级检测流程来确定安全区域高度:

  1. 优先级1:URL参数检测

    • 检查URL中是否存在 safeAreaHeight参数
    • 示例:https://example.com/?safeAreaHeight=34
    • 如果存在且为有效数值,则直接使用该值
    • 支持hash路由:https://example.com/#/path?safeAreaHeight=34
  2. 优先级2:UA参数检测

    • 检查User-Agent字符串中是否包含 bheight参数
    • 支持两种格式:
      • 新格式:bheight/34
      • 旧格式:bheight=34
    • 这主要用于原生应用WebView环境,原生应用可以在打开WebView时注入此参数
  3. 优先级3:iOS环境变量检测

    • 检测当前设备是否为iOS设备
    • 如果是iOS设备,添加 viewport-fit=cover元标签
    • 尝试检测 env(safe-area-inset-bottom)环境变量
    • 使用动态创建的测试元素实际测量环境变量值
    • 如果环境变量有效,使用测量值
  4. 优先级4:默认值回退

    • 如果以上检测都未能获取有效值,且设备为iOS
    • 使用默认安全区域高度(默认34px)
    • 可通过配置修改默认值

核心处理流程

初始化适配器时,会执行以下步骤:


┌───────────────────┐
│  初始化适配器     │
└────────┬──────────┘
         │
         ▼
┌───────────────────┐
│  检测安全区域高度 │
└────────┬──────────┘
         │
         ▼
┌───────────────────┐    否    ┌───────────────┐
│ 高度 > 0 ?        │─────────►│ 退出,不适配  │
└────────┬──────────┘          └───────────────┘
         │ 是
         ▼
┌───────────────────┐
│  应用到body       │
└────────┬──────────┘
         │
         ▼
┌───────────────────┐
│  处理已有元素     │
└────────┬──────────┘
         │
         ▼
┌───────────────────┐
│  设置DOM监听      │
└───────────────────

配置选项详解

初始化时可以传入以下配置选项:

| 配置项 | 类型 | 默认值 | 说明 | | ------------------------- | ------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | defaultSafeAreaHeight | Number | 34 | iOS默认安全区域高度(像素)。当无法通过环境变量、URL或UA获取安全区域高度时,将使用此值。常见值有34px(iPhone X/11/12/13)、39px(iPhone 14 Pro)等。 | | attributeName | String | "data-safe-area-processed" | 标记已处理元素的属性名。此属性用于避免重复处理已适配的元素。 | | safeAreaAttribute | String | "data-safe-area-adapter" | 标记由适配器添加的样式。此属性用于还原原始样式时识别哪些样式是由适配器添加的。 | | forceAdaptation | Boolean | false | 是否强制适配。如果设为true,即使已有足够内边距,也会强制应用安全区域适配。适用于需要覆盖现有样式的场景。 | | debug | Boolean | false | 是否开启调试日志。开启后会在控制台输出详细的适配过程日志,有助于排查问题。在生产环境建议关闭。 | | checkIOSEnv | Boolean | true | 是否检测iOS环境变量并使用。开启后,会自动检测并优先使用iOS原生的safe-area-inset-bottom环境变量,提供更精准的适配效果。 | | maskColor | String | "white" | 遮挡层的背景色。在安全区域处会创建一个背景色为该颜色的遮挡层,防止内容透过安全区域展示。可使用颜色名称、HEX值或RGB/RGBA值。 | | forceAdaptationAttr | String | "data-force-safe-area" | 强制适配属性名。添加此属性的元素会被强制适配,无论其位置如何。适用于需要特别适配的元素。 | | skipAdaptationAttr | String | "data-skip-safe-area" | 跳过适配属性名。添加此属性的元素会被跳过适配,即使其符合适配条件。适用于需要保持原样的元素。 | | enableUAVersionControl | Boolean | false | 是否启用UA版本控制。启用后,将根据UA中指定字段的版本号决定是否进行适配。用于控制特定客户端版本后才开始适配。 | | uaVersionField | String | "xxxUAField" | UA版本控制中要检查的字段名。例如"xxxUAField"将检查UA中是否包含"xxxUAField/10.0"或"xxxUAField 10.0"格式的版本号。 | | uaMinVersion | String | "10.0" | UA版本控制的最低版本要求。只有当UA中检测到的版本号大于或等于此值时,才会启用适配。支持多段版本号如"10.0.1"。 | | enableIfUAFieldNotFound | Boolean | true | 当UA中未找到指定字段时的行为。如果为true,则在未找到字段时仍启用适配;如果为false,则在未找到字段时不启用适配。 |

配置示例与最佳实践

基础配置示例:

SafeAreaAdapter.init({
  debug: process.env.NODE_ENV !== 'production', // 仅在非生产环境开启调试
  defaultSafeAreaHeight: 34, // 设置默认安全区域高度
  maskColor: '#ffffff' // 设置遮挡层为白色
});

高级配置示例:

SafeAreaAdapter.init({
  // 基础配置
  debug: true,
  defaultSafeAreaHeight: 39, // iPhone 14 Pro 安全区域高度

  // 外观配置
  maskColor: 'rgba(255,255,255,0.8)', // 半透明白色遮挡层

  // 行为配置
  forceAdaptation: true, // 强制适配
  checkIOSEnv: true, // 检测iOS环境变量

  // 自定义属性名配置
  safeAreaAttribute: 'data-sa-adapted',
  attributeName: 'data-sa-processed',
  forceAdaptationAttr: 'data-sa-force',
  skipAdaptationAttr: 'data-sa-skip',

  // UA版本控制配置
  enableUAVersionControl: true, // 启用UA版本控制
  uaVersionField: 'xxxUAField', // 检查UA中的xxxUAField字段
  uaMinVersion: '10.0', // 最低版本要求
  enableIfUAFieldNotFound: false // 如果未找到字段则不启用适配
});

// 或使用指定客户端版本适配
SafeAreaAdapter.init({
  enableUAVersionControl: true,
  uaVersionField: 'MyApp', // 指定自定义UA字段名
  uaMinVersion: '2.5.1', // 支持多段版本号
  enableIfUAFieldNotFound: true // 非指定客户端时仍然适配
});

针对不同设备的配置:

// 根据设备类型进行不同配置
function getDeviceConfig() {
  // 检测是否为iPad
  const isIPad = /iPad/.test(navigator.userAgent);

  // 检测是否为iPhone 14 Pro或更新机型
  const isNewerIPhone = /iPhone/.test(navigator.userAgent) && (screen.height > 844 || screen.width > 844);

  if (isIPad) {
    return {
      defaultSafeAreaHeight: 20, // iPad的安全区域较小
      maskColor: '#f5f5f5' // 使用淡灰色
    };
  } else if (isNewerIPhone) {
    return {
      defaultSafeAreaHeight: 39, // iPhone 14 Pro及以上
      maskColor: '#000000' // 使用黑色
    };
  } else {
    return {
      defaultSafeAreaHeight: 34, // 其他iPhone机型
      maskColor: '#ffffff' // 使用白色
    };
  }
}

// 使用设备特定配置初始化
SafeAreaAdapter.init(getDeviceConfig());

元素适配条件与原理

哪些元素会被自动适配?

SafeAreaAdapter会对以下元素进行自动适配:

  1. 固定定位元素:使用了 position: fixed的元素
  2. 粘性定位元素:使用了 position: sticky的元素
  3. 底部接触元素:元素的 bottom值为0或小于等于安全区域高度
  4. 手动标记元素:添加了 data-force-safe-area属性的元素(强制适配)

哪些元素会被跳过适配?

以下元素不会被适配:

  1. 手动排除元素:添加了 data-skip-safe-area属性的元素
  2. 内部元素:适配器自动创建的安全区域占位元素和遮挡层
  3. 非定位元素:未使用 fixed或 sticky定位的元素
  4. 顶部元素:bottom值未指定或大于安全区域高度的元素(除非被强制适配)

兼容性与降级策略

浏览器兼容性

SafeAreaAdapter支持以下浏览器环境:

  • 现代浏览器:Chrome 60+、Safari 11.2+、Firefox 63+、Edge 79+
  • 移动浏览器:iOS Safari 11.2+、Android Chrome 60+、Android WebView 60+
  • iOS WebView:WKWebView、UIWebView(注意:UIWebView已被苹果废弃)
  • 跨平台WebView:React Native WebView、Cordova WebView、Electron

功能降级策略

SafeAreaAdapter采用渐进增强的策略,针对不同环境提供不同程度的支持:

  1. 现代iOS Safari(iOS 11.2+):

    • 优先使用 env(safe-area-inset-bottom)环境变量
    • 自动添加 viewport-fit=cover元标签
    • 精确适配各种iPhone机型的安全区域
  2. 旧版iOS(iOS 11.2以下):

    • 不支持 env()环境变量
    • 回退到默认的安全区域高度(通常为34px)
    • 确保基本的适配效果
  3. Android设备:

    • 默认不应用安全区域适配(Android设备通常不需要)
    • 如果UA中包含 bheight参数,则使用该值作为安全区域高度
    • 可以通过URL参数指定安全区域高度
  4. 不支持MutationObserver的环境:

    • 仅处理页面初始化时存在的元素
    • 动态添加的元素需要手动调用 applySafeAreaToElement

错误处理

适配器添加了全面的错误处理,确保在各种环境下的稳定性:

  • 每个关键函数都包含try/catch块,防止单点失败导致整个适配器失效
  • 日志系统提供详细的错误信息,帮助开发者排查问题
  • 发生错误时会优雅降级,确保页面功能不受影响
  • 初始化失败时返回明确的错误信息,而不是抛出异常

高级使用技巧

URL参数控制

SafeAreaAdapter支持通过URL参数控制适配行为:

  1. 禁用底部安全区域适配: 在URL中添加 hideBottom=1参数可以完全禁用底部安全区域适配。

    https://example.com/your-page?hideBottom=1

    这对于某些特殊页面或临时需要禁用适配的场景非常有用。

  2. 指定安全区域高度:

    https://example.com/your-page?safeAreaHeight=50

    通过 safeAreaHeight参数可以手动指定安全区域高度(优先级高于UA检测和iOS环境变量)。

这些参数可以与其他URL参数一起使用:

https://example.com/your-page?hideBottom=1&otherParam=value

UA版本控制

UA版本控制功能可以根据客户端版本号决定是否启用适配,这在需要逐步推出适配功能或只针对特定版本客户端进行适配时非常有用:

// 根据客户端版本控制适配行为
SafeAreaAdapter.init({
  enableUAVersionControl: true, // 启用UA版本控制
  uaVersionField: 'xxxUAField', // 检查UA中的xxxUAField字段
  uaMinVersion: '10.0', // 要求版本至少为10.0
  enableIfUAFieldNotFound: false // 如果未找到字段则不启用适配
});

UA版本控制支持以下UA格式:

  • UA-Field/1.0.2(斜杠分隔)
  • UA-Field 1.0.2(空格分隔)

版本比较采用标准的语义化版本比较规则,支持任意段数的版本号(如 10.0.1.5)。

该功能适用于以下场景:

  • 在新版本App中逐步启用安全区域适配
  • 针对特定客户端或浏览器版本提供定制适配
  • A/B测试不同版本客户端的适配效果

CSS变量集成

您可以将安全区域高度与CSS变量集成,实现更灵活的样式适配:

// 初始化后将安全区域高度设置为CSS变量
SafeAreaAdapter.init().then(result => {
  if (result.active) {
    document.documentElement.style.setProperty('--safe-area-bottom', `${result.safeAreaHeight}px`);
  }
});

然后在CSS中使用:

.my-footer {
  padding-bottom: calc(20px + var(--safe-area-bottom, 0px));
}

框架集成指南

Vue.js集成

// safeArea.js
import SafeAreaAdapter from 'h5-safe-area-adapter';

export default {
  install(Vue) {
    Vue.prototype.$safeArea = SafeAreaAdapter;

    // 创建全局指令
    Vue.directive('safe-area', {
      inserted(el) {
        SafeAreaAdapter.applySafeAreaToElement(el);
      }
    });
  }
};

// main.js
import SafeArea from './safeArea';
Vue.use(SafeArea);

// 组件中使用
export default {
  mounted() {
    this.$safeArea.init();
  },
  beforeDestroy() {
    this.$safeArea.cancel();
  }
}

// 指令使用
<div v-safe-area>带安全区域的元素</div>

React集成

// SafeAreaContext.js
import React, { createContext, useContext, useEffect, useState } from 'react';
import SafeAreaAdapter from 'h5-safe-area-adapter';

const SafeAreaContext = createContext(null);

export function SafeAreaProvider({ children }) {
  const [safeAreaHeight, setSafeAreaHeight] = useState(0);

  useEffect(() => {
    SafeAreaAdapter.init().then(result => {
      setSafeAreaHeight(result.safeAreaHeight);
    });

    return () => {
      SafeAreaAdapter.cancel();
    };
  }, []);

  return (
    <SafeAreaContext.Provider
      value={{
        adapter: SafeAreaAdapter,
        height: safeAreaHeight
      }}>
      {children}
    </SafeAreaContext.Provider>
  );
}

export function useSafeArea() {
  return useContext(SafeAreaContext);
}

// 使用Hook
function MyComponent() {
  const { height } = useSafeArea();
  return <div style={{ marginBottom: height }}>内容</div>;
}

// 包装根组件
function App() {
  return (
    <SafeAreaProvider>
      <Router>
        <Routes />
      </Router>
    </SafeAreaProvider>
  );
}

调试与问题排查

开启调试模式

通过初始化选项启用详细的调试日志:

SafeAreaAdapter.init({ debug: true });

检查适配状态

查看当前安全区域适配的详细状态:

// 检查适配器状态
console.log('适配器是否激活:', SafeAreaAdapter.isActive());

// 获取当前安全区域高度
console.log('安全区域高度:', SafeAreaAdapter.getSafeAreaHeight() + 'px');

// 查看完整配置
console.log('当前配置:', SafeAreaAdapter.getConfig());

常见问题排查

问题1: 安全区域高度为0

可能原因:

  • 非iOS设备且UA中无bheight参数
  • iOS设备但viewport-fit未设置为cover
  • 初始化失败

解决方案:

// 强制指定安全区域高度
SafeAreaAdapter.forceApply({ defaultSafeAreaHeight: 34 });

问题2: 元素未被适配

可能原因:

  • 元素不符合自动适配条件
  • 元素在适配器初始化后动态添加但未被检测到

解决方案:

// 手动对特定元素应用适配
const element = document.querySelector('.problematic-element');
SafeAreaAdapter.applySafeAreaToElement(element);

问题3: 样式冲突

可能原因:

  • 第三方样式覆盖了适配器添加的样式
  • CSS优先级问题

解决方案:

// 使用强制适配模式
SafeAreaAdapter.forceApply();

// 或为特定元素添加强制适配属性
element.setAttribute('data-force-safe-area', 'true');

问题4: UA版本控制导致适配未启用

可能原因:

  • UA中未找到指定字段
  • UA中版本号低于指定的最小版本
  • UA格式与预期不匹配

解决方案:

// 检查当前UA
console.log(navigator.userAgent);

// 临时禁用UA版本控制
SafeAreaAdapter.refresh({
  enableUAVersionControl: false
});

// 或调整UA版本控制配置
SafeAreaAdapter.refresh({
  uaVersionField: '正确的字段名',
  uaMinVersion: '较低的版本号',
  enableIfUAFieldNotFound: true
});

完整重置测试

如果遇到难以排查的问题,可以完全重置后重新初始化:

// 取消所有适配
SafeAreaAdapter.cancel();

// 短暂延时确保DOM更新
setTimeout(() => {
  // 重新初始化
  SafeAreaAdapter.init({ debug: true }).then(result => {
    console.log('重新初始化结果:', result);
  });
}, 100);