引言

iPhoneX发布至今已经有将近一年的时间了,各类app都多多少少做了对iPhoneX的适配,那对于我们H5页面该做哪方面的适配呢?

首先了解安全区域(safe area)的概念,它保证了内容在设备上的正确嵌入,不会被状态栏、导航栏等遮挡。

Apps should adhere to the safe area and layout margins defined by UIKit, which ensure appropriate insetting based on the device and context. The safe area also prevents content from underlapping the status bar, navigation bar, toolbar, and tab bar.

-- by Apple's Human Interface Guidelines

图1

对于h5页面来说,通常是在浏览器或app的webview这样的“容器”中打开,这些容器大都会做这样的适配:

图2

可以看到,这些容器都会保证页面顶部在安全区内,而为了保证全屏体验的效果,底部会占满屏幕。

在不考虑横屏浏览的情况下,我们只需要对底部导航做一个适配就可以啦~

如下图所示,iPhoneX底部的危险区域高度为34pt,对应@3x页面像素值为102px。我们可以根据这个值对底部导航做适配。

图3

底部导航适配三法

1. js基本实现

var isIphoneX = window.devicePixelRatio && window.devicePixelRatio === 3 && window.screen.width === 375 && testUA('iPhone')

if (isIphoneX) {

 document.body.classList.add('fix-iphonex-bottom')

}

function testUA (str) {

 return navigator.userAgent.indexOf(str) > -1

}

.fix-iphonex-bottom .navi[data-v-539b7842]{

 padding-bottom: 34px;

}

demo

2.js动态适配

如上图2所示,针对有底部栏的浏览器,页面滚动过程中底部栏显示、隐藏的情况,我们可以做一个动态适配:

var isIphoneX = window.devicePixelRatio && window.devicePixelRatio === 3 && window.screen.width === 375 && testUA('iPhone')

if (isIphoneX) {

 check()

 window.onscroll = throttle(check, 200)

}

function check () {

 // 处理lib-flexible放大viewport的情况

 var scale = window.innerWidth / window.screen.width

 // 部分浏览器在滚动页面时会显示/隐藏工具栏,影响视口高度。在有底部工具栏的情况下,不做iPhoneX的fix。100为经验值

 if (window.screen.height - window.innerHeight / scale < 100) {

   document.body.classList.add('fix-iphonex-bottom')

 } else {

   document.body.classList.remove('fix-iphonex-bottom')

 }

}

function testUA (str) {

 return navigator.userAgent.indexOf(str) > -1

}

效果:

demo:

3.纯css实现

In order to handle any adjustment that may be required iOS 11's version of Safari includes some constants that can be used when viewport-fit=cover is being used.

  • safe-area-inset-top

  • safe-area-inset-right

  • safe-area-inset-left

  • safe-area-inset-bottom

为了更好地适配IOS 11版本的safari提供了上面几个变量。且当 viewport-fit=cover时可以在css中使用。

首先设置meta标签

  1. <meta name=“viewport” content=”initial-scale=1, viewport-fit=cover”>

然后我们可以使用 constant()(IOS 11.0-11.2)或 env()(>IOS 11.2)来引用上面的变量

.selector{

 /* 利用css fallback机制,下面的代码可以兼容两种版本 */

 padding-top: env(safe-area-inset-top);

 padding-top: constant(safe-area-inset-top);

}

如果需要基于这些变量计算,可以这么写:

.selector{

 --safe-area-inset-bottom: env(safe-area-inset-bottom);

 height: calc(80px + var(--safe-area-inset-bottom));

}

需要注意, safe-area-inset-bottom这个变量的实际像素值是固定的(约为34px),如果我们对页面进行了缩放,就要重新计算。比如我们的项目中使用手淘flexible布局方案,在iPhoneX上页面的实际宽度为1125px,这时页面底部的安全区域高度应为这个值的3倍

.selector{

 padding-bottom: calc(env(safe-area-inset-bottom) * 3);

}

demo:

总结

js实现除了不够优雅没啥毛病,css实现因为是依赖于ios11版本的safari,有兼容性问题(测试发现内核为AppleWebkit/604.3.5的qq浏览器不支持,其他浏览器正常。具体兼容到哪个版本还未查到相关资料)

全部demo地址:https://marvinxu.github.io/demos/

References

  1. iPhone X - Overview - iOS Human Interface Guidelines

  2. 三分钟弄懂iPhoneX设计尺寸和适配

  3. “The Notch” and CSS

  4. Designing Websites for iPhone X

  5. iPhone X layout features with CSS Environment variables(需翻墙)

  6. CSS Round Display Level 1

