一、Web的兼容问题
Web的特点就是跨平台支持。不过也正是所支持的平台设备数不胜数,使其在各设备的完美显示成为问题——因为各设备的屏幕尺寸不同,尤其是宽度不同,致使往往应用px单位的元素的显示千差万别(注意:px是相对单位,相对的是屏幕像素),其中最悲剧的估计就是超长的横滚动条了。幸运的是,Web开发技术更迭快速,为开发者提供了另一中选择:响应式Web设计(responsive-web-design)。这个名称最初由Web开发者Ethan Marcotte提出。2010年5月,Ethan Marcott发表了一篇名为responsive-web-design的文章,大致内容是现在屏幕参数越来越参差不齐,为每类屏幕适配变得不合时宜,所以应该采用流式布局使网页优雅地适应屏幕。
- 流式布局 即将盒模型宽度设置为百分比,比如在内外边距重设为0的情况下,body的宽为1349px,最外层container的宽为1080px,重新将comtainer的宽设置为80.059%,即1080/1349px,这样可使其比例在各个设备上相同,注意百分比宽度是以外层宽为基准,container的外层就为body,以此类推。此外为了防止过宽或过窄,一般在container上设置max-width,min-width。此外,还有弹性布局。
- 弹性布局 即以em为单位来设置元素宽高和字体大小,em和px一样是相对单位,只不过是相对的是元素的字体大小。哪何为“弹性”?,即修改顶层的字体大小即可对整个布局,字体大小产生影响。例如,浏览器默认body的字体为16px;将外层container宽设为67.5em即为1080px,里面段落元素字体设为1em,即为16px。这样,当将body字体设为18px时,container的宽将为18px*67.5=1215px,段落字体将为18px*1=18px,这样就做到了全局的“弹性”了,不过我觉得这对开发者的意义远大于用户,毕竟很少有用户会主动修改body字体。同样要注意的是,em是相对于元素的字体大小,如将container字体大小设为17px,则container宽会变为17px*67.5=1147.5px,段落字体应继承了外层container,变为17px*1=17px,而非之前的18px,以此类推。
二、移动浏览器上的问题
之前谈到的流式布局很大程度上确实解决了桌面端的问题,但对于移动设备,因其绝对尺寸实在太小,这样虽然布局还是原来的布局,也没有横滚动条,可是各个元素,字体却实在太小了。显然需要为移动端匹配不同的布局,比如原来的三列布局变为单列。这样,就需要使用CSS媒体查询了。
@media (min-width:800px) { /* 桌面端布局 */} @media (max-width:799px) { /* 移动端布局*/}
好吧,要是确实如此就好了,遗憾的是情况稍显复杂。
三、Viewport
在早期,移动端分辨率主流是480×320,iphone前三代和一些老型号Android手机都是如此。那作为智能手机,兼容桌面端Web是必不可少的,但因宽度太小,为了显示起来不是无穷无尽的横向滚动条,于是浏览器模拟出一个viewport(视口),其宽度以接近电脑的宽度(比如960px)渲染出页面,并将其缩小到合适的尺寸,再让用户放大想看的内容,简单的说,就是移动浏览器预先进行了缩放。之后虽然分辨率发展迅速,动辄720p、1080或更高,可是由于屏幕绝对尺寸还是小(4英寸,5英寸等),所以仍然采用之前的布局方法去渲染。总之,就是屏幕太小。这样做问题很明显:元素变小,尤其是字体。与此同时,苹果提供了人为设置viewport宽度的接口并被广泛采纳,这帮助解决了这个问题,也就是viewport元标签。在使用时就像下面一样:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
实际上,content中可以设置六个属性:width、height、initial-scale、minimum-scale、maximum-scale、user-scalable,分别是viewport的宽和高、初始缩放值、最小和最大缩放值、是否允许用户缩放。其中最关键的就是width属性了。在上面,我将width设为device-width。虽然device-width名为“设备宽度”,但它往往不是实际的设备宽度。大部分手机在300px~400px之间,比如iphone的320px。在iphone4中,设备物理像素为960×640,在用viewport将布局宽度设置device-width时,CSS设置中的每个像素横向上是由两个像素显示。这也就解释了为什么这样可以让字体等元素不变小,显示却更为细腻了,实际上,高分屏的设备都是这么处理的,包括众多的移动设备和一些Mac,以后的windows对高分屏也将是这样。这样,device-width的值已不是设备物理像素了,而称为设备独立像素。其中设备物理像素与设备独立像素的比称为devicePixelRatio,实际上,device-width就是物理宽度比上devicePixelRatio,就像在iphone4中,device-width=320=640/2。遗憾的是,它在一些设备中并不可靠,要么是错的,要么就是不可获取。特别地,devicePixelRatio在windows上普遍为1,也就是CSS设置中的像素与设备物理对等,而没有默认缩放。
四、Viewport总结与参数获取
- 想完美适配移动浏览器界面宽度,应匹配viewport宽度。
- 在默认情况下,viewport宽度会很宽,因此,我们使用viewport设置宽度。而且默认宽度与你设置的宽度都可以通过 document.documentElement.clientWidth获取。
- 布局宽度不仅可以是device-width,也可以自定义,不过很少使用。
- 你可以通过your viewport size获取你的设备的device-width或者默认宽度;也可以通过viewportsizes查询其他设备的device-width;同时还可以使用devicepixelratio获取设备的devicePixelRatio。
五、开始响应式布局
首先,通过viewport元标签设置viewport,你可以直接插入:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
接着,使用之前提到的CSS媒体查询,问题的关键是CSS媒体查询中所识别的宽是默认布局宽度,还是device-width?其实两者都可以,也就是clientWidth。例如,你的移动设备布局宽度为默认值,如960px,那么你可以这样写:
@media (min-width:961px) {/*桌面端*/} @media (max-width:960px) {/*移动端*/}
如果你使用viewport设置了布局宽度为device-width,如320px,那么你可以这样写:
@media (min-width:321px) {/*桌面端*/} @media (max-width:320px) {/*移动端*/}
不过,第一种显然不是我们想要的,第二种只能是某一设备,因而我们一般使用流式布局,在媒体查询时我们往往设置一个大致的断点,比如800px。
六、结束
其实,这篇文章介绍的只是响应式Web开发的思路,其中细节很多,已经超出了本文范围。在实际开发中,设置Viewport后,通过媒体查询,配合使用流式设计就能够做到网页在桌面和移动端上都布局优雅。不过,这只是响应式布局内容的一点,实际上,除了视觉优雅,还得交互优雅。