一站式解决:H5开发中的各类坑与技巧【1】
响应式布局
在 H5 中,我们通常会使用 REM 和 VW 这两种单位来实现页面的响应式布局。这两种单位可以让页面元素的大小随着根元素(对于 REM)或视口宽度(对于 VW)的大小变化而变化,从而适应不同尺寸的屏幕。
rem布局
引入手淘的flexible
方案进行REM布局
<script src="https://cdnjs.cloudflare.com/ajax/libs/flexible.js/0.3.2/flexible.min.js"></script>
配合使用postcss-pxtorem
插件来自动将 px 单位转换为 REM 单位
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5, // 该值应与 flexible.js 中设置的 remUnit 值相同
propList: ['*'],
minPixelValue: 2 // 设置最小的转换尺寸,如果设置为 1 则会转换所有大小的像素值
}
}
}
注意:以上rootValue
的设置值是基于设计稿的尺寸。例如,如果你的设计稿是 750px,那么你设置rootValue: 75
。如果你的设计稿是 375px,那么你设置rootValue: 37.5
。这样设置后,设计稿上的 1px 就对应于 1/100rem,方便转换。
vw布局
npm install postcss-px-to-viewport --save-dev
module.exports = {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px', // 要转化的单位
viewportWidth: 750, // UI设计稿的宽度
unitPrecision: 5, // 转换后的精度,即小数点位数
propList: ['*'], // 指定转换的css属性的单位,*表示全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: [], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: false, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否直接更换属性值,而不添加备用属性
exclude: [], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules',使用正则表达式
include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件(使用正则表达式)
landscape: false, // 是否处理横屏情况
},
},
};
在你配置完成后,你可以像平时一样在 CSS 中使用 px 单位,然后postcss-px-to-viewport
会在构建时自动将 px 单位转换为 vw 单位。
系统功能:
调用电话
<a href="tel:1234567890">Call me</a>
调用短信
<a href="sms:1234567890">Send me a SMS</a>
调用邮件
<a href="mailto:example@example.com">Email me</a>
调用图库和文件功能
<input type="file" accept="image/*">
弹出数字键盘:
适合输入电话号码
<input type="tel">
适合输入纯数字格式
<input type="number" pattern="\d*">
其他
忽略自动识别
禁止移动端浏览器自动识别电话和邮箱
<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="email=no">
唤醒原生应用
URL Scheme 示例
<a href="twitter://user?screen_name=OpenAI">Open Twitter</a>
禁止页面缩放和缓存
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="expires" content="0">
禁止字母大写
禁止字母大写功能和自动纠正功能
<input type="text" autocapitalize="off" autocorrect="off">
针对特定浏览器的配置:
Safari私有属性示例
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
监听屏幕旋转
通过使用CSS媒体查询中的orientation
选择器,您可以监听屏幕的旋转事件,并根据屏幕方向调整样式,以便页面始终保持最佳布局。
@media (orientation: portrait) {
/* 在竖屏模式下的样式 */
}
@media (orientation: landscape) {
/* 在横屏模式下的样式 */
}
禁止滚动传播
使用overscroll-behavior: contain
属性可以阻止滚动传播的问题。当内容滚动到顶部或底部时,滚动事件不会继续传递给父容器。
.container {
overscroll-behavior: contain;
}
禁止屏幕抖动
通过提前声明滚动容器的padding-right
为滚动条宽度,可以防止滚动条的出现导致屏幕抖动。
.container {
padding-right: calc(100vw - 100%);
}
禁止长按操作
使用user-select: none
和-webkit-touch-callout: none
属性可以禁止用户对元素进行长按操作,防止出现意外的行为。
.element {
user-select: none;
-webkit-touch-callout: none;
}
禁止字体调整
通过设置text-size-adjust: 100%
属性,可以阻止用户在旋转屏幕时浏览器自动调整字体大小。
body {
text-size-adjust: 100%;
}
禁止高亮显示
使用-webkit-tap-highlight-color: transparent
属性可以禁止触摸元素时的高亮显示效果,使界面更加平滑和一致。
.element {
-webkit-tap-highlight-color: transparent;
}
禁止动画闪屏
通过使用perspective
、backface-visibility
和transform-style
属性,可以解决在移动设备上动画闪屏的问题,提供更流畅的动画效果。
.element {
perspective: 1000px;
backface-visibility: hidden;
transform-style: preserve-3d;
}
自定义表单外观
使用appearance: none
属性可以自定义表单元素的样式,使其更符合您的设计需求。
input[type="text"],
input[type="email"],
textarea {
appearance: none;
}
自定义滚动滚动条
通过使用::-webkit-scrollbar-*
伪元素,可以自定义滚动条的样式,使其更加美观。
.scrollable::-webkit-scrollbar {
width: 8px;
}
.scrollable::-webkit-scrollbar-thumb {
background-color: #ccc;
}
.scrollable::-webkit-scrollbar-track {
background-color: #f1f1f1;
}
自定义输入占位文本样式
使用::-webkit-input-placeholder
伪元素,可以自定义输入框的占位文本样式,使其更加吸引人。
input::placeholder {
color: #999;
}
调整输入框文本
通过设置line-height: normal
,可以调整输入框的文本位置,使其垂直居中显示。
input {
line-height: normal;
}
对齐下拉选项
通过设置direction: rtl
,可以改变下拉框选项的对齐方式,使其从右向左排列。
select {
direction: rtl;
}
修复点击无效
在苹果系统上,有些元素无法触发click
事件。通过声明cursor: pointer
属性,可以解决这个问题。
.element {
cursor: pointer;
}
识别文本换行
通过设置white-space: pre-line
,可以让浏览器自动处理文本的换行,保留原始的换行符。
.element {
white-space: pre-line;
}
开启硬件加速
使用transform: translate3d(0, 0, 0)
属性可以开启GPU硬件加速,提高动画的流畅性和性能。
.element {
transform: translate3d(0, 0, 0);
}
控制溢出文本
使用CSS的text-overflow
、white-space
、-webkit-line-clamp
和-webkit-box-orient
属性,可以控制文本的单行和多行溢出,使其更加易读。
.element {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.element.multiline {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
iPhoneX 系列手机适配问题
现象
在 iPhoneX 系列手机上,头部或底部区域可能会出现刘海遮挡文字或点击区域的情况,或者出现黑底或白底的空白区域。
原因
iPhoneX 及以上版本手机采用了特殊的设计,包括状态栏、圆弧展示角、传感器槽、主屏幕指示器和屏幕边缘手势。为了适配这些特性,头部、底部及侧边栏都需要做特殊处理,使 content 尽可能地处于安全区域内。
解决方案
1、设置 viewport-fit meta 标签为 cover,使内容能够填充所有区域,并对 iPhone X 进行特殊适配。
<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">
2、利用 WebKit 的新 CSS 函数 constant() 和 env(),以及四个预定义的常量:safe-area-inset-left, safe-area-inset-right, safe-area-inset-top 和 safe-area-inset-bottom,来设置安全区域。
body {
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
padding-left: constant(safe-area-inset-left);
padding-left: env(safe-area-inset-left);
padding-right: constant(safe-area-inset-right);
padding-right: env(safe-area-inset-right);
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
3、为底部固定的元素增加适应 iPhoneX 系列手机的底部小黑条和圆角的底部高度。
click 点击延迟与穿透问题
现象
在 iOS 设备上,单击事件可能会有 300ms 的延迟,因为 Safari 浏览器需要在单击 300ms 后判断用户是否进行了第二次点击以实现双击缩放操作。此外,点击穿透问题也常见,如点击蒙层,蒙层消失后可能会触发蒙层下层元素的点击事件。
解决方案
禁止缩放:通过设置 meta 标签的
user-scalable=no
来禁止用户缩放。使用 touch 事件替代 click 事件:这可以消除延迟,因为 touch 事件没有 300ms 延迟。
function tap(obj, callback) {
var startTime = 0;
var flag = false;
obj.addEventListener('touchstart', function(e) {
startTime = Date.now();
});
obj.addEventListener('touchmove', function(e) {
flag = true;
});
obj.addEventListener('touchend', function(e) {
if (!flag && (Date.now() - startTime) < 150) {
callback && callback();
}
flag = false;
startTime = 0;
});
}
使用 FastClick 库:FastClick 库可以解决 click 延时和穿透问题。
<script type='application/javascript' src='/path/to/fastclick.js'></script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
使用 CSS 的 pointer-events 属性:通过设置 pointer-events: none,可以让鼠标点击事件失效,从而解决点击穿透问题。
.element {
pointer-events: none;
}