移动端适配方案

移动端适配方案

前言

我认识的很多前端的初学者停留在PC端页面的阶段,但其实移动端开发也是非常重要的一个模块。而在移动端开发中最需要我们注意的,就是适配问题。这篇文章对完全没有接触过移动端开发的小伙伴也比较友好,我们从源头开始,让没有接触过移动端的小伙伴先有一个宏观上的认知,然后我们再细致的聊聊移动端适配的那些事儿(文章比较长,大家可以分阶段食用)。

何为移动端开发

大家最开始学习前端,一定是从PC端页面做起的,同样的道理,移动端无非就是把PC端的网页搬到手机上而已,通常我们把这样的项目叫做app(手动尴尬~~),但是app的开发也是有他的渊源的,大部分情况下我们开发的app只是其中的一种,app的种类共有三种:

  • 原生app
    基于特定的手机开发平台,使用各自的语言(Android、IOS…),开发出的适合本机系统平台的app。它能够充分使用系统底层的api并且和硬件有良好的交流,但是它不支持跨平台,受开发语言的限制,同时也只能在对应的机型上使用。这个比较好理解,其实就是手机上自带的那些app(日历、闹钟、应用商城…),在不同系统和品牌的手机上自然会不同,同样,我们使用这种app时也不会提示我们需要开放各种权限,因为本机的app本机用,都是自家人嘛。
  • web app
    基于手机中的浏览器,其实就是手机中的web页面,它开发更便捷,不需要下载就能使用,但是不能充分发挥手机的性能以及系统的api,性能较差,同时会受到浏览器内核版本和设备版本的双重限制。这个就更好理解了,打开手机上的浏览器,里面所有的网页都可以叫做web app。但是大家也能明显的感受到,这些app的性能要相对差一些,就是上面提到的原因。
  • 混合app
    仔细想想,我们生活中使用的最多app都是怎么来的。不是手机自带,也不是在浏览器中使用,而是下载后才使用的,这就是混合app,为什么叫混合app嘞?因为它结合了上面两者,将html5网页层、网页引擎层、容器层有机的结合在一起。它可以跨平台开发,并且能综合使用系统和web服务。本质上是在原生app的外壳中内嵌一个浏览器做web开发,它可以应用于多类设备,虽然它的性能介于以上两者之间,但是它能够广泛的应用,面向更多的市场,所以混合app才是我们工作中最经常接触的。

总结一下,移动端的开发,大部分情况下还是依赖于浏览器的,那么我们只不过是把网页放在了手机上而已。

为什么要做移动端的适配

