使用vw做移动端页面的适配

  • Post author:
  • Post category:其他


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

dpr

值相应改变

<meta>

标签中

viewport

的值:

 

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

  • 根据

    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

,比如:

 

PostCSS编译之后就是我们所需要的带

vw

代码:

 

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

 

假设你的设计稿不是

750px

而是

1125px

,那么你就可以修改

vewportWidth

的值。有关于该插件的详细介绍,

可以阅读其官方使用文档

上面解决了

px



vw

的转换计算。那么在哪些地方可以使用

vw

来适配我们的页面。根据相关的测试:

  • 容器适配,可以使用

    vw
  • 文本的适配,可以使用

    vw
  • 大于

    1px

    的边框、圆角、阴影都可以使用

    vw
  • 内距和外距,可以使用

    vw

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

如果我们直接使用:

 

最终的效果会造成

[w-187-246]

容器的高度小于

[w-188-246]

容器的高度。这个时候我们就需要考虑到

容器的长宽比缩放

。这方面的方案很多,但我还是推荐工具化来处理,这里推荐@一丝 姐姐写的一个PostCSS插件

postcss-aspect-ratio-mini

。这个插件使用很简单,不需要做任何的配置,你只需要本地安装一下就OK。使用的时候如下:

 

编译出来:

 

这样就可以完美的实现长宽比的效果。有关于这方面的原理在这里不做过多阐述,感兴趣的话可以阅读早前整理的文章:

目前采用PostCSS插件只是一个过渡阶段,在将来我们可以直接在CSS中使用

aspect-ratio

属性来实现长宽比。

解决

1px

方案

前面提到过,对于

1px

是不建议将其转换成对应的

vw

单位的,但在Retina下,我们始终是需要面对如何解决

1px

的问题。在《

再谈Retina下

1px

的解决方案

》文章中提供了多种解决

1px

的方案。在这里的话,个人推荐另外一种解决

1px

的方案。依旧是使用PostCSS插件,解决

1px

可以使用

postcss-write-svg

使用postcss-write-svg你可以通过

border-image

或者

background-image

两种方式来处理。比如:

 

这样PostCSS会自动帮你把CSS编译出来:

 

使用PostCSS的插件是不是比我们修改图片要来得简单与方便。

上面演示的是使用

border-image

方式,除此之外还可以使用

background-image

来实现。比如:

 

编译出来就是:

 

这个方案简单易用,是我所需要的。目前测试下来,基本能达到我所需要的需求。但有一点千万别忘了,记得在

<head>

中添加:

 

上面阐述的是这个适配方案中所用到的技术点,简单的总结一下:

  • 使用

    vw

    来实现页面的适配,并且通过PostCSS的插件

    postcss-px-to-viewport



    px

    转换成

    vw

    。这样的好处是,我们在撸码的时候,不需要进行任何的计算,你只需要根据设计图写

    px

    单位
  • 为了更好的实现长宽比,特别是针对于

    img



    vedio



    iframe

    元素,通过PostCSS插件

    postcss-aspect-ratio-mini

    来实现,在实际使用中,只需要把对应的宽和高写进去即可
  • 为了解决

    1px

    的问题,使用PostCSS插件

    postcss-write-svg

    ,自动生成

    border-image

    或者

    background-image

    的图片

这里使用了多个PostCSS的插件,其实现在有很多优秀的PostCSS插件能帮助我们解决很多问题。哪果你从未接触过有关于PostCSS相关的知识,建议你可以花点时间去学习一下,在W3cplus提供了一些有

关于PostCSS相关的文章

。如果你想系统的学习PostCSS相关的知识,推荐你购买《

深入PostCSS Web设计

》一书:

降级处理

最开始提到过,到目前为止,T30的机型中还有几款机型是不支持

vw

的适配方案。那么如果业务需要,应该怎么处理呢?有两种方式可以进行降级处理:

Viewport不足之处

采用

vw

来做适配处理并不是只有好处没有任何缺点。有一些细节之处还是存在一定的缺陷的。比如当容器使用

vw

单位,

margin

采用

px

单位时,很容易造成整体宽度超过

100vw

,从而影响布局效果。对于类似这样的现象,我们可以采用相关的技术进行规避。比如将

margin

换成

padding

,并且配合

box-sizing

。只不过这不是最佳方案,随着将来浏览器或者应用自身的Webview对

calc()

函数的支持之后,碰到

vw



px

混合使用的时候,可以结合

calc()

函数一起使用,这样就可以完美的解决。

另外一点,

px

转换成

vw

单位,多少还会存在一定的像素差,毕竟很多时候无法完全整除。

到目前为止,我发现的两个不足之处。或许在后面的使用当中,还会碰到一些其他不为人之的坑。事实也是如此,不管任何方案,踩得坑越多,该方案也越来越强大。希望喜欢这个适配方案的同学和我一起踩坑,让其更为完善。



版权声明:本文为qq_38744335原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。