h5适配ios顶部和底部安全区域的问题

Posted 铁锤妹妹@

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了h5适配ios顶部和底部安全区域的问题相关的知识,希望对你有一定的参考价值。

一. 前言:

苹果手机从iphoneX之后,屏幕顶部都有一个齐刘海,iPhoneX 取消了物理按键,改成底部小黑条,如果不做适配,这些地方就会被遮挡,所以本文记录一下齐刘海与底部小黑条的适配方法。

二. 知识点学习

1)viewport-fit
ios11 新增特性,苹果公司为了适配 iPhoneX 对现有 viewport meta 标签的一个扩展,用于设置网页在可视窗口的布局方式,可设置三个值:

  • contain: 可视窗口完全包含网页内容
  • cover:网页内容完全覆盖可视窗口
  • auto:默认值,跟 contain 表现一致

注意:
网页默认不添加扩展的表现是 viewport-fit=contain,需要适配 iPhoneX 必须设置 viewport-fit=cover,这是适配的关键步骤。

2)env() 和 constant()
iOS11 新增特性,Webkit 的一个 CSS 函数,用于设定安全区域与边界的距离,有四个预定义的变量(单位是px):

  • safe-area-inset-left:安全区域距离左边边界的距离
  • safe-area-inset-right:安全区域距离右边边界的距离
  • safe-area-inset-top:安全区域距离顶部边界的距离
  • safe-area-inset-bottom:安全区域距离底部边界的距离

注意:
1)当 viewport-fit = contain 时 env() 是不起作用的,必须要配合 viewport-fit = cover 使用。对于不支持env() 的浏览器,浏览器将会忽略它。
需要做向后兼容。
2)env() 跟 constant() 需要同时存在,而且顺序不能换。

//适配底部小黑条
.page_bottom 
    padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS<11.2 */
    padding-bottom: env(safe-area-inset-bottom); /* 兼容iOS>= 11.2 */
 

三. 适配步骤?

1)设置网页在可视窗口的布局方式
<meta name='viewport'  content="width=device-width, viewport-fit=cover" />
2)适配导航栏刘海屏

用的是vant的导航栏组件自带的 safe-area-inset-top 属性,因为van-nav-bar导航栏开启了fixed布局,导致页面下面的所有内容,直接上升到了页面的最顶部,部分内容会被van-nav-bar导航栏遮挡,我没用这个组件自带的placeholder占位,而是在外面又增加了一个class类名为navBarCon的div,给他一个和导航栏一样的高度,设置了 height:50px; 这样就会占位了

//适配导航栏刘海屏,用的是vant的导航栏组件,自带的 safe-area-inset-top 属性
<template>
  <div class="root">
    <div class="navBarCon">
      <van-nav-bar
        title="收货地址"
        left-arrow
        fixed
        safe-area-inset-top
        @click-left="navBack"
      />
    </div>
  </div>
</template>

<script>
export default 
  data () 
    return 
  ,
  mounted () 

</script>

<style lang="scss" scoped>
::v-deep 
  .van-nav-bar .van-icon 
    color: #333 !important;
    font-weight: 600;
    font-size: 20px;
  
  .van-nav-bar__title 
    color: #333;
    font-weight: 600;
  
  .van-nav-bar__content 
    height: 50px;
  


.root 
  height: 100vh;
  .navBarCon 
    height: 50px;
  

</style>

对于安卓机这里会有个问题,会没有状态栏的一个区域,就是wifi,时间那一栏 (这是个困扰了一段时间的问题),今天解决了来记录下

大体思路:
判断手机系统是否是Andriod,是的话增加一个padding-top的样式作为安卓的头部距离;ios的话还是让他自己适配

// 判断手机系统
export const getNavigatorType = () => 
  let temp = ''
  var u = navigator.userAgent
  if (u.indexOf('android') > -1 || u.indexOf('Linux') > -1) 
    temp = 'Android'
   else 
    temp = 'ios'
  
  return temp

<script>
import  getNavigatorType  from '@/utils/tool.js'
 mounted () 
    let navigatorType = getNavigatorType()
    if (navigatorType === 'Android') 
    // 获取文档中的第一个class="van-nav-bar"的元素
      document.querySelector('.van-nav-bar').style.paddingTop = '20px'
    
  ,
</script>
3)适配底部小黑条 fixed 元素的适配

吸底的情况(bottom=0)

<template>
  <div class="root">
    <div class="page_bottom flexAround">
      <div class="amount">
        <span>合计:</span>
        <span class="red"></span>
        <span class="total_money red"> total_money </span>
      </div>
      <div class="payBtn" @click="confirmOrder">提交订单</div>
    </div>
  </div>
</template>

<script>
export default 
  data () 
    return 
  ,
  mounted () 

</script>

<style lang="scss" scoped>
/* 这个方案需要吸底条必须是有背景色的,因为扩展的部分背景是跟随外容器的,否则出现镂空情况。*/
.page_bottom 
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(45px + constant(safe-area-inset-bottom)); /* 直接扩展高度,因为padding-bottom是内边距 */
  height: calc(45px + env(safe-area-inset-bottom)); /* 直接扩展高度 */
  background: #fff;
  padding: 0 11px 0 20px;
  box-sizing: border-box;
  padding-bottom: constant(safe-area-inset-bottom); /*兼容 iOS<11.2 */
  padding-bottom: env(safe-area-inset-bottom); /* 兼容iOS>= 11.2*/

.flexAround 
  display: flex;
  justify-content: space-between;
  align-items: center;

</style>

四:结语

为了方便维护使用,可以把顶部导航栏封装成一个子组件,在父组件中调用

推荐
fixed元素的适配 bottom=0和非0的情况
适配底部小黑条
yidongduanh5安全区适配
如何解决移动端的安全区域为0的问题

以上是关于h5适配ios顶部和底部安全区域的问题的主要内容,如果未能解决你的问题,请参考以下文章

H5在iOS中的安全域问题

css关于解决苹果手机底部小黑条适配问题

vue适配iphoneX底部安全区域

iphoneX底部安全区域适配

极速适配 iPhone X 秘笈

iOS小技能:适配安全区域高度