专栏名称: qize
前端交互开发工程师
目录
相关文章推荐
51好读  ›  专栏  ›  qize

再聊移动端页面的适配

qize  · 掘金  · 前端  · 2018-01-22 08:30

正文

前端圈真乱,这话一点不假。但乱也乱的好处,乱则生变,有变化才有进步。今天还是老调重谈,聊聊移动端页面的适配。因为对于一枚前端而言,天天和页面打交道(H5页面),那么布局的活总是少不了,这也将面临不同终端的适配问题。不知道你是否和我一样,页面布局总是或多或少会有一些蛋疼的事情发生。如果是的话,建议你花点时间阅读完下面我扯蛋的东东。

Flexible承载的使命

Flexible到今天也有几年的历史了,解救了很多同学针对于H5页面布局的适配问题。而这套方案也相对而言是一个较为成熟的方案。简单的回忆一下,当初为了能让页面更好的适配各种不同的终端,通过Hack手段来根据设备的 dpr 值相应改变 <meta> 标签中 viewport 的值:

<!-- dpr = 1-->
<meta name="viewport" content="initial-scale=scale,maximum-scale=scale,minimum-scale=scale,user-scalable=no"> 
<!-- dpr = 2-->
<meta name="viewport" content="initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">
<!-- dpr = 3-->
<meta name="viewport" content="initial-scale=0.3333333333,maximum-scale=0.3333333333,minimum-scale=0.3333333333,user-scalable=no">

从而让页面达么缩放的效果,也变相的实现页面的适配功能。而其主要的思想有三点:

  • 根据 dpr 的值来修改 viewport 实现 1px 的线
  • 根据 dpr 的值来修改 html font-size ,从而使用 rem 实现等比缩放
  • 使用Hack手段用 rem 模拟 vw 特性

有关于Flexible方案实现适配,在2015年双十一之后做过这方面的技术文档分享,感兴趣的同学可以移步阅读《 使用Flexible实现手淘H5页面的终端适配 》一文。虽然Flexible解决了适配终端很多问题,但它并不是万能的,也不是最优秀的,他还是存在一些问题的,比如 iframe 的引用,有时候就把我们自己给埋进去了。针对其中的一些不足之处,有些同学对其进行过相关的改造,在网上搜索能找到相关的方案。

那么时代在变化,前端技术在不断的变化,试问: Flexible还是最佳方案?Flexible还有存在的必要吗? 最近一直在探讨这方面,这里先告诉大家 Flexible已经完成了他自身的历史使命,我们可以放下Flexible,拥抱新的变化 。接下来的内容,我将分享一下我最近自己探讨的新的适配方案,或许很多团队同学已经开始使用了,如果有不对之处,希望能得到大婶们的指正;如果您有更好的方案,希望能一起分享一起探讨。

先上菜,再唠嗑

先上个二维码:

你可以使用手淘App、优酷APP、各终端自带的浏览器、UC浏览器、QQ浏览器、Safari浏览器和Chrome浏览器扫描上面的二维码,您看到相应的效果:

iPhone系列效果

部分Android效果

注: 如果扫上面的二维码没有任何效果,你 可以点击这里 ,打开在线页面,重新生成你的设备能识别的二维码号 。

上面的Demo,测试了Top30的机型。目前未得到支持的:

品牌 型号 系统版本 分辨率 屏幕尺寸 手淘APP 优酷APP 原生浏览器 QQ浏览器 UC浏览器 Chrome浏览器
华为 Mate9 Android7.0 1080 x 1920 5英寸 Yes Yes No Yes Yes Yes
华为 Mate7 Android4.2 1080 x 1920 5.2英寸 Yes Yes No Yes Yes Yes
魅族 Mx4 (M460 移动4G) Android4.4.2 1152 x 1920 5.36英寸 Yes No No Yes Yes Yes
Oppo R7007 Android4.3 1280 x 720 5英寸 Yes No No Yes Yes No
三星 N9008 (Galaxy Note3) Android4.4.2 1080 x 1920 5.7英寸 Yes No Yes Yes Yes Yes
华硕 ZenFone5(x86) Android4.3 720 x 280 5英寸 No No No Yes No No

Top30机型中不在列表中的,将看到的效果如上图所示。至于敢不敢用,这就得看亲了。必竟第一个吃螃蟹的人是需要一定的勇气!(^_^)

适配方案

前面给大家介绍了这个方案目前得到的支持情况以及效果。也扯了不少废话,接下来进入正题吧。

在移动端布局,我们需要面对两个最为重要的问题:

  • 各终端下的适配问题
  • Retina屏的细节处理

不同的终端,我们面对的屏幕分辨率、DPR、 1px 2x 图等一系列的问题。那么这个布局方案也是针对性的解决这些问题,只不过解决这些问题不再是使用Hack手段来处理,而是直接使用原生的CSS技术来处理的。

适配终端

首要解决的是适配终端。回想一下,以前的Flexible方案是通过JavaScript来模拟 vw 的特性,那么到今天为止, vw 已经得到了众多浏览器的支持,也就是说,可以直接考虑将 vw 单位运用于我们的适配布局中。

众所周知, vw 是基于Viewport视窗的长度单位,这里的视窗(Viewport)指的就是浏览器可视化的区域,而这个可视区域是 window.innerWidth/window.innerHeight 的大小。用下图简单的来示意一下:

因为Viewport涉及到的知识点很多,要介绍清楚这方面的知识,都需要几篇文章来进行阐述。@PPK大神有 两篇 文章 详细介绍了这方面的知识。中文可以移步 这里 进行阅读。

CSS Values and Units Module Level 3 中和Viewport相关的单位有四个,分别为 vw vh vmin vmax

  • vw :是Viewport's width的简写, 1vw 等于 window.innerWidth 1%
  • vh :和 vw 类似,是Viewport's height的简写, 1vh 等于 window.innerHeihgt 1%
  • vmin vmin 的值是当前 vw vh 中较小的值
  • vmax vmax 的值是当前 vw vh 中较大的值

vmin vmax 是根据Viewport中长度偏大的那个维度值计算出来的,如果 window.innerHeight > window.innerWidth vmin 取百分之一的 window.innerWidth vmax 取百分之一的 window.innerHeight 计算。

还是用一张图来示意吧,一图胜于千言万语:

所以在这个方案中大胆的使用 vw 来替代以前Flexible中的 rem 缩放方案。先来回归到我们的实际业务中来。目前出视觉设计稿,我们都是使用 750px 宽度的,从上面的原理来看,那么 100vw = 750px ,即 1vw = 7.5px 。那么我们可以根据设计图上的 px 值直接转换成对应的 vw 值。看到这里,很多同学开始感到崩溃,又要计算,能不能简便一点,能不能再简单一点,其实是可以的,我们可以使用PostCSS的插件 postcss-px-to-viewport ,让我们可以直接在代码中写 px ,比如:

[w-369]{
    width: 369px;
}

[w-369] h2 span {
    background: #FF5000;
    color: #fff;
    display: inline-block;
    border-radius: 4px;
    font-size: 20px;
    text-shadow: 0 2px 2px #FF5000;
    padding: 2px 5px;
    margin-right: 5px;
}

PostCSS编译之后就是我们所需要的带 vw 代码:

[w-369] {
    width: 49.2vw;
}
[w-369] h2 span {
    background: #ff5000;
    color: #fff;
    display: inline-block;
    border-radius: .53333vw;
    text-shadow: 0 0.26667vw 0.26667vw #ff5000;
    padding: .26667vw .66667vw;
}
[w-369] h2 span,
[w-369] i {
    font-size: 2.66667vw;
    margin-right: .66667vw;
}

在实际使用的时候,你可以对该插件进行相关的参数配置:

"postcss-px-to-viewport": {
    viewportWidth: 750,
    viewportHeight: 1334,
    unitPrecision: 5,
    viewportUnit: 'vw',
    selectorBlackList: [],
    minPixelValue: 1,
    mediaQuery: false
}

假设你的设计稿不是 750px 而是 1125px ,那么你就可以修改 vewportWidth 的值。有关于该插件的详细介绍, 可以阅读其官方使用文档

上面解决了 px vw 的转换计算。那么在哪些地方可以使用 vw 来适配我们的页面。根据相关的测试:

  • 容器适配,可以使用 vw
  • 文本的适配,可以使用 vw
  • 大于 1px 的边框、圆角、阴影都可以使用 vw
  • 内距和外距,可以使用 vw

另外有一个细节需要特别的提出,比如我们有一个这样的设计:







请到「今天看啥」查看全文