了解了移动端开发的大概,我们发现它和PC端的没什么区别,都是在浏览器中搞事情,那为什么要针对移动端做适配的工作呢?移动端之所以能受此殊荣,一定是有原因滴。(先上一波图,大家感受一下)

  • 1983年,史上第一部上市销售的手机摩托罗拉8000X,它使用的是单色LCD屏,属于液晶屏技术,通过电压去控制液晶材料的排布与遮光性,使其拥有像素的属性去展示图像。
    在这里插入图片描述

  • 1994年,IBM Simon,同样是LCD屏,屏幕的大小为4.5英寸 × 1.4英寸,分辨率为160 × 293,但是第一次去除了物理按键,完全采用触摸屏操作
    在这里插入图片描述

  • 1997年,西门子S10,实现了LCD彩色屏,不过该屏幕只能显示红、绿、蓝、白四种颜色。
    在这里插入图片描述

  • 2001年,爱立信T68m,推出了256色的STN彩色屏幕,分辨率为101×80
    在这里插入图片描述

  • 2008年,诺基亚N85,采用AMOLED屏幕,2.6英寸,分辨率240×320
    在这里插入图片描述

  • 2010年,iPhone4,3.5英寸,分辨率为960×640,采用了视网膜显示屏(即retina屏),保证屏幕在正常视距下不会出现颗粒感,同时retina屏将设备像素比(dpr)提升至2,移动端适配需要多考虑dpr的因素
    在这里插入图片描述

  • 2011年,第一代三星Galaxy Note,5.3英寸的屏幕几乎是当时最大的屏幕,800×1280分辨率,当时对其界定与智能手机和平板电脑之间,但是对移动端设备屏幕大小做出了突破。
    在这里插入图片描述

  • 2014年,夏普Aquos Crystal,5英寸LCD显示屏,分辨率为1280 x 720,屏占比达到了78.5%,第一代全面屏手机。
    在这里插入图片描述

  • 2015年,三星Galaxy S6 Edge,5.1英寸,2560 x 1440的AMOLED显示屏,第一代曲面屏手机。
    在这里插入图片描述

  • 2017年,苹果iPhone X,屏幕尺寸5.8英寸,2436 × 1125 像素分辨率,458 ppi,屏幕的样式做出了突破性的刘海屏,自此之后,水滴屏、挖孔屏…等屏幕相继推出,在保证功能的情况下极大的提高的屏占比。
    在这里插入图片描述

  • 2019年,华为Mate X,第一次推出折叠屏,正面屏幕为6.6英寸,背面为6.38英寸,这就要求对此类设备做出额外的适配,要实时感知屏幕大小的变化。包括之后推出的卷轴屏…
    在这里插入图片描述
    现在大家能理解为什么要做移动端的适配了吗?从硬件的角度看,移动端设备在以极快的速度更新更无敌的体验,包括:音质、相机像素、屏幕分辨率、屏幕大小、存储能力、运行能力、续航能力…,而如此参差不齐设备屏幕和分辨率无疑对前端开发是非常不友好的,我们的页面会在五花八门的手机有完全不同的展示,甚至直接扭曲掉。ok,移动端适配就是来避免这种情况的。与大小形状差距不大的电脑显示器,大家能理解为什么要针对移动端做适配了吗?

移动端适配中的基础概念

至此,我们已经大概知道了移动端的发展背景,以及我们要解决的问题。那么在做具体工作之前,我们还要储备一些基础的知识,包括开发中用到的单位,有关移动端中一些属性的理解。

(一)设备上相关概念

  • 物理像素 pt(point):设备上最小的发光点。
  • 分辨率:设备屏幕上有多少物理像素。
  • 像素密度 dpi (dots per inch)/ ppi(Pixels Per Inch):表示每英寸上有多少物理像素,ppi越高,表示屏幕能以更高的密度排布物理像素,图像也越清晰。
  • 设备独立像素 dip (density-independent pixel):可以理解为”逻辑像素“,在高清屏上,物理像素颗粒多且小,那么相对于原始屏,同样大小的元素,在观感上会小很多,所以用高清屏中的n个像素点去表示原始屏中的一个像素点,对应原始屏的像素点个数就是dip。
  • 设备像素比 dpr (device pixel ratio):dpr = 物理像素/dip,dpr创造了移动适配中的一个大问题,有的小伙伴不理解原始屏和高清屏,直观上的理解原先一个物理像素的位置,在高清屏上由多个物理像素组成,所以高清屏上的物理像素更密集,展示出的图像也就更细腻。那么dpr具体造成了什么问题,后面会慢慢提到。

(二)开发中使用的单位

这些单位相信大家都不陌生,我也就不用说的太详细了,重点要理解的是rem和vw/vh,这个我会在后面着重讲。

  • css像素(px):一个css像素由n个物理像素组成,开发中的抽象单位。
  • em:相对于父元素字体大小的单位。
  • rem:相对于根元素字体大小的单位。
  • ex:相对于当前字体大小,代表一个小写字母“x”的高度。
  • ch:相对于当前字体大小,代表一个数字”0“的宽度。
  • vw/vh:相对于layout viewport(这是什么东西?请看下文~~)的百分比宽度/高度,取决于viewport中的配置。
  • vmin/vmax:识别vw和vh中较小/较大的一个,在横竖屏适配中可以保证元素的方向统一。vmax在IE和Safari中不支持。
  • %:相对于父元素的百分比大小
  • 一些绝对长度单位
    in 英寸 (1 英寸 = 2.54 厘米)
    cm 厘米
    mm 毫米
    pt 点Points (1点 = 大约1/72英寸)
    pc 皮卡Picas (1 皮卡 = 大约 12 点)

