正文
前端圈真乱,这话一点不假。但乱也乱的好处,乱则生变,有变化才有进步。今天还是老调重谈,聊聊移动端页面的适配。因为对于一枚前端而言,天天和页面打交道(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机型中不在列表中的,将看到的效果如上图所示。至于敢不敢用,这就得看亲了。必竟第一个吃螃蟹的人是需要一定的勇气!(^_^)
适配方案
前面给大家介绍了这个方案目前得到的支持情况以及效果。也扯了不少废话,接下来进入正题吧。
在移动端布局,我们需要面对两个最为重要的问题:
不同的终端,我们面对的屏幕分辨率、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
另外有一个细节需要特别的提出,比如我们有一个这样的设计: