1.移动端迷之视口
为什么我称他为“迷之视口”,因为其实我听过很多人的分享,来讲解移动端视口的问题,但我好像都没太懂。尴尬~_~, 其实我也不确定我能否将我的理解表述清楚,再次尴尬~_~。
说到视口的事情,要提一个大神:
Peter-Paul Koch(另一个更广为人知的名字是PPK)是HTML、CSS和JavaScript方面的专家,尤其擅长解决浏览器兼容性问题。在2009年,他就从传统的桌面浏览器和网站转而研究移动Web领域,并且从未间断。
ppk大神对于移动设备上的viewport有着非常多的研究(第一篇,第二篇,第三篇),有兴趣的同学可以去看一下,本文中有很多数据和观点也是出自那里。你也可以在StackOverflow上找到一些对此描述的相互补充,例如:[1],[2],有兴趣的童鞋也可以看看。
ppk认为,移动设备上有三个viewport。
1:layout viewport (布局视口)
2:visual viewport (视觉视口)
3:ideal viewport (完美视口)
layout viewport(布局视口)
首先,移动设备上的浏览器认为自己必须能让所有的网站都正常显示,即使是那些不是为移动设备设计的网站。但如果以浏览器的可视区域作为viewport的话,因为移动设备的屏幕都不是很宽,所以那些为桌面浏览器设计的网站放到移动设备上显示时,必然会因为移动设备的viewport太窄,而挤作一团,甚至布局什么的都会乱掉。也许有人会问,现在不是有很多手机分辨率都非常大吗,比如768x1024,或者1080x1920这样,那这样的手机用来显示为桌面浏览器设计的网站是没问题的吧?前面我们已经说了,css中的1px并不是代表屏幕上的1px,你分辨率越大,css中1px代表的物理像素就会越多,devicePixelRatio的值也越大,这很好理解,因为你分辨率增大了,但屏幕尺寸并没有变大多少,必须让css中的1px代表更多的物理像素,才能让1px的东西在屏幕上的大小与那些低分辨率的设备差不多,不然就会因为太小而看不清。所以在1080x1920这样的设备上,在默认情况下,也许你只要把一个div的宽度设为300多px(视devicePixelRatio的值而定),就是满屏的宽度了。回到正题上来,如果把移动设备上浏览器的可视区域设为viewport的话,某些网站就会因为viewport太窄而显示错乱,所以这些浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。ppk把这个浏览器默认的viewport叫做layout viewport。这个layout viewport的宽度可以通过document.documentElement.clientWidth来获取。
Apple对于这个问题的处理地是在iOS Safari中定义了一个viewport meta标签,用来创建一个虚拟的布局视口(layout viewport),而这个视口的分辨率接近于PC显示器,Apple将其定义为980px(其他厂商各有不同)。
这就很好的解决了早期的页面在手机上显示的问题,由于两者之间的宽度趋近,CSS只需要像在PC上那样渲染页面就行,原有的页面结构不会被破坏。
描述大致如下,数值不一定持续准确,厂商可能更改,但这个绝对值其实并非特别重要:
iOS, Android基本都是: 980px
BlackBerry: 1024px
visual viewport(视觉视口)
然而,layout viewport 的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个viewport来代表 浏览器可视区域的大小,来承载layout viewport ,ppk把这个viewport叫做visual viewport。这个视口可以简单的认为是手持设备物理屏幕的可视区域,这是一个比较直观的概念,因为你能看得见你的手机屏幕。visual viewport的宽度可以通过window.innerWidth来获取,但在Android 2, Oprea mini 和 UC 8中无法正确获取。
对于visual viewport,开发者一般只需要知道它的存在和概念就行,因为无法对它进行任何设置或者修改。很明显,visual viewport的尺寸不会是一个固定的值,甚至每款设备都可能不同。大致列几种常见设备的visual viewport尺寸:
iPhone4~iPhone5S: 320*480px
iPhone6~iPhone6S: 375*627px
iPhone6 Plus~iPhone6S Plus: 414*736px
ideal viewport (完美视口)
为了更好的适配移动端或者只为移动端设计的应用,单有布局视口和视觉视口还是不够的。
我们还需要一个视口,它类似于布局视口,但宽度和视觉视口相同,这就是完美视口(ideal viewport)。所谓的完美适配指的是,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;其次,显示的文字的大小是合适,比如一段14px大小的文字,不会因为在一个高密度像素的屏幕里显示得太小而无法看清,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。当然,不只是文字,其他元素像图片什么的也是这个道理。ppk把这个viewport叫做ideal viewport,也就是第三个viewport——移动设备的理想viewport。
我们在开发移动设备的网站时,最常见的的一个动作就是把下面这个东西复制到我们的head标签中:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
该meta标签的作用是让当前viewport的宽度等于设备的宽度,同时不允许用户手动缩放。也许允不允许用户缩放不同的网站有不同的要求,但让viewport的宽度等于设备的宽度,这个应该是大家都想要的效果,如果你不这样的设定的话,那就会使用那个比屏幕宽的默认viewport,也就是说会出现横向滚动条。
一般viewport 有6种属性设置,这些属性可以同时使用,也可以单独使用或混合使用,多个属性同时使用时用逗号隔开就行了。此外,在安卓中还支持 target-densitydpi 这个私有属性,它表示目标设备的密度等级,作用是决定css中的1px代表多少物理像素。
target-densitydpi值可以为一个数值或 high-dpi 、 medium-dpi、 low-dpi、 device-dpi 这几个字符串中的一个
特别说明的是,当 target-densitydpi=device-dpi 时, css中的1px会等于物理像素中的1px。因为这个属性只有安卓支持,并且安卓已经决定要废弃 target-densitydpi 这个属性了,所以这个属性我们要避免进行使用 。
width被用来定义layout viewport的宽度,如果不指定该属性(或者移除viewport meta标签),则layout viewport宽度为厂商默认值。如:iPhone为980px;
视口小结:
第一、如果不设置meta viewport标签,那么移动设备上浏览器默认的宽度值为800px,980px,1024px等这些,总之是大于屏幕宽度的。这里的宽度所用的单位px都是指css中的px,它跟代表实际屏幕物理像素的px不是一回事。
第二、每个移动设备浏览器中都有一个理想的宽度,这个理想的宽度是指css中的宽度,跟设备的物理宽度没有关系,在css中,这个宽度就相当于100%的所代表的那个宽度。我们可以用meta标签把viewport的宽度设为那个理想的宽度,如果不知道这个设备的理想宽度是多少,那么用device-width这个特殊值就行了,同时initial-scale=1也有把viewport的宽度设为理想宽度的作用。所以,我们可以使用。来得到一个理想的viewport(也就是前面说的ideal viewport)。为什么需要有理想的viewport呢?比如一个分辨率为320x480的手机理想viewport的宽度是320px,而另一个屏幕尺寸相同但分辨率为640x960的手机的理想viewport宽度也是为320px,那为什么分辨率大的这个手机的理想宽度要跟分辨率小的那个手机的理想宽度一样呢?这是因为,只有这样才能保证同样的网站在不同分辨率的设备上看起来都是一样或差不多的。实际上,现在市面上虽然有那么多不同种类不同品牌不同分辨率的手机,但它们的理想viewport宽度归纳起来无非也就 320、360、384、400等几种,都是非常接近的,理想宽度的相近也就意味着我们针对某个设备的理想viewport而做出的网站,在其他设备上的表现也不会相差非常多甚至是表现一样的。
2.移动端应该如何动态设置字体大小?
1.px单位在PC上很流行,在手机屏幕上一看,MD的,同样的12px却小的跟蚂蚁似的。
2.好不容易在iPhone上调的正常了,换个菊花牌手机,MD不堪入目了。
3.知道了rem的用法,但是html的font-size到底是多少才合适啊啊啊,MD~。
好了,那么现在来解决这些问题。
在解决之前,要了解一些你可能不想了解的东东
1.物理像素(physical pixel)
我们看到的每个屏幕都是由一颗颗我们肉眼难以看到的小颗粒(物理像素)组成的。
2.逻辑像素(css)
是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素)。
3.设备的像素比(device pixel ratio)简称DPR
它的数值体现了物理像素和逻辑像素之间的关系,用公式可以计算出该设备的DPR的大小:
DPR= 物理像素 / 逻辑像素 [eg: 2=640/320;]
4.PPI (Pixels Per Inch所表示的是每英寸所拥有的像素(Pixel)数目)
ppi可以理解为屏幕像素密度;
那么了解了上面这些概念,就可以知道,为什么css在pc上写着font-size=12px;但是换到手机上却变小了?因为DPR啊啊啊,大婶~。
没错,我们在电脑屏幕上的DPR是1,但是手机却不同,可能是它可能是2,也可能是3。获取设备DPR的方法还是有的:
1.在JavaScript中,通过window.devicePixelRatio来获取
2.在css中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和-webkit-max-device-pixel-ratio进行媒体查询,对不同DPR的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。
下面把几个常用的列举出来:
一,用媒体查询来设置html的font-size:
@media screen and (min-width:320px) {html{font-size:14px;}}
…… ……
二,用LESS或者SASS函数进行转换
SASS:
sass function px to remLESS:
less function px to rem三,淘宝貌似是用JS来做这方面的转换,这个我先暂时不作说明;
四,高手在民间,我相信一定也会有其它的方法;
总之这些知识也可以说是常识,既不高深也不新奇,它仅仅是一点观念转变。当我们掌握了viewport,那么意味着你已经大致了解了移动平台与PC平台的不同,可以帮助我们更专注而细致的去解决某些平台差异问题。
最后给大家分享一个有趣的现象,
网友评论