社区精选|谈谈 H5 移动端适配原理
共 13006字,需浏览 27分钟
·
2023-09-08 03:04
今天小编为大家带来的是社区作者 熊的猫 的文章,让我们一起来学习 H5 移动端适配原理。
H5 移动端 开发的必不可少的一个环节就是 移动端网页的适配,因为 UI 通常只会提供 大小固定的设计稿,而各种不同移动设备具有不同的页面分辨率和大小,所以适配的目的就是让一份设计稿在不同移动设备上表现出一致性。
虽然现如今各种插件都可以帮助我们快速配置完成,例如 lib-flexible
、postcss-pxtorem
、postcss-px-to-viewport
等等,但不少小伙伴在被问及相关原理时却很难说清楚,那么本篇文章我们就一起来探究一下其中原理吧!!!
文中有不当之处,欢迎在评论区指正
CSS 中的尺寸单位
px 像素单位
px 全称为 pixel(像素),它是相对于 屏幕显示器分辨率(桌面设定的分辨率,不是显示器的物理分辨率) 而言的,在 相同/不同 的设备上 1px 表示多个 设备像素。
em 相对单位
rem (root em) 相对单位
-
rem 相对于 html 根元素的,因此在 body 标签里面设置 font-size 是不起作用的 -
因此 rem 就可做到 目标元素 与 根元素 间保持 成比例 的大小关系,又可以避免字体大小逐层复合的连锁反应等,例如公共的字体大小可以在 body 中设置即可
vw 和 vh
-
vw 全称是 viewport width,代表的是 视口的宽度,相对于 视口 viewport 的 宽度 -
vh 全称是 viewport height,代表的是 视口的高度,相对于 视口 viewport 的 高度 -
vw 和 vh 是将 视口 宽/高 都分成 100 份,因此 100vw = 视口宽、100vh = 视口高
-
vmin 和 vmax 代表的是 视口宽度 和 视口高度 中的 最小值 和 最大值 -
vmin = 视口高度 vh 和 宽度 vw 间的最小值 -
vmax = 视口高度 vh 和 宽度 vw 间的最大值
适配方案
核心原理
将 设备视口 划分成 n 份, n 可以是 任何正确的值(如 flexible.js 中的 n = 10)
设置 设备视口 根元素 html 的 font-size = 设备视口宽 ÷ 份数 n,即得到 设备视口 1 rem 到底表示 多少设备视口 px
将 设计稿 也同样划分成 n 份,此时 设计稿中的 a px 对应 设备视口 b rem 的计算方式为
设备视口 b rem = 设计稿 a px ÷ (设计稿 宽 ÷ n 份)
举个例子
设备视口宽为 375px
(function (n = 10){
const dEl = document.documentElement;
function setRem(){
const rem = dEl.clientWidth / n;
dEl.style.fontSize = rem + 'px';
}
// 初始化执行
setRem()
// 视口大小变动时执行
window.onresize = setRem
})()
设计稿宽为 750px
-
将 设计稿 也分成 10 份,每份大小 = 750 ÷ 10 = 75 px -
此时 设计稿 上的 "点我拍照"(font-size: 34px) 的文案转换成符合 设备视口 对应的 rem 就为:
设备视口 中 文字 font-size = 34 ÷ 75 = 0.4533333333333333 rem ≈ 0.45 rem
【注意】 一般计算结果(人为计算、插件自动化自动化计算)都不会使用这么长的小数位,比如 0.4533333333333333 rem ≈ 0.45 rem,此时:
原始值 0.4533333333333333 rem = 0.4533333333333333 * 37.5 = 17 px 保留两位小数后的值 0.45 rem = 0.45 * 37.5 = 16.875 px 而在肉眼观察下 16.875 px 和 17 px 是没有差别的,因此可以忽略不计
用 amfe-flexible 和 postcss-pxtorem 验证
-
34px 转换成 rem = 34 ÷ 75,这种不直观的计算叫 复杂计算,若可以实现 34 ÷ 100 即可得到相应的 rem 的方式,就称为 简单计算(任何数除以 10 或 100 都很容易口算)
vw/vh 适配
-
rem 的适配方式支持自定义将设备视口划分为 n 份,n 可以是任何正确值 -
vw/vh 就是将设备视口划分为 100 份,不支持自定义
CSS 预处理器 — 简化计算
// plugin.js
module.exports = {
install: function (less, pluginManager, functions) {
functions.add('px2vw', (param, perVW) => {
if (!param.value) return '0vw'
if (!perVW.value) return param.value + 'px'
return Number(param.value) / perVW.value + 'vw'
})
},
}
// 具体使用
<style lang="less">
@plugin './plugin.js';
@design-width: 750;
@per-vw: @design-width / 100;
.text {
font-size: px2vw(34, @per-vw);
color: #457fff;
}
</style>
<style lang="scss">
$design-width: 750;
$per-vw: $design-width / 100;
@function px2vw($param) {
@return $param / $per-vw + 'px';
}
.text {
font-size: px2vw(34);
color: #457fff;
}
</style>
使用 postcss-px-to-viewport 进行验证
文本和原始样式
postcss-px-to-viewport 配置
等比缩放 — viewport <meta> 标记
(function (designWidth) {
const dEl = document.documentElement;
let meta = document.querySelector("meta[name=viewport]");
// 页面中不存在 <meta name="viewport" /> 时,手动创建一个
if(!meta) {
meta = document.createElement('meta');
meta.setAttribute('name', 'viewport');
document.head.appendChild(meta);
}
function setMetaContent(){
const deviceWidth = dEl.clientWidth;
const scale = deviceWidth / designWidth;
const content = `width=${deviceWidth}, initial-scale=${scale}`;
meta.setAttribute("content", content);
}
setMetaContent();
window.addEventListener("resize", setMetaContent)
})(750);
第三方组件库如何做适配?
-
Viewport 布局 -
Vant 默认使用 px
作为样式单位,如果需要使用viewport
单位 (vw, vh, vmin, vmax),推荐使用 postcss-px-to-viewport 进行转换 -
Rem 布局适配 -
postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位 -
lib-flexible 用于设置 rem 基准值 -
桌面端适配 -
若需要在桌面端使用 Vant,可以引入 @vant/touch-emulator,这个库会在桌面端自动将 mouse
事件转换成对应的touch
事件,使得组件能够在桌面端使用
vant-ui:https://vant-ui.github.io/vant/#/zh-CN/advanced-usage
postcss-px-to-viewport :https://github.com/evrone/postcss-px-to-viewport
postcss-pxtorem:https://github.com/cuth/postcss-pxtorem
lib-flexible:https://github.com/amfe/lib-flexible
@vant/touch-emulator:https://github.com/vant-ui/vant/tree/main/packages/vant-touch-emulator
最后
往期推荐
社区精选|纳尼!CSS 也能实现碰撞检测?
社区精选|记一次 Vue-CLI 生产项目的打包优化
社区精选|TypeScript 玩转类型操作