前端系列——与众不同的移动端底部固定栏 fixed、absolute 兼容 iOS 和 Android 方案

本文主要是介绍前端系列——与众不同的移动端底部固定栏 fixed、absolute 兼容 iOS 和 Android 方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

相信我,我分享的和你在其他博客上看到的终极方案是如此的与众不同!

做过移动端开发的同学,对底部DOM定位出现的各种奇葩情况已经深恶痛绝了吧,底部DOM设置不同的position,在Android和ios上表现都不一样。

为了兼容Android和ios,很多人都煞费苦心,也包括我。

打开你做的H5,尤其是在微信上打开看看,是不是觉得很恶心,如果自我感觉很恶心,那么请往下看这篇文章,不恶心说明你成功了,可以走了!

最终还是成功解决了,这篇文章记录一下兼容2种设备的方案。

第一种情况

据我所知,网上还找不到一个能够真正解决这个问题的教程,因为大多数人都是只考虑在body scroll的情况下,设置底部为fixed或者absolute,然后设置滚动区域padding-bottom的值,这种做法反正我是无法接受的,体验太不爽了,也没有兼容Android和ios。

下图是第一种情况,滚动区域有表单,底部一个固定栏,当填写表单的时候,我们看看ios和Android的表现情况:

1、底部定位为fixed的情况下

ios:激活输入框时,底部不会弹出来(合理)。
Android:激活输入框时,底部会跟着输入框弹出来(不合理)。

2、底部定位为absolute的情况下

ios:激活输入框时,底部不会弹出来(合理)。
Android:激活输入框时,底部会跟着输入框弹出来(不合理)。

android后遗症:输入框失焦的时候,可能导致底部显示在浏览器中间某个位置,回不到原位置。

absolute后遗症:底部按钮和输入框区域一起随着body滚动,不再置顶独立。当滚动区域超过一屏幕时,底部输入框定位出现错乱。

clipboard.png

传统解决办法

通常将底部设置为fixed,当激活输入框的时候,将底部定位改为relative,即可兼容ios和Android。

第二种情况

底部如果是个输入框的情况下,我们肯定需要输入框在激活的时候弹出来,和第一种情况是相反的。

1、底部定位为fixed的情况下

ios:激活输入框时,底部不会弹出来(不合理)。
Android:激活输入框时,底部会跟着输入框弹出来(合理)。

2、底部定位为absolute的情况下

ios:当滚动区域超过一屏幕时,底部输入框定位出现错乱(不合理)。
Android:当滚动区域超过一屏幕时,底部输入框定位出现错乱(不合理)。

clipboard.png

传统解决办法:

仍旧是采用fixed定位

ios:在激活输入框的时候,执行下面代码

setTimeout(() => document.body.scrollTop = document.body.scrollHeight, 500)

android: 表现正常

传统解决方案的后遗症

除了抖动问题,还有就是微信端滚动body会显示微信浏览器背景,也就是超出滚动边界回弹效应,还有一个恶心的问题是当有弹框的时候,弹框和body滚动累加的双重滚动会有点击穿透造成的卡顿问题。

由此,如果你还寄希望于body滚动,那么你的移动端开发体验真的一塌糊涂。

搭建真正的移动端滚动架构

看到这里,你可以暂时把上面的传统解决方案统统忘记。

下面我将会分享移动端最舒适的架构方案。

1、你可能听过Iscroll,这个东西是我们今天要用到的框架的鼻祖,但我们不是用它,而是我曾经另外一篇文章介绍到的JRoll框架(比IScroll更加轻量和兼容的移动端滚动框架)。

2、使用这款框架对我们解决底部定位问题还有优化弹框体验有什么帮助呢?他可以完美解决传统解决方案的后遗症,因为他并不是使用body滚动,而是使用css3滚动,采用GPU加速,在ios和Android上测试并不卡顿。如果你想做出像app一样流程的H5,别再用那恶心的body滚动了。

源码(复制查看效果,别忘了导入js插件)

下面的源码你可以直接复制到一个html文件上测试,代码中我提供了多种功能的解决方案:

1、采用滚动框架时,何时获取滚动区域的高度(看源码)

2、输入框底部固定时,在该框架中兼容ios和Android的方法(看源码)

