移动布局方案(转载)

layout viewport和visual viewport
移动端浏览器和PC最大的不同在于大小(废话= =),那么怎样让网页友好的展示在移动端呢。很显然的,如果不做任何处理,很多页面的展示必然会乱掉。Apple也发现了这个问题,并定义了一个viewport meta标签,用来创建一个虚拟的**layout viewport**(布局视图),这个视图的分辨率接近pc,Apple将其定义为**980px**,其他厂商可能不同,感兴趣的可以自己写页面测试下。这就很好的解决了早期的页面在手机上显示的问题,由于两者之间的宽度趋近,只需要像在PC上那样渲染页面就行,原有的页面布局不会错乱。

layout viewport

除了**layout viewport**,还有个**visual viewport**的概念,顾名思义,**layout viewport**是虚拟的窗口,**visual viewport**其实就是设备物理屏幕的可视区域,也就是屏幕大小。

visual viewport

这两个视图的关系,George Cummins这样解释

Imagine the layout viewport as being a large image which does not change size or shape. Now image you have a smaller frame through which you look at the large image. The small frame is surrounded by opaque material which obscures your view of all but a portion of the large image. The portion of the large image that you can see through the frame is the visual viewport. You can back away from the large image while holding your frame (zoom out) to see the entire image at once, or you can move closer (zoom in) to see only a portion. You can also change the orientation of the frame, but the size and shape of the large image (layout viewport) never changes.
想象**layout viewport**是一张大图片,然后有个周围不透明的固定位置的小框框(**visual viewport**),可以选择后退(zoom out)来透过小框看整张大图,也可以向前走(zoom in),看大图的局部。

viewport meta
viewport meta主要有6个属性设置

Name    Value   Description
width   正整数或device-width    定义视口的宽度,单位为像素
height  正整数或device-height   定义视口的高度,单位为像素
initial-scale   [0.0-10.0]  定义初始缩放值
minimum-scale   [0.0-10.0]  定义缩小最小比例,它必须小于或等于maximum-scale设置
maximum-scale   [0.0-10.0]  定义放大最大比例,它必须大于或等于minimum-scale设置
user-scalable   yes/no  定义是否允许用户手动缩放页面,默认值yes
其中width和height就是用来定义layout viewport宽高的,如果不指定该属性或者没有viewport meta标签,那么layout viewport宽度就是默认值

所以在移动端经常看见的这个设置

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
就是让layout viewport的宽度等于设备宽度,同时不允许缩放,这样的话用户不需要进行缩放(当然也不能缩放- -)和拖动网页,就能很好的进行网页浏览

设备像素比
设备像素比devicePixelRatio,其概念为设备物理像素和设备独立像素的比。

window.devicePixelRatio = physical pixels / dips
物理像素
一个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。

设备独立像素
独立于设备的用于逻辑上衡量像素的单位

如何获取
在javascript中,可以通过window.devicePixelRatio获取到当前设备的dpr。

在css中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。

以上是概念,下面举个栗子,以iphone6为例:

设备屏幕宽高为375×667,可以理解为设备独立像素
dpr为2,那么他的物理像素应该*2,为750×1334



width: 2px;
height: 2px;
在普通屏幕和retina屏幕,css像素所呈现的大小是一致的,但是普通屏幕对应了4个物理像素点,retina屏是16个



对于图片来说,理论上,1个图片像素对应1个物理像素,图片才能完美清晰的展示,但是在retina屏,如果和普通屏用相同的宽和高,就会出现图片像素点不够,从而导致图片模糊的情况




自适应
手机型号多种多样,屏幕大小也有很多种,如何在各种手机上完美展示页面成了一个大问题

media query
2010年,Ethan Marcotte提出了"自适应网页设计"(Responsive Web Design)这个名词,指可以自动识别屏幕宽度、并做出相应调整的网页设计。

其实现方式就是利用css3的media query

@media screen and (max-width:400px){ 
    .class  {
         background:#ccc; 
    }
}
也可以

<link rel="stylesheet" media="screen and (max-width: 400px)" href="mini.css" />
在不同屏幕宽度范围使用不同的class,以实现不同屏幕下布局的完美

百分比
media query能解决部分问题,但是有些布局方式,比如双层浮动



百分比布局就派上用场,直接设置宽度50%就ok了

如果是一行3列,33.33%嘛,不过这小数点,不优雅不精确

flex
2009年,W3C提出了一种新的方案----Flex布局,可以简便、完整、响应式地实现各种页面布局。

概念就不多讲了,可以看看阮老师的文章,有了flex布局,上面的一行三列非常简单,flex:1;就好了

rem
rem是(font size of the root element),根据网页的根元素来设置字体大小,和em(font size of the element)的区别是,em是根据其父元素的字体大小来设置,而rem是根据网页的跟元素(html)来设置字体大小的,举一个简单的例子

大部分浏览器下,默认字体大小为16px

html {
    font-size:16px;
}
如果想给一个p标签设置字体大小为12px,用rem就是这样写

p {
    font-size: 0.75rem; //12÷16=0.75(rem)
}
手淘flexible方案就利用了rem,其脚本主要做了三件事情

动态改写标签,根据不同的设备像素比,设置不同的scale值
给元素添加data-dpr属性,并且动态改写data-dpr的值
给元素添加font-size属性,并且动态改写font-size的值
如果设计稿是750px的,将其中元素的宽和高用rem作为单位,换算如下:

Flexible会将视觉稿分成100份(主要为了以后能更好的兼容vh和vw),而每一份被称为一个单位a。同时1rem单位被认定为10a。针对我们这份视觉稿可以计算出:

1a   = 7.5px
1rem = 75px 
比如一个200px×200px的元素,应该写为2.67rem×2.67rem

以上几种方案,其实要根据具体场景来选用或者组合使用,比如设计师想要的效果,一个通顶header,是想不同宽度屏幕都用相同的高度,还是想等比增高,这个决定了你的实现方案