likes
comments
collection
share

你是如何实现移动端适配方案的?看看这里有没有你心水的

作者站长头像
站长
· 阅读数 10

以前的简历为了突显我在 H5 也有一定涉猎,总是会想办法写一点相关的上去,其中移动端适配是问的比较多的,但是每次的回答面试官都不太满意,因为我在这方面纯纯是半桶水,没有亲自有过实际环境处理,所以今天的文章就从 01 实现一个适配方案

为什么要适配?

通常页面的设计是由 UI 来完成,比如活动页、登录页,而对于 UI 来说会选择一个适合自己业务的设计稿大小,比如 iPhone X375x812可以参考下面这个墨刀提供的

你是如何实现移动端适配方案的?看看这里有没有你心水的

单位这个引‘设计稿’而异,通常是 px,如果是 Android 的会是 dp,开发按照设计稿并且模拟机型也是 UI 原本设计的,比如 iPhone X,肯定是没问题,但由于移动端机型较多,不同分辨率和大小的很多,那么基于 iPhone X 比例时写死宽度高度,会导致其它机型比例会出现问题,甚至是错位的情况,这就是需要适配的场景之一

适配的场景还可能有移动端的横屏模式,长辈模式...

总之适配是一件很麻烦的事,通常中后台的管理系统就不会要求这么多,而对于 H5 场景要求比较严格,因此对于适配来说,你甚至可以作为一个专业技能写在简历上,比如高保真还原设计稿,有些公司为了减轻前端的烦恼,有可能还会细化出另一个分工,比如 UI 开发工程师

那么适配的方案有哪些呢?

百分比适配

前面说比例没对是导致不能还原设计稿原因,那么我让 UI 按照百分比为单位画设计稿不就行了?如果不行那我自己换算一下不就行了

对于简单的稿子或者说布局,比如三段式、两列布局那肯定没问题,但细化的组件时这种做法对开发和 UI 都是一种折磨,谁会整体拿着计算器去搞设计/开发呢?而且对于需要固定大小或者最小宽度(min-width)的场景不适合,比如某个按百分比的悬浮按钮,在 iPhone XR 上还能按,但是你在 iPhone SE 可能就按不了,还有一些 IMG 的占位和计算问题,很多场景是需要写死的

你是如何实现移动端适配方案的?看看这里有没有你心水的

找到一篇深受百分比适配迫害老哥写的文章,可以看看

rem/flexible 适配

关于 rem 适配的源代码可以在线查看

这个方案又被叫阿里移动端适配方案,大概是因为相关库的作者是阿里的工程师,比如 px2rem-loader 的作者是 JinjiangWeex 的作者,前阿里云工程师,勾三股四

主要用到三个库

  1. amfe/lib-flexible
  2. songsiqi/px2rem
  3. Jinjiang/px2rem-loader

其中 px2rem 可以认为是 babel/corepx2rem-loaderbabel-loader,前者是理论实现,而后者是打包工具兼容实现

先介绍 lib-flexible,它的原理就是模拟出一个符合视口的等比例宽度,而这个模拟的宽度会根据 rem 的特性去传递给其它层级的元素,而且可以动态修改

而对于 px2rem 就是一个编译时的东西,它用来在开发时转换设计稿和 rem

就拿 iPhone XR 举例,开发和设计以 iPhone XR(414 896) 为基础,开发时按照 UI 给的稿子去设计,然后实际部署时通过 px2rem 相关库去编译

/* ... */
/** 源代码的 CSS 按照设计稿 **/
.search {
  display: block;
  height: 34px;
  width: 220px;
  border: 1px solid #bbbbbb;
  border-radius: 16px;
  font-size: 14px;
  line-height: 20px;
  padding-left: 30px;
}
/* ... */
// bin/build
const fs = require("fs");
const Px2rem = require("px2rem");
const px2remIns = new Px2rem({
  remUnit: 41.2,
});

fs.readFile("./src/style.css", function (err, data) {
  if (err) {
    return console.error(err);
  }
  const originCssText = data.toString();
  const newCssText = px2remIns.generateRem(originCssText);
  fs.writeFile("./dist/style.css", newCssText, (err) => {
    if (err) console.log(err);
  });
});

最关键的就是 remUnit 的转换,iPhone XR(414 896) 的宽度是 414px,然后 lib-flexible 会将屏幕 10 等分,因此按比例 remUnit = 414 / 10 = 41.4

执行完编译后,可以得到结果

npm run build

预期效果如下

你是如何实现移动端适配方案的?看看这里有没有你心水的

实际效果如下

可以看到无论是 414/320/820,它的比例都没有变化

同样是比例适配,相对于百分比适配,rem 的方案会更稳定些,rem 是由根元素的 font-size 统一决定,HTML 的子元素都会继承(inherit),而基于流式布局DOM,它的百分比是相对于父级元素变化的,而百分比适配对应的解决方案并没有给出唯一参照,而且字体大小无法随屏幕变化,从开发体验上来说不如 rem

vw 适配

lib-flexible 源码只有 44 行,但就像 Jquery,可能实现不是很复杂,但在那个时代具有开创性,也因为时代的关系,随着浏览器的发展逐渐有了其局限性

比如,video 标签的视频频播放器的样式在不同 dpr 的设备上展示差异很大

而对于 lib-flexible 的问题,其 github 给出了回答,就是使用 viewport

由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方。

viewport 单位就是 vw,原理和 rem 一致,也是一种比例单位,它的相对于设备的视口的宽度而定,被均分为 100

同样的 vw 也具有对应的工具 evrone/postcss-px-to-viewport,和 px2rem 一样,类似于编译器,不过这次就没有 lib-flexible 而是由浏览器支持

参考资料

  1. 详解百分比布局问题!- guanzhangl - CSDN
  2. 2022 年移动端适配方案指南 — 全网最新最全