移动端兼容性问题总结
1. ios 移动端页面对点击事件有 300ms 延时
使用 fastclick 库 https://github.com/ftlabs/fastclick
使用 FastClick 的时候,在需要使用的层上,实例化它。我们使用 document.body 是因为希望所有的按钮和链接都获得快速点击
import FastClick from 'fastclick' |
2. ios 滚动卡顿
div { |
3. ios 1px border 变宽
以 dpr = 2 为例:
你拿到一张标准的基于 iphone6 的设计稿(750px)
你看到它设计的一个 border 宽度是 1px
你兴致勃勃地写下了 border: 1px solid #000;
然而 iphone6 实际渲染像素是 375px,那么设计需要 border 的其实是 border: 0.5px solid #000;
然后你的是 1px
不是 1px 变粗了,只是实际只是需要 0.5px 而已
<meta name="viewport" content="width=device-width">
意思是将物理设备的宽度设置给当前浏览器
在使用 table 标签设置 border: 1px
并使用 border-collapse: collapse;
合并边框后,发现 td 之间的边框宽度并不是 1px,而是比 1px 宽,大概为 1.5px
4. webapp 软键盘弹起时问题
其他参考链接 https://segmentfault.com/a/1190000010693229
https://github.com/ioing/IOING
页面放大:
<meta name="viewport" content="user-scalable=no" /> |
输入框被遮挡,看不见输入的内容: document.activeElement.scrollIntoView()
页面自动上移,但收回软键盘时页面没有恢复原样少了一截
fixed 定位效果失效: ios 弹出软键盘的时候, webview 的高度没有变化导致超出屏幕范围,并且不会触发 resize 事件
scrollIntoView 与 scrollIntoViewIfNeeded
Element.scrollIntoView(option) 方法让当前的元素滚动到浏览器窗口的可视区域内
option 如果为 true,元素的顶端将和其所在滚动区的可视区域的顶端对齐, 默认
option 如果为 false,元素的底端将和其所在滚动区的可视区域的底端对齐
element.scrollIntoViewIfNeeded() 用来将不在浏览器窗口的可见区域内的元素滚动到浏览器窗口的可见区域。 如果该元素已经在浏览器窗口的可见区域内,则不会发生滚动
var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0 |
<input @focus="input(1)" @blur="input(2)" /> |
input (num) { |
附:安卓手机监听 resize
data () { |
5. 手机端页面文件上传兼容性问题
6. 移动端和 PC 端中的 hover 处理 移动端点击时会有 pc 端 hover 效果
百度一下给出的方式是注册 touchstart 事件
document.body.addEventListener('touchstart', function() {}) |
但经过测试并没有解决该问题
7. 移动端 touch 时,会触发 pc 端的 mouseenter mouseleave 事件
在事件中通过判断屏幕宽度解决
8. ios a 链接 input type=”file” 等在点击时会出现灰色(touch 高亮)
-webkit-tap-highlight-color: transparent; |
9. 禁用浏览器自动调整字体大小
移动端浏览器切换橫向模式时会调整字体大小(字体变大),解决方式:
html { |
谷歌浏览器已不支持这个属性了,不能通过该方式实现小于 12px 的字体,可使用缩放(transform:scale(0.8))来实现小于 12px 的字体
10. appearance 属性
normal|icon|window|button|menu|field
所有主流浏览器都不支持 appearance 属性
-webkit-appearance: none;
去除默认样式,使 ios 端和安卓端显示效果一样,但有一个问题,input 的 checkbox 和 radio 类型在安卓端可能无法正常显示
11. 禁止长按
在 iOS 上,当你触摸并按住触摸的目标,比如长按一个链接,浏览器将显示链接有关的系统默认菜单,
长按图像弹出选项存储或者拷贝图像,长按文字弹出选择文字菜单
可通过如下方式禁止这些行为
禁止长按图片保存
img { |
禁用长按复制
user-select: none; |
禁止长按呼出菜单
div { |
12. 点击穿透
假如页面上有两个元素 A 和 B。B 元素在 A 元素之上。我们在 B 元素的 touchstart 事件上注册了一个回调函数,该回调函数的作用是隐藏 B 元素。我们发现,当我们点击 B 元素,B 元素被隐藏了,随后,A 元素触发了 click 事件。
这是因为在移动端浏览器,事件执行的顺序是 touchstart > touchend > click。而 click 事件有 300ms 的延迟,当 touchstart 事件把 B 元素隐藏之后,隔了 300ms,浏览器触发了 click 事件,但是此时 B 元素不见了,所以该事件被派发到了 A 元素身上。如果 A 元素是一个链接,那此时页面就会意外地跳转。
跨页面点击穿透问题 点击页内按钮跳转至新页,然后发现新页面中对应位置元素的 click 事件被触发了
13. 移动端 video 播放时不弹出页面层
<video x5-playsinline="" playsinline="" webkit-playsinline=""></video> |
14. vue 移动端监听 scroll
mounted () { |
15. vue 移动端列表保存滚动位置
beforeRouteEnter (to, from, next) { |
16. 移动端去除 type 为 number 的箭头
input::-webkit-outer-spin-button, |
17. 设置状态栏的背景颜色(IOS)
设置状态栏的背景颜色,只有在”apple-mobile-web-app-capable” content=”yes”时生效
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> |
content 参数:
default :状态栏背景是白色。
black :状态栏背景是黑色。
black-translucent :状态栏背景是半透明。 如果设置为 default 或 black ,网页内容从状态栏底部开始。
如果设置为 black-translucent ,网页内容充满整个屏幕,顶部会被状态栏遮挡。
18. 弹出数字键盘
<!-- 有"#" "*"符号输入 --> |
打开原生应用
某些浏览器会禁用此协议,比如微信内部浏览器(除非开了白名单)
<a href="weixin://">打开微信</a> |
解决 IOS下 active 伪类失效
给 body 注册一个空事件即可
<body ontouchstart></body> |
最简单的 rem 实现
@media (min-width: 640px) { |
better-scroll 解决移动端滚动问题
https://github.com/ustbhuangyi/better-scroll/
iphone X 适配 - 安全区域(safe area)
参考:https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/
在 iOS 11 中采用了 viewport-fit
的 meta 标签作为适配方案
viewport-fit
取值
auto 默认:页面内容显示在 safe area 内
cover 页面内容充满屏幕,可以通过添加边距保证网页主要内容处于 safe area 中不被裁剪
iOS 11 的 webview 引入了 constant
、env
来处理 viewport-fit=cover
属性,以及一组四个预定义的常量:safe-area-inset-left
, safe-area-inset-right
, safe-area-inset-top
和 safe-area-inset-bottom
,分别表示 safe area 和可视窗口 viewport 顶部,右边,左边,底部的间距,可以用于设置 margin 和 padding 或者绝对定位时 left 和 top,这四个常量只有在 viewport-fit=cover
时有效
建议使用 viewport-fit=cover
因为会使用 auto 会造成屏幕四周出现白边
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" /> |
/* top 为 0 的 fixed 定位的 heade */ |
body { |