(三)viewport

  • 广义的理解,viewport就是设备屏幕上能展示网页的区域(可能是整个浏览器,可能是一个app的webView),但是viewport不局限在浏览器可视区域中。相反,一般的viewport会比浏览器可视区域更大,为了方便移动设备能正常展示PC端的网页,各个浏览器厂商设置了不同的viewport默认值。所以在开发中要注意app所用的浏览器内核以及其版本,确定viewport的默认值。
    在这里插入图片描述

  • 狭义上,viewport可以有三种理解。

    • layout viewport:表示浏览器默认的viewport大小,浏览器的首要任务并不是兼容移动设备,而是正常的展示所有网页,所以对于所有的网页,需要有一个统一的viewport规范来保证它们正常显示。但是layout viewport并不能很好的展示在移动端上。显然,这样会有横向的滚动条出现。layout viewport的宽度可以用document.documentElement.clientWidth获取。

    在这里插入图片描述

    • visual viewport:表示浏览器可视区域的大小,移动设备的屏幕普遍较小,如果照搬使用layout viewport,会导致其大量的内容挤在一起,布局会乱掉,所以要规定一个visual viewport来表示浏览器可视区域的大小,浏览器可视区即不会超出手机屏幕,也不会影响页面的布局。但是visual viewport会在页面缩放的时候改变,例如:当页面放大时,visual viewport将承载更少的css像素。visual viewport的宽度可以用window.innerWidth获取。

    在这里插入图片描述

    • ideal viewport:既然浏览器中有完全为了PC端开发的网页,那么也会有完全为了移动端开发的网页(其实绝大部分手机app页面和PC端都是两套设计),此时需要一个viewport来完美适配移动端设备的屏幕,保证页面正常显示,不需要用户缩放,也没有横向滚动条。ideal viewport是通过meta标签对layout viewport进行修改得到的。所以不同设备拥有不同的ideal viewport,即表示设备屏幕的大小。

      在这里插入图片描述

  • 说了这么多,可能还有有人不理解,为什么要给一个viewport三种定义?他们之间是什么关系?我师傅也问过我这个问题,其实viewport作为一个抽象的概念,它的含义有很多,但是我们开发中只会参照ideal viewport去做页面。理解的小伙伴们可能发现了,这三个viewport并不是并存的,而是开发者对其理解思考的过程,一步一步更加完美的实现适配,这样说大家应该可以理解了吧。

适配方案

移动端适配是一个漫长的发展过程,前人对此总结出多种适配方案,下面我们就其中最具有代表性的来分析。

百分比(%)方案

这是比较古老的一种方案,现在%作为css中的一个单位,除了保证100%宽度时使用一下,它的用武之地越来越小了。虽然%能够实时的适应屏幕的大小,但是依旧不受宠。原因也很简单,举个栗子,当我们出现比较多的标签嵌套时。
在这里插入图片描述
看似每个div的宽度都是30%,但是出来的效果却是这样的。%的特性就是这样,我们定义任何一个元素的宽高时都需要考虑到其父元素的宽高,想想都复杂,这种方案用起来太费劲。
在这里插入图片描述
当然,不仅仅是因为上面的原因,还有一个缺点就是”%“不能应用在字体上,这就导致字体不能跟着”%“的节奏去适配,要么字体大小永远不变,要么只能根据js判断屏幕宽度,然后动态改变字体大小,抛开性能问题不谈,这样的操作就相当复杂。

rem方案

