ios移动端浏览器,vh高度和页面实际高度不匹配的解决方案

最近写h5页面,在浏览器顶部和底部的功能栏,会动态隐藏,导致页面高度和可视高度不匹配,导致部分元素被遮挡。

原因

浏览器顶部和底部的功能栏,是占用100vh的高度的。导致页面部分底部被遮挡。

所以常规页面设置vh方式就有问题。

解决方案

我的一个方案就是,通过css的var变量,配合js,动态修改变量的值,以达到页面高度变化时,自动修改css变量。

页面使用的时候,同时使用css变量。

定义了2个变量,--vh和--svh。

--vh是当前页面可视窗口的高度。

--svh是可视窗口的高度 - 安全区域底部高度。也就是手机的底部bar。

使用方式:

  1. 页面全屏展示,不需要考虑安全区域底部高度

height: calc(var(--vh, 1vh) * 100);

  1. 页面考虑安全区域底部高度时

height: calc(var(--svh, 1vh) * 100);

完整的js文件如下:

javascript 复制代码
//使用场景:页面全屏展示,不需要考虑安全区域底部高度
// height: calc(var(--vh, 1vh) * 100);
//使用场景:页面有安全区域底部高度,需要考虑安全区域底部高度
// height: calc(var(--svh, 1vh) * 100);

export function updateVh(height: number) {
  // 容器高度
  const vh = window.innerHeight * 0.01;
  // 去除ios安全区域底部高度
  const svh = (window.innerHeight - getSafeAreaInsetBottom()) * 0.01;
  
  document.documentElement.style.setProperty('--vh', `${vh}px`);
  document.documentElement.style.setProperty('--svh', `${svh}px`);
}

/**
 * 获取安全区域底部高度(safe-area-inset-bottom)
 * @returns {number} 安全区域底部高度(单位:px,不支持时返回 0)
 */
export function getSafeAreaInsetBottom() {
  // 创建临时元素用于计算
  const tempElement = document.createElement('div');
  
  // 设置样式:利用 env() 函数获取安全区域值,默认值为 0px(兼容不支持的浏览器)
  Object.assign(tempElement.style, {
    position: 'fixed', // 脱离文档流,不影响布局
    visibility: 'hidden', // 隐藏元素,仅用于计算
    paddingBottom: 'env(safe-area-inset-bottom, 0px)', // 核心:应用安全区域值
    left: '0',
    bottom: '0'
  });
  
  // 将临时元素添加到页面
  document.body.appendChild(tempElement);
  
  // 获取计算后的样式值(如 "34px")
  const computedStyle = window.getComputedStyle(tempElement);
  const paddingBottomValue = computedStyle.paddingBottom;
  
  // 移除临时元素(清理痕迹)
  document.body.removeChild(tempElement);
  
  // 转换为数字(去除单位),确保返回数值类型
  return parseFloat(paddingBottomValue) || 0;
}

function initAndWatchVh() {
  // 初始化
  let availableHeight = window.innerHeight;
    console.log('load', availableHeight);

  updateVh(availableHeight);

  // IOS需要load以后再触发,不然获取不到安全区域底部高度
  window.addEventListener('load', () => {
    let availableHeight = window.innerHeight;
    updateVh(availableHeight);
  });

  // 监听窗口大小变化(工具栏隐藏/显示)
  window.addEventListener('resize', () => {
    availableHeight = window.innerHeight;
    console.log('resize', availableHeight);
    updateVh(availableHeight);
  });
}

initAndWatchVh();
相关推荐
阿明Drift9 小时前
使用 CSS `perspective` 实现 3D 卡片效果
前端·css
若安程序开发9 小时前
web京东商城前端项目4页面
前端
申阳9 小时前
Day 8:06. 基于Nuxt开发博客项目-我的服务模块开发
前端·后端·程序员
转角羊儿9 小时前
layui框架中,表单元素不显示问题
前端·javascript·layui
muyouking119 小时前
WASM 3.0 两大领域实战:SvelteKit前端新范式(完整版)
前端·wasm
Hilaku9 小时前
当你的Ant-Design成了你最大的技术债
前端·javascript·前端框架
Highcharts.js10 小时前
时间序列图的“性能陷阱”:Highcharts “金融级”优化方案
前端·python·金融
摇滚侠10 小时前
Vue 项目实战《尚医通》,完成预约通知业务,笔记21
前端·vue.js·笔记·前端框架
IT_陈寒10 小时前
SpringBoot性能优化实战:我从10万QPS项目中总结的7个核心技巧
前端·人工智能·后端
顾安r10 小时前
11.9 脚本网页 消消乐
前端·javascript·flask·html·pygame