3、采用DocumentFragment动态渲染5000个列表元素,说到这个有点意思,记得腾讯某部门的社招面试题就是考察这个知识点,一般人可能采用的是for循环加innerHTML的方法(看源码)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5, user-scalable=no"><title>Title</title><style>* {padding: 0;margin: 0;}body, html {font-size: 24px;height: 100%;}ul {padding-bottom: 1rem;}ul li {list-style: none;}.bottom {position: fixed;bottom: 0;left: 0;width: 100%;height: 4.0833rem;}.bottom > input {width: 100%;border: 0;outline: 0;background: rgb(246, 246, 246);color: rgb(255, 255, 255);text-align: center;line-height: 4.0833rem;font-size: 1.25rem;}</style>
</head>
<body>
<div id="scroll-body"><ul></ul>
</div>
<div class="bottom"><input type="text" placeholder="请输入内容" onfocus="evocation()"></div>
<script src="./js/jroll.js"></script>
<script>function getClientHeight() {
//        获取移动端屏幕高度var winHeightif (window.innerHeight) {winHeight = window.innerHeight;} else if ((document.body) && (document.body.clientHeight)) {winHeight = document.body.clientHeight;} else if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth) {winHeight = document.documentElement.clientHeight;}return winHeight}var scrollBody = document.querySelector('#scroll-body') //获取滚动区域的DOMvar bottom = document.querySelector('.bottom') //获取底部DOMfunction renderLi() {//渲染li列表,采用DocumentFragment方案var ul = document.querySelector('ul')var dFrag = document.createDocumentFragment()var startTime = new Date().getTime()for (var i = 0; i < 5000; i++) {var li = document.createElement("li")li.textContent = idFrag.appendChild(li)}ul.appendChild(dFrag)var endTime = new Date().getTime()console.log('渲染耗时:', endTime-startTime, 'ms')}function evocation() {//ios唤出弹框,Android的不需要setTimeout(() => document.body.scrollTop = document.body.scrollHeight, 500)}renderLi()document.addEventListener('DOMContentLoaded', function() {var height = getClientHeight() - bottom.offsetHeight //获取滚动区域高度scrollBody.style.height = height + 'px' //计算出实际的滚动区域的高度,然后设置new JRoll(scrollBody) //实例化JRoll插件})
</script>
</body>
</html>

总结

使用上面提供的框架,你在移动端开发中,不再需要担心底部固定的问题,不再需要担心滚动造成的一系列问题,不再需要担心弹框滚动以及点击弹框造成的穿透问题等。

而且,不知道你发现没有,底部固定栏你现在可以尝试使用fixed、absolute、relative等设置,不再局限于只能使用fixed了。感兴趣就好好研究一下代码吧!

但是

在IOS11版本中,我发现了document.body.scrollTop = document.body.scrollHeight无效的bug,目前还没找到原因,小于IOS11一切正常。

这里也封装了React版本的插件,可以下载使用:react-roll-container

转载https://segmentfault.com/a/1190000012310521

这篇关于前端系列——与众不同的移动端底部固定栏 fixed、absolute 兼容 iOS 和 Android 方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/509401

相关文章

使用Vue-ECharts实现数据可视化图表功能

《使用Vue-ECharts实现数据可视化图表功能》在前端开发中,经常会遇到需要展示数据可视化的需求,比如柱状图、折线图、饼图等,这类需求不仅要求我们准确地将数据呈现出来,还需要兼顾美观与交互体验,所... 目录前言为什么选择 vue-ECharts?1. 基于 ECharts,功能强大2. 更符合 Vue

Vue中插槽slot的使用示例详解

《Vue中插槽slot的使用示例详解》:本文主要介绍Vue中插槽slot的使用示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、插槽是什么二、插槽分类2.1 匿名插槽2.2 具名插槽2.3 作用域插槽三、插槽的基本使用3.1 匿名插槽

springboot+vue项目怎么解决跨域问题详解

《springboot+vue项目怎么解决跨域问题详解》:本文主要介绍springboot+vue项目怎么解决跨域问题的相关资料,包括前端代理、后端全局配置CORS、注解配置和Nginx反向代理,... 目录1. 前端代理(开发环境推荐)2. 后端全局配置 CORS(生产环境推荐)3. 后端注解配置(按接口

Vue 2 项目中配置 Tailwind CSS 和 Font Awesome 的最佳实践举例

《Vue2项目中配置TailwindCSS和FontAwesome的最佳实践举例》:本文主要介绍Vue2项目中配置TailwindCSS和FontAwesome的最... 目录vue 2 项目中配置 Tailwind css 和 Font Awesome 的最佳实践一、Tailwind CSS 配置1. 安

利用Python实现可回滚方案的示例代码

《利用Python实现可回滚方案的示例代码》很多项目翻车不是因为不会做,而是走错了方向却没法回头,技术选型失败的风险我们都清楚,但真正能提前规划“回滚方案”的人不多,本文从实际项目出发,教你如何用Py... 目录描述题解答案(核心思路)题解代码分析第一步:抽象缓存接口第二步:实现两个版本第三步:根据 Fea

CSS3 布局样式及其应用举例

《CSS3布局样式及其应用举例》CSS3的布局特性为前端开发者提供了无限可能,无论是Flexbox的一维布局还是Grid的二维布局,它们都能够帮助开发者以更清晰、简洁的方式实现复杂的网页布局,本文给... 目录深入探讨 css3 布局样式及其应用引言一、CSS布局的历史与发展1.1 早期布局的局限性1.2

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

CSS引入方式和选择符的讲解和运用小结

《CSS引入方式和选择符的讲解和运用小结》CSS即层叠样式表,是一种用于描述网页文档(如HTML或XML)外观和格式的样式表语言,它主要用于将网页内容的呈现(外观)和结构(内容)分离,从而实现... 目录一、前言二、css 是什么三、CSS 引入方式1、行内样式2、内部样式表3、链入外部样式表四、CSS 选

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R