如何写一个适配iPhoneX的底部导航的更多相关文章

  1. Flutter - 创建底部导航栏

    之前写过的一篇文章介绍了 Flutter - 创建横跨所有页面的侧滑菜单, 这次就一起来学习一下底部导航栏. 底部导航栏在ios平台上非常常见,app store就是这样的风格.还有就是大家最常用的微 ...

  2. Android应用底部导航栏(选项卡)实例

    现在很多android的应用都采用底部导航栏的功能,这样可以使得用户在使用过程中随意切换不同的页面,现在我采用TabHost组件来自定义一个底部的导航栏的功能. 我们先看下该demo实例的框架图: 其 ...

  3. 用vetr.x写一个HTTP接口适配器, 对接各种形式接口

    用vetr.x写一个HTTP接口适配器, 对接各种形式接口 项目地址:https://github.com/hjx601496320/transmit 业务说明 在日常开发工作中,我们经常会遇到要和各 ...

  4. android应用开发--------------看RadioGroup源代码,写相似单选选项卡的集成控件(如底部导航,tab等等)

    博客为 有时个哥 原创.如需转载请标明出处:http://blog.csdn.net/ls703/article/details/46694967 watermark/2/text/aHR0cDovL ...

  5. wap2app(八)-- iphoneX 底部导航的兼容问题

    iphoneX 没有home键,用其打开应用时,iphoneX的底部和应用底部导航重叠,不兼容. 解决办法: 打开manifest.json文件,在“plus”下加入以下代码(安全区域): " ...

  6. 01-02 Flutter仿京东商城项目 功能分析、底部导航Tab切换以及路由配置、架构搭建:(Flutter仿京东商城项目 首页布局以及不同终端屏幕适配方案)

    Flutter和Dart交流学习群:交流群:452892873 01Flutter仿京东商城项目 功能分析.底部导航Tab切换以及路由配置.架构搭建 02Flutter仿京东商城项目 首页布局以及不同 ...

  7. Vue 如何实现一个底部导航栏组件

    参考网址: https://www.jianshu.com/p/088936b7b1bd/ Vue 如何实现一个底部导航栏组件 可以看到父组件是知道我点击了底部TabBar的哪个item的. 实现 实 ...

  8. vue.js 踩坑第一步 利用vue-cli vue-router搭建一个带有底部导航栏移动前端项目

    vue.js学习 踩坑第一步 1.首先安装vue-cli脚手架 不多赘述,主要参考WiseWrong 的 Vue 爬坑之路(一)-- 使用 vue-cli 搭建项目 2.项目呈现效果 项目呈现网址:w ...

  9. 87、代码适配IphoneX

    一.APP在iphoneX运行后不能占满,上下都有多余的边 解决方法:把旧的image.xcassets中的LaunchImage删掉,重新创建并在Images.xcassets中为iPhone X添 ...

随机推荐

  1. virtualbox装个 ubuntu

    好久没弄 虚拟机了,感觉好不习惯 根据网上的步骤装了一ubuntu 启动报错 virtualbox intel_rapl: no valid rapl domains ...... 搜索到了一片中文博 ...

  2. React Native不同设备分辨率适配和设计稿尺寸单位px的适配

    React Native中使用的尺寸单位是dp(一种基于屏幕密度的抽象单位.在每英寸160点的显示器上,1dp = 1px),而设计师使用的是px, 这两种尺寸如何换算呢? 官方提供了PixelRat ...

  3. ABP 依赖注入

    1.ABP自动注入 //IapplicationService注入方式暴露接 //ITransientDependency 不会暴露接口 ITransientDependency和ISingleton ...

  4. Google资深工程师深度讲解Go语言完整教程

    资源获取链接点击这里 欢迎大家来到深度讲解Go语言的课堂.本课程将从基本语法讲起,逐渐深入,帮助同学深度理解Go语言面向接口,函数式编程,错误处理,测试,并行计算等元素,并带领大家实现一个分布式爬虫的 ...

  5. Java第4次实训作业

    编写"电费管理类"及其测试类. 第一步 编写"电费管理"类 私有属性:上月电表读数.本月电表读数 构造方法:无参.2个参数 成员方法:getXXX()方法.se ...

  6. 【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端

    [转]TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端).UDP客户端 目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP ...

  7. robotframework+selenium搭配chrome浏览器,web测试案例(搭建篇)

    这两天发布版本 做的事情有点多,都没有时间努力学习了,先给自己个差评,今天折腾了一天, 把robotframework 和 selenium 还有appnium 都研究了一下 ,大概有个谱,先说说we ...

  8. SQL语句操作数据

    --切换数据库:手动切换和命令切换 use MySchool --向Student表中插入数据 --语法:INSERT [INTO] 表名 (列名) VALUES (值列表) --注意事项: --1. ...

  9. SQL,group by分组后分别计算组内不同值的数量

    select name as 姓名,sum( case when cargo='笔' then 1 else 0 end ) as 笔,sum( case when cargo='橡皮' then 1 ...

  10. RAM和ROM

    RAM:随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器.[1]它可以随时读写(刷新时除外,见下文),而且速度很快,通常作为 ...