稍微理解一下,百分比方案之所以不流行的原因,就是因为这个单位的参照物不一致,没有一个统一的标准,所以我们要定义一个统一的标准。显然,把标准宽度设置为屏幕宽度是最好不过,我们假设屏幕宽度为10a(a是我们假想的单位),那么在代码中任何第一个地方使用2a,都能实现整个屏幕20%的效果,并不需要考虑父元素。
不幸的是,css并没有a这个单位,于是rem诞生了,按照上面的理解,rem的统一参照标准是根字体(即html的font-size)大小,我们只需要根据屏幕的变化改变根字体的大小即可实现良好的适配。
当然,问题一定是存在的,有兴趣的小伙伴可以自己试试,随着屏幕的变化,用rem定义宽度的元素也会随着变化,这个变化的趋势是线性的,简言之就是”等比缩放“的。但是我们的浏览器中的字体大小的变化并不是线性,请看下图。
在这里插入图片描述
另外,一般情况下我们会把根字体的大小设置为屏幕大小的1/10,对于元素来说,1rem或者0.1rem都是可以接受的,但是字体就比较傲娇了,由于rem换算出的px精度很差,特别是针对屏幕尺寸比较奇怪的手机,字体的大小又只能适应整数px(浏览器会对此做出相当强硬的取整),那么我们页面中的字体布局样式很可能事与愿违。

vw/vh方案

很遗憾,rem方案并不能对字体的大小做出良好的适配。如果你能理解上面的两个方案,这里都不需要分析,vw/vh一定会存在上面的问题,那么我们为什么还要推出这种方案呢?想想上面两种方案的特性,vw/vh是不是把它们两个整合起来了呢?它拥有统一的参考标准(layout viewport),并且这个标准就是屏幕本身,而不是需要我们自己配置的根字体。所以,我的理解是,vw/vh综合了以上两种方案的特性。它的出现让适配更加的纯粹,它不需要太多js的干预,减小的与js之间的耦合性。

lib-flexible

这是一套比较成熟的适配方案,详细的介绍请转至这里
如果想要真正了解flexible的发展,请看这里

lib-flexible + postcss-pxtorem

如果你看过了lib-flexible,会发现它的缺点也很明显,一般我们设计稿中提供的单位全部是px,但是在lib-flexible中大部分要使用rem,中间的换算问题需要人为解决,比较复杂。所以我们要搭配postcss-pxtorem来帮助我们完成换算,开发时直接使用px作为单位。postcss-pxtorem安装后做一些webpack配置即可。

	module.exports = {
		  plugins: {
			 'postcss-pxtorem': {
				  //设置根字体的大小
				  rootValue: 75,
				  //表示哪些属性可以接受px变为rem
				  propList: ['*'],
			 }
		   }
		 }

需要注意的是,在使用Echarts,canvas之类组件的时候,用js代码定义宽高,单位会省略,默认是px。此类的px并不会被postcss转化为rem,而是单纯的指css像素,所以Echarts内字体大小用数字定义时,字体的大小不会是实时变化的。

需要理解

移动端适配并不是“响应式”

学习过PC端响应式页面的小伙伴,一定用过bootstrap这类UI库,其中的UI组件可以自动实现响应式。大家可以去对比一下,在响应式中,不仅仅是元素的等比变化,在超过一定临界点的时候,会有全新的页面布局设计,以保证良好的展示和交互。而我们所做的移动端适配,并不会像“响应式”那样频繁的变化页面大小,毕竟屏幕大小能实时变化的手机还是少数。我们的适配操作只需要在项目启动的时候执行一次即可。

没有100%的适配

讲了这么有关适配的方案也好,思想也好,都是为了让我们的项目更接近完美的展示在不同设备上,而要做到真正的100%,我不能说完全不可能,只能说任重而道远。

未解决的问题

移动端适配的学习是一个漫长的过程,不是看几天的文章就能搞懂的,它需要长期的跟踪学习、理解、练习,才能做出更好的适配效果。本文中仍然留下了很多坑,比如:字体的大小到底怎么适配,1px问题,高清图问题… 我也会持续学习更新。看完这篇文章,希望大家能有所收获,也希望大家提出宝贵意见,蟹蟹!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值