再聊移动端页面的适配

时间: 2018-03-06阅读: 1340标签: 移动端

前端圈真乱,这话一点不假。但乱也乱的好处,乱则生变,有变化才有进步。今天还是老调重谈,聊聊移动端页面的适配。因为对于一枚前端而言,天天和页面打交道(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浏览器
华为Mate9Android7.01080 x 19205英寸YesYesNoYesYesYes
华为Mate7Android4.21080 x 19205.2英寸YesYesNoYesYesYes
魅族Mx4 (M460 移动4G)Android4.4.21152 x 19205.36英寸YesNoNoYesYesYes
OppoR7007Android4.31280 x 7205英寸YesNoNoYesYesNo
三星N9008 (Galaxy Note3)Android4.4.21080 x 19205.7英寸YesNoYesYesYesYes
华硕ZenFone5(x86)Android4.3720 x 2805英寸NoNoNoYesNoNo

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

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


如果我们直接使用:

[w-188-246] {
    width: 188px;
}
[w-187-246]{
    width: 187px
}

最终的效果会造成[w-187-246]容器的高度小于[w-188-246]容器的高度。这个时候我们就需要考虑到容器的长宽比缩放。这方面的方案很多,但我还是推荐工具化来处理,这里推荐@一丝 姐姐写的一个Postcss插件postcss-aspect-ratio-mini。这个插件使用很简单,不需要做任何的配置,你只需要本地安装一下就OK。使用的时候如下:

[aspectratio] {
    position: relative;
}
[aspectratio]::before {
    content: '';
    display: block;
    width: 1px;
    margin-left: -1px;
    height: 0;
}

[aspectratio-content] {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
}
[aspectratio][aspect-ratio="188/246"]{
    aspect-ratio: '188:246';
}

编译出来:

[aspectratio][aspect-ratio="188/246"]:before {
    padding-top: 130.85106382978725%;
}

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

目前采用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两种方式来处理。比如:

@svg 1px-border {
    height: 2px;
    @rect {
        fill: var(--color, black);
        width: 100%;
        height: 50%;
    }
}
.example {
    border: 1px solid transparent;
    border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch;
}

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

.example {
    border: 1px solid transparent;
    border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E") 2 2 stretch;
}

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

上面演示的是使用border-image方式,除此之外还可以使用background-image来实现。比如:

@svg square {
    @rect {
        fill: var(--color, black);
        width: 100%;
        height: 100%;
    }
}

#example {
    background: white svg(square param(--color #00b1ff));
}

编译出来就是:

#example {
    background: white url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2300b1ff' width='100%25' height='100%25'/%3E%3C/svg%3E");
}

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

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />

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

  • 使用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单位,多少还会存在一定的像素差,毕竟很多时候无法完全整除。

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


如何判断自己的应用是否支持

虽然该文的示例,进行了多方面的测试。但很多同学还是会担忧自己的APP应用是否支持该方案,而不敢大胆尝试或者使用。其实不必要这么担心,你可以拿自己的设备,或者应用扫描下面的二维码:


当页面跑完测试之后,找到对应的Values and Units列表项:


如果vw栏是绿色代表你的设备或应用支持该方案;反之则不支持。另外你也可以经常关注css3test相关的更新,后面将会根据相关的规范更新测试代码,让你能快速掌握哪些属性可以大胆使用。


总结

H5页面的适配方案总是令人蛋疼的,事实上页面的布局总是令人蛋疼的。但技术是不断革新的,我们可以随着保持对新技术的关注,尝试这些新特性运用到实际项目中,只有这样,我们解决问题的方案才会越来越完善。

到写这篇文章为止,虽然还有那么一两款机型不支持vw,但并不影响我们去使用。只有不断去尝试,才会有进步。在此,希望大家大胆尝试,一起让该方案变得更完美。如果你有更好的建议,或者你踩到任何坑,欢迎在下面的评论中与我分享,或者发邮件给我一起讨论。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对html5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:www.w3cplus.com/css/vw-for-…


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/468

手淘H5移动端适配方案flexible源码分析

随着技术的飞速发展,当前lib-flexible适配方案也在逐渐被更新的适配方案所替代,但是截止目前为止,还没有发现哪种方案能完全满足适配各种机型的需要,也会有一些小的问题。lib-flexible是目前用到的比较成熟的适配方案

rem.js的用法及在浏览器端的适配

更新换代快的大前提下自然又涌现出了适配问题,主流解决方案有很多,如响应式布局、cover布局、container布局 这几种布局在大多数情况下不限制高度的页面下还是相当有用的

移动端尺寸基础知识

初涉移动端设计和开发的同学们,基本都会在尺寸问题上纠结好一阵子才能摸到头绪。我也花了很长时间才弄明白,感觉有必要写一篇足够通俗易懂的教程来帮助大家。从原理说起,理清关于尺寸的所有细节

解决移动端点击穿透问题_h5实现移动端点击事件穿透的多种解决方案

移动端点透现象的解决办法:解决方案一:来得很直接github上有个fastclick可以完美解决;解决方案二:用touchend代替tap事件并阻止掉时A元素touchend的默认行为preventDefault(),从而阻止click事件的产生;解决方案三:延迟一定的时间(300ms+)来处理事件...

移动端适配的两种方案及flexible和px2rem-loader在webpack下的配置

方案一:使用lib-flexible包:使用flexible包方式,安装 lib-flexible 包和 px2rem-loader包;方案二:使用less或者sass等CSS 预处理语言写适配方案:基准按照设计图尺寸,但是缺点是不通用,不同页面可能设计图基准尺寸不同

移动端H5页面阻止图片和文字被选中

阻止span标签等文字被选中;阻止浏览器点击图片查看的行为(常见于uc浏览器)1.背景图的方式插入(这种是比较普遍的方式),2.使用js事件阻止默认行为的方法

vue中的适配:px2rem

这应该是vue项目在适配移动端时候,最简单的方法之一。下载并引入lib-flexible,引入px2rem-loader,将px2rem-loader添加到cssLoaders,完了就可以直接用px做单位按照750的设计稿撸代码了。

移动端开发注意问题

这篇文章主要总结移动端页面开发时需要注意的一些问题。比如:防止手机中网页放大和缩小、format-detection设置、上下拉动滚动条时卡顿慢 、禁止复制选中文本...

js判断pc端和手机端

js判断是否为移动端代码,获取用户userAgent代理头的值,进行匹配判断,如果匹配到就进行跳转到移动端。查看当前代理头信息在浏览器中按F12进入调试模式,查看请求

移动端如何强制页面横屏

有些机型有些app不能横屏:比如Android的微信就没有横屏模式,而ios的微信能开启横屏模式。解决办法就是在竖屏模式下,写一个横屏的div,然后设置rotate正(负)90度,把他旋转过来;而且如果用户切到横屏时,需要把rotate复原,要求也能正常展现。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广