整理归纳一些之前记录的h5兼容性问题以及相应的解决方法,大多都是移动端的,持续更新…
1、iOS滑动卡慢
- ios里父元素设置overflow:auto或scroll时,子元素滚动时没有滚动惯性,手指离开屏幕就立即停止滚动,所以会有一种卡和慢的感觉。
- 目前发现ios13及以上系统没有这个问题,但低版本的还会出现,需要解决。
- 解决方法:
css里给滚动父元素设置:
-webkit-overflow-scrolling: touch;
- 慎用-webkit-overflow-scrolling属性,会有很多坑,例如内部fixed层级失效、绝对定位元素被父元素padding覆盖等。
- 为了避免使用这个属性带来的副作用,个人总结了以下最佳实践:
.index {
height: 100%;
.content {
height: 100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
}
(1) 不要直接给顶层盒子index使用,而是给子盒子content使用。
(2) 凡是相对于屏幕而固定位置的都使用fixed固定定位,不要用absolute。
(3) 所有fixed固定定位的盒子都不要放在content里,应该放index里和content平级。
2、多行文本溢出隐藏时文字被遮挡
- 常见于移动端,比如设置两行文本溢出隐藏显示省略号,个别机型会出现第二行文字下面部分显示不全。
- 解决方法:
在添加溢出隐藏样式的盒子外再套一层父盒子,给这个父盒子设置固定高度,使高度撑起来。
3、android端文字未垂直居中
-
情况一:文字偏上
- 使用height等于line-height或者通过设置上下padding使文字垂直居中的方法在android会有问题,文字偏上,个别安卓机型比较明显。
- 这是个历史问题,简单点说就是css设计时就给字体底部预留了一定的空间用于展示特殊字符,所以实际占用空间比文字看起来的高度要高。
- 解决方法:
给文字所在的元素设置flex布局,通过align-items: center属性来控制垂直居中,并添加padding-top: 1px。
这样基本能满足需求,必要时可以再适当加大padding-top,但是一般建议1px够了,因为不是所有机型都有未垂直居中的问题,避免矫枉过正。
-
情况二:文字偏下
- 这种情况要看一下在浏览器中文字实际占据的高度和父盒子占据的高度的差值,这个差值如果是奇数,可能在手机就出现文字偏下,可能是移动端css解析间距时最低只精确到1px导致。
- 解决方法:
凑个整呗,给父盒子高度加一或减一,使间距差值凑个偶数,这样一分为二就是整数,也就居中了。
4、移动端页面跳转时窗口高度变小
- 移动端输入法弹窗弹起时,会导致页面窗口高度变小,此时如果跳转到了另一个html页面,会出现另一个页面刚打开时获取到的窗口高度是缩小后的高度。
- 解决方法:
方法1:跳转页面之前,先通过document.activeElement.blur()隐藏输入法键盘,然后延时300毫秒左右再跳转页面。
方法2:跳转前先通过window.innerHeight获取输入法未弹起时的窗口高度,再通过地址传参的方法传递该高度值。
5、ios的数字被识别为电话号码,有默认样式
- 个别ios机型会自动把一些数字识别为电话号码,添加了默认样式,比如网站备案号之类的,而且通过设置meta标签也无法去除。
- 解决方法:
把被识别为号码的内容通过::before或after伪元素来设置。
6、ios底部margin-bottom失效
- css里的margin不稳定,能不用就不用,能用padding代替就用padding,特别是margin-top和margin-bottom还有其他例如上边距吸顶和下边距重叠的问题。
- 解决方法:
设置一个空的div撑起margin-bottom设置的高度。
7、定位元素被输入法顶起
- 输入法弹起时,窗口高度缩小,导致定位在窗口底部的定位元素被顶起,可能会遮盖内容元素。
- 解决方法:
方法一:input获取焦点时,让定位元素隐藏或改为静态定位,失去焦点时再恢复。
方法二:不使用输入法键盘,而改用前端手写的模拟键盘。 - 附(移动端监听输入法键盘弹起及收起的通用方法):
if (isAndroid) {
// 安卓输入法弹起时页面容器高度会缩小,而ios不会,通过监听窗口resize事件,判断html元素的高度。
const htmlHeight = document.documentElement.offsetHeight
function setKeyboardActive () {
const currentHeight = document.documentElement.offsetHeight
if (currentHeight < htmlHeight) {
// 输入法弹起
} else {
// 输入法收起
}
}
window.addEventListener('resize', setKeyboardActive, { passive: true })
} else if (isIos) {
// ios在输入法收回时焦点元素会失焦,而安卓不会,通过监听focusin和focusout,获取聚焦和失焦的冒泡事件
function setKeyboardActiveTrue () {
// 输入法弹起
}
function setKeyboardActiveFalse () {
// 输入法收起
}
window.addEventListener('focusin', setKeyboardActiveTrue, { passive: true })
window.addEventListener('focusout', setKeyboardActiveFalse, { passive: true })
}
8、ios后台运行时倒计时不准
- ios应用后台运行时,js的定时器的执行频率会降低直至暂停执行,恢复至前台运行时就发现倒计时时间与预期不符。
- 解决方法:不通过执行循环次数来判断倒计时时间,改用时间戳判断。
9、安卓9.0不显示图片
- 安卓9.0开始,不支持https协议的网页内使用http协议的图片地址。
- 解决方法:
方法1:推荐,换用https的图片地址。
方法2:安卓客户端配置android:usesCleartextTraffic=“true”,出于安全考虑,不建议。
10、ie设置flex纵向布局撑不开
- ie下设置 display: flex; flex-direction: column; 时,如果子元素设置 flex: 1 无法撑开内容,会覆盖顶部。这是因为 flex: 1 在ie下会被解析成flex: 1 1 0,而chrome会解析为flex: 1 1 0%
- 解决方法:
不使用 flex: 1 这种简写形式,改用 flex: 1 1 0%
11、audio标签autoplay无法自动播放
- 由于浏览器的安全限制、防噪音等,音频不允许自动播放。
- 解决方法:
浏览器的限制无法突破,只能通过人为交互来触发,比如点击或滑动事件里,获取audio标签元素,调用play()方法开始播放。
12、滚动到顶部无效
- 原生js的scrollTo方法在个别机型存在兼容性问题。
- 解决方法:
改用ele.scrollTop = 0 的方式,让滚动父容器滚动到指定位置。
13、ios固定定位fixed层级不对
- ios里定位的层级取决于父元素的层级,不管是absolute还是fixed,而安卓里fixed层级是独立计算的。
- 解决方法:
给父元素也加定位并设置较大的z-index值。
(最好是一开始就把所有fixed定位元素放在同级dom下。)
14、ios下父元素设置overflow: hidden子元素仍超出
- ios父元素设置了border-radius和overflow: hidden,子元素设置绝对定位,仍然会超出,导致边框圆角无效果。
- 解决方法:
父元素设置transform: rotate(0deg);
15、ios元素盒子下边框不显示
- ios个别机型,元素设置的下边框被遮挡或未显示。
- 解决方法:
给盒子父元素添加高度撑起来。
16、中文输入法下触发input事件
- 中文输入法在输入拼音但还没显示在输入框时也会触发输入框的input事件,有些场景下会有副作用,比如输入框搜索联想功能,会产生不必要的接口请求。
- 解决方法:
js原生有个api可以监听非直接输入事件(包括中文输入),
// (“inputElement”指代输入框元素dom对象)
// 开始非直接输入时触发,在这个事件里可以通过改变一个flag变量来控制这个阶段不触发你的业务逻辑
“inputElement”.addEventListener('compositionstart', function(){})
// 结束非直接输入(开始直接输入)时触发,这里可以改回flag变量,正常触发你的业务逻辑了
“inputElement”.addEventListener('compositionend', function(){})
17、格式化输入手机号时光标错位问题
- 在一些要输入手机号的输入框需求里,有时需要对手机号进行344划分显示,例如:131 1111 1111,在边输入边自动格式化时个别机型可能出现输入光标错位问题,导致输入的手机号也乱了。
- 解决方法:
利用原生js的setSelectionRange方法,
HTMLInputElement.setSelectionRange 方法用于设定 input 或 textarea元素中当前选中文本的起始和结束位置。
// 以vue代码示例
<input v-model="phone" @input="setPhone"/>
setPhone(eve) {
this.formatPhone(this.phone)
setTimeout(() => {
var lenth = this.phone.length
eve.target.setSelectionRange(lenth, lenth)
}, 20)
}
18、ios屏幕外的图片不显示
- 一般在写页面时遇到图片不应该直接写个img标签,而是在外层套一层div父盒子,方便对图片做各种控制,而如果图片需要圆角边框之类的需求,在给图片父盒子加代码来实现时在ios端个别机型会遇到屏幕外的图片(滑动查看后仍然)不显示的问题。
- 上述以圆角边框来说明是因为要设置圆角边框就得加overflow:hidden样式,其实这个问题就是图片父盒子的overflow:hidden代码导致的。
- 解决方法:直接给img标签加overflow:hidden等样式来控制,代码示例如下:
.imgBox {
width: 100px;
height: 100px;
img {
width: 100%;
height: 100%;
display: block;
border-radius: 6px;
overflow: hidden;
}
}