谈谈 H5 移动端适配原理

前言

虽然现如今各种插件都可以帮助我们快速配置完成,例如 lib-flexiblepostcss-pxtorempostcss-px-to-viewport 等等,但不少小伙伴在被问及相关原理时却很难说清楚,那么本篇文章我们就一起来探究一下其中原理吧!!!

文中有不当之处,欢迎在评论区指正!!!

CSS 中的尺寸单位

在了解具体的适配方案之前,我们先把 CSS 中适配会涉及到的相关尺寸单位进行一个了解吧,总结起来就是一句话:CSS 中的尺寸单位都是 相对长度单位,只是相对的目标不同

px 像素单位

px 全称为 pixel(像素,它是相对于 屏幕显示器分辨率(桌面设定的分辨率,不是显示器的物理分辨率 而言的,在 相同/不同 的设备上 1px 表示多个 设备像素

当 一个像素点越大 时, 呈现的图像就会 越模糊;当一个像素点越小时, 像素点就会 越密集, 呈现的图像就会 越清晰

em 相对单位

好多人都认为 em 就是相对于 父元素 font-size,实际上在不同的 CSS 属性当中使用 em 其相对的目标也是不同,如下:

  • 用于 font-size 中则是相对于 父元素 font-size 大小

  • 用于 其他属性(如 width,height) 中使用是相对于 自身 font-size 大小

 

值得注意的是,若 当前元素/父元素 的 font-size 未设置,由于 font-size 属性值可被继承的原因,可逐级向上查找,最终找不到则相对于浏览器默认字体大小,即 font-size = 16px

rem (root em) 相对单位

rem 是 CSS3 新增的一个相对单位,它只相对于 根元素 html 的 font-size 字体大小,rem 与 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 和 vmax 代表的是 视口宽度 和 视口高度 中的 最小值 和 最大值

  • vmin = 视口高度 vh 和 宽度 vw 间的最小值

  • vmax = 视口高度 vh 和 宽度 vw 间的最大值

适配方案

rem 适配(等比适配)

核心原理

  • 将 设备视口 划分成 n 份, n 可以是 任何正确的值(如 flexible.js 中的 n = 10

    • 设置 设备视口 根元素 html 的 font-size = 设备视口宽 ÷ 份数 n,即得到 设备视口 1 rem 到底表示 多少设备视口 px

  • 将 设计稿 也同样划分成 n 份,此时 设计稿中的 a px 对应 设备视口 b rem 的计算方式为

    • 设备视口 b rem = 设计稿 a px ÷ (设计稿  ÷ n 份)

举个例子

设备视口宽为 375px

  • 将设备视口分成 10 份,设置 根元素 html 的 font-size = 375 ÷ 10 = 37.5 px,即 1 rem = 37.5 px

(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 验证

  • 文本和原始样式

  • amfe-flexible  postcss-pxtorem 配置

  • 最终展示效果

 

早期 rem 适配优化(过期方案,了解即可

在早期还没有各种 CSS 预处理器 和 自动化计算的插件 时(即 还需要人为计算时),上述 rem 适配的方案 有一个缺点,那就是针对 设计稿中不同的 px 的转换为 设备视口 rem 的计算过程还是比较繁琐,特别是一些比较难算的数值。

例如,上述将 设计稿 34px 转换为 设备视口 0.9rem 的例子,对大部分人来说是不能 直接/快速 看到设计稿中 px 的数值就能直接算出其对应的 rem 单位的数值的,因此需要进行优化。

而 优化 的核心就是 将 复杂计算 变成 简单计算,例如在 宽 750 px 的设计稿中

  • 34px 转换成 rem = 34 ÷ 75,这种不直观的计算叫 复杂计算,若可以实现 34 ÷ 100 即可得到相应的 rem 的方式,就称为 简单计算任何数除以 10 或 100 都很容易口算

也就是说,如果我们希望所有设计稿上 px 的计算都是 简单计算,那么我们就需要保证其 渲染结果 是正确的即可,换句话说,就是我们需要调整设备视口的 1 rem = n px 中 n 的值让其能够满足 34 ÷ 100 = 0.34 rem 的情况下还能够被正常渲染为 17 px 即可,这无非就涉及到一个数学倍数计算而已,就不过多展开了。

vw/vh 适配

前面说过,vw 和 vh 是将 视口 宽/高 都分成 100 份,相对于 设备视口 375px 来说 1vw = 375 ÷ 100 = 3.75px

经过了 rem 适配方案 的介绍,vw/vh 这种适配方式就是相当于把替换了原本的 rem 单位,因此,这个方式的计算方式和 rem 的方式 如出一辙,区别就在于:

  • rem 的适配方式支持自定义将设备视口划分为 n 份,n 可以是任何正确值

  • vw/vh 就是将设备视口划分为 100 份,不支持自定义

因此,假设将 设计稿 750px 中的 34px 转换为 设备视口 n vw 就等于 n = 34 ÷ 7.5 = 4.533333333333333 vw ≈ 4.53 vw

CSS 预处理器 — 简化计算

如果使用的是 CSS 预处理器(Less、Sass),那么就可以通过定义一个全局的 函数 来帮助我们进行运算,例如:

  • Less 中 px2vw() 的定义:

    // plugin.jsmodule.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' }) },}
    // 具体使用> @plugin './plugin.js';
    @design-width: 750; @per-vw: @design-width / 100;
    .text { font-size: px2vw(34, @per-vw); color: #457fff; }
  • Sass 中 px2vw() 的定义:

    >  $design-width: 750;  $per-vw: $design-width / 100;
    @function px2vw($param) { @return $param / $per-vw + 'px'; }
    .text { font-size: px2vw(34); color: #457fff; }

使用 postcss-px-to-viewport 进行验证

  • 文本和原始样式

  • postcss-px-to-viewport 配置

  • 最终展示效果

 

等比缩放 — viewport  标记

所谓 等比缩放 也就是我们不需要关注 设计稿 px 到底对应多少 设备视口 rem 或 vw,在开发时,直接使用 设计稿提供的数据 px 即可,然后在将整体页面按照 设备视口 / 设计稿 的比例进行 整体缩放

而缩放就需要使用到 使用 “viewport”  标记 来控制视口的大小和形状了,例如常见的  标记如下:

很明显,我们只需要控制其中的 width 和 initial-scale 的值即可,它们分别是代表当前设备视口宽度和缩放比的值。

还是用 设计稿 750px 和 设备视口 375px 举例子,因为我们是直接只用设计稿提供的数据来开发,那么上面的 width = 设计稿的宽initial-scale = 设备视口 / 设计稿

(function (designWidth) {  const dEl = document.documentElement;  let meta = document.querySelector("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);

第三方组件库如何做适配?

不知道你是不是会有一些疑问,比如第三方组件库的适配方式和我们使用的不一致怎么办?

不用担心,第三方组件库默认都是直接使用 px 的方式来开发的,因此我们在项目中定义的适配方式就是第三方组件库的适配方式,不会产生冲突的。

例如,vant-ui 文档中很贴心的为你列出了 浏览器适配方案(详情可见文档):

  • 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 事件,使得组件能够在桌面端使用

 

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=18566,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?