移动适配方案
视口介绍
1 : 布局视口(layout viewpor)
var width=document.documentElement.clientWidthconsole.log(width)
可以看作为当前顶级的HTML元素的宽度,也就是咱们浏览器当前的可视区域的宽度,咱们的媒体查询max-width和min-width的值也是布局视口的宽度,布局视口中的宽度和高度都是像素,也就是px,是一个抽象单位。
布局视口宽度受到meta标签内的width属性和initial-scale的影响,仅设置width的值时,这个值就是布局视口的宽度,它的值可以是正整数或者特殊值device-width。
布局视口宽 = 可视视口宽时 html 元素正好横向铺满窗口(但其后代元素若有横向 overflow 的情况,仍然会出现滚动条),布局视口宽 > 可视视口宽时,出现横向滚动条
2 : 可视视口(visual viewport)
var width=window.innerWidth
可视视口是当前可见区域的CSS像素数,和布局视口差不多,区别可视视口的宽度决定了将页面分成了多少份,每份对应一个CSS像素。
可视视口受到缩放比例的影响, 在meta标签内设置了 initial-scale=0.5 后会改变可视视口的尺寸,可视视口尺寸越小显示的CSS像素数也越少,则单位CSS像素数对应的可视区域越大,对应的缩放比例也就越大。缩放比例是相对于理想视口而言 缩放比例 = 理想视口尺寸/可是视口尺寸,而当没有设置initial-scale的时候,浏览器会取适当的缩放比例,一般情况下为1,使布局正好铺满屏幕,此时布局视口尺寸 = 可视视口尺寸。
3 : 理想视口(ideal viewport)
理想视口是一个比较适合移动布局的视口尺寸,作为计算布局视口和可视视口尺寸的基准值,上面mete标签中的 device-width 就是理想视口的宽度。
var width=screen.width
JS中这么写,也可以获取理想视口的宽度
备注 :
上面三个视口属性中,只有理想视口是不可以改变的,因为理想视口的宽度拒绝与设备的物理像素比存在着比例的关系,这个比例叫做设备像素比(device pixel ratio, dpr), 公式为 : 设备像素比 = 物理像素数/理想视口尺寸。
/* 举个栗子 iPhone 物理宽度像素 640 理想视口宽度 320 设备像素比 2*/var c=window.devicePixelRatio//这样可以获取设备像素比(Android系统下可能不符合预期)
由于没有禁用缩放属性,手动缩放不会影响布局视口或者理想视口,只会影响到可视视口的尺寸,而且可能导致布局视口小于理想视口。
设置 initial-scale 的值时,布局视口的尺寸与可视视口的计算方式相同,但不受手动缩放的影响同时设置 width 和 intial-scale 的值时,布局视口的宽取上述两个值中较大的一个
总结一下 :
1 : 将meta标签中的width设为device-width时,布局视口 = 可视视口 = 理想视口,这时设备像素比,设备像素比 = 物理像素 / 理想视口尺寸 = 物理像素比 / 布局视口尺寸,对iphone而言,一个CSS像素对应4个物理像素。
2 : initial-scale 设置任意合法的值同时禁用手动缩放时,布局视口 = 可视视口。
3 : initial-scale 设置为1时也可以使布局视口 = 可视视口 =理想视口。
分析一下网易和淘宝的适配方案
前言 : 网易新闻和淘宝尺寸适配采用了相同的思路,使用相对单位rem并将设备的可视视口宽度乘以一个系数得到html元素的font-size,元素布局时不超出可视视口宽度即可。
网易 :
我们并不需针对设置布局视口的宽度---只需要所有的元素占满可视视口即可,理论上如果设置了meta中的width值且大于可视视口的计算结果,会出现横向滚动条,但是网易和淘宝都没有设置width,所以布局视口的尺寸会大于可视视口的尺寸,只要没有超过可视视口的宽度,就不会出现滚动条。
1 网易新闻方案相对简单,采用理想视口作为可视视口,需要将缩放比例为
2 第二个要解决的问题是计算html元素的font-size,要将可视视口乘以一个系数。
理论上这个系数可以是任意值,如果为1,则html元素的fon-size即1rem等于可视视口的宽度,此时以rem单位的长度n, 可以理解为n倍数的可视视口,这个技术为0.01时,1rem = 可视视口款的1/100,也就是布局视口的1/100.
实际使用过程中这个系数尽可能方便将设计稿长度数值换算为Css中的长度数值.
假设,设计稿为750(iphone 6的物理像素),100是期望的换算比例,即设计稿中100px长度对应Css中1rem,将设计稿中的长度数值除以100得到的就是rem为到位的Css长度值,设计稿的宽换算为以rem为单位的Css长度应为(750/100)rem,同时设计稿对应可视视口的宽,即(750/100)rem=可视视口宽,1rem=可视视口(100/750),(100/750)就是我们要的系数。
3 第三个将可视视口的宽度换算为rem单位的数值,布局时元素不能超出这个值,有(750/100)font-size=可视视口 可知 可视视口宽度为(750/100)rem
网易新闻的结局方案中将这个值设置到了body元素的width上,但没有对overflow进行处理,所以实际上没有什么卵用。
4 在最新的网易新闻页面中字体也使用了rem。
PS : 网易的咱们暂时不用细说,主要介绍的是手淘的适配方案,因为手淘的方案更加且易用;
淘宝
原文链接 : https://github.com/amfe/article/issues/17
看一看咱们需要适配的屏幕吧 :
早期移动端开发,对于终端设备适配问题只属于Android系列,只不过很多设计师常常忽略Android适配问题,只出一套iOS平台设计稿。但随着iPhone6,iPhone6+ ,iPhone7+的出现,从此终端适配问题不再是Android系列了,也从这个时候让移动端适配全面进入到“杂屏”时代。
整个手淘设计师和前端开发的适配协作基本思路是 :
选择一种尺寸作为设计和开发基准
定义一套适配规则,自动适配剩下的两种尺寸(其实不仅这两种,你懂的)
特殊适配效果给出设计效果图片来自原文链接 :
在设计师与前端开发协作过程中 : 设计师经常选择iphone6作为基准设计尺寸,交付给前端的设计尺寸是按750px * 1344px为准(高度可能会随着内容改变)。前端开发人员通过一套适配规则自动适配到其他尺寸。
根据上面所说,设计师给我们的是一个750px * 1600px的页面
前端开发完成终端适配
这是咱们要说一下手淘的方案了 :
flexible方案,gitHup地址为 : https://github.com/amfe/lib-flexible, 原理性的东西不详说了,但是还需要说一点必要的。
flexble方案会把视觉稿分为100份,主要是为了以后可以更好的兼容vh 和 vw ,而每一份被称为一个单位a,同时1rem单位被认定为10a,这么算我们可以得出 :
1a = 750px/100
1a 为 : 7.5px
1rem =10a
1rem为: 75px
所以这份视觉稿分为了10a,整个宽度为10rem, 元素相对应的font-size=75px :
这么算的话,只需要将*原始的px值 / rem基准值。例如此视觉稿的尺寸为176px 176px,转换为 : 176/75 * 176/75
也就是 2.346667rem * 2.346667rem。
快速计算
CSSREM插件
是一个在CSS中将px值快速转换为rem的插件。
gitHup地址为 : https://github.com/flashlizi/cssrem
这个插件也有Vs Code 版本,不过不知道是我自己笨还是怎么回事,总是按照默认的16px来进行换算...如果有知道怎么用的话麻烦告知一下...
当然咱们也可以使用less/sass进行换算,代码之类的就不详说!
文字大小不是非常适合实用rem
前面主要介绍了怎么使用,估计也有人会说咱们的文字大小可不可以呢? 这里引用原文作者的一段话 :
前面大家都见证了如何使用rem
来完成H5适配。那么文本又将如何处理适配。是不是也通过rem
来做自动适配。
显然,我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px
和24px
,所以我们不希望出现13px和15px这样的奇葩尺寸。
如此一来,就决定了在制作H5的页面中,rem
并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px
作为单位。只不过使用[data-dpr]
属性来区分不同dpr
下的文本字号大小。
div { width: 1rem; height: 0.4rem; font-size: 12px; // 默认写上dpr为1的fontSize}[data-dpr="2"] div { font-size: 24px;}[data-dpr="3"] div { font-size: 36px;}
为了更好的利于开发,这里定制一个font-dpr()
的混合宏 :
@mixin font-dpr($font-size){ font-size: $font-size; [data-dpr="2"] & { font-size: $font-size * 2; } [data-dpr="3"] & { font-size: $font-size * 3; }}
有了这么一个混合宏之后,在开发中可以这样利用 :
@include font-dpr(16px);
这里也只是针对描述性的文本,假设需求方希望字体可以根据不同终端适配,完全可以实用rem来作为单位。
看一下在真机上面的效果吧。
http://huodong.m.taobao.com/act/yibo.html