移动前端开发中的页面布局问题

屏幕尺寸

屏幕尺寸指的是屏幕可视区域对角线的长度,单位都是英寸。

屏幕分辨率

通常情况下屏幕分辨率指的是屏幕可视区域横向和纵向各有多少个物理像素用于显示。比如华为P9、小米5以及iPhone 6 Plus的分辨率都是1080*1920,也就是说屏幕可视区域横向有1080个物理像素,纵向有1920个物理像素用于显示。

屏幕像素密度(PPI/DPI)

  • 概念

屏幕像素密度是指的屏幕对角线一英寸长度里的物理像素数量,安卓设备叫做DPI(Dots Per Inch),苹果设备泽叫做PPI(Pixels Per Inch)。

  • 计算

以前面的1080*1920分辨率为例,根据计算可得到对角线的物理像素数量为2203:

√(1080² + 1920²) ≈ 2203px

然后根据屏幕尺寸可以计算出屏幕的像素密度,比如华为P9为5.2英寸,那么屏幕像素密度为:

2203 / 5.2 ≈ 441 dpi

iPhone 6 Plus为5.5英寸,屏幕像素密度为:

2203 / 5.5 ≈ 401 ppi
  • 分类

谷歌和苹果根据屏幕密度的取值范围,对屏幕设备进行了分类,不同级别的屏幕对应不同的设备像素比。

安卓设备的分类:

名称屏幕像素密度范围设备像素比
ldpi < 120dpi 0.5
mdpi 120dpi <= && < 160dpi 1
hdpi 160dpi <= && < 240dpi 1.5
xhdpi 240dpi <= && < 320dpi 2
xxhdpi 320dpi <= && < 480dpi 3
xxxhdpi 480dpi <= && < 640dpi 4

苹果设备的分类:

名称屏幕像素密度范围设备像素比
non-retina 163ppi 1
retina 326ppi 2
retina HD 401ppi 3

前面提到了设备像素比的概念,这个与开发密切相关,后面会详细介绍。

屏幕物理像素(Device Pixel)

屏幕的最小物理显示单位,数值跟屏幕分辨率的意义一致。因为不同屏幕的像素密度不一样,因此不同设备1px的物理像素的尺寸也不一样。

有的设备为了优化显示,会用 “ 缩减像素采样 ” 算法,使屏幕表现出来的横(纵)向物理像素总数,与设备的实际的屏幕分辨率参数不一致。在PC显示器上设置分辨率大小,也是会实现类似的效果。

渲染虚拟像素(Device Independent Pixel)

用于设置界面显示的虚拟像素单位。在屏幕密度不同的设备上,1px的物理像素尺寸不一样,但是1px的渲染虚拟像素基本是一样的,因此这类像素也被称为设备无关像素。

在前端开发时,页面上的CSS像素就是指的渲染虚拟像素,在不同设备上浏览同一个页面,当页面的缩放比例相同时,字体看上去都是一样大的。

各个设备,在横(纵)向上的渲染虚拟像素数量,可以根据屏幕的物理数量以及设备像素比计算出来,而设备像素比的取值取决于屏幕的像素密度。

常见设备的屏幕横(纵)向上的渲染虚拟像素数:

华为P9:1080 / 3 = 360px
iPhone 6 Plus:1242 / 3 = 414px (实际横向分辨率为1080px,经过 “ 缩减像素采样 ”处理后,能达到1242px)

设备各类像素映射关系图(来源paintcodeapp) image

设备像素比(Device Independent Pixel)

了解了上面两个概念,那么设备像素比按字面意思来理解,是指的屏幕横(纵)向的物理像素数量除以屏幕横(纵)向渲染虚拟像素数量,经四舍五入后得到的整数值。

设备像素比 = 屏幕物理像素 / 渲染虚拟像素

通俗点来理解,就是指的一个渲染虚拟像素对应到的屏幕物理像素的数量。例如华为P9的设备像素比是3,那么用华为P9浏览页面时,页面上1px像素的区域包含了3px * 3px个物理像素。

这也能解释在设备像素比超过1的手机上浏览页面,遇到图片模糊的原因。例如在一个设备像素比是2的手机上浏览页面,页面上有一个图片的像素为12px * 12px,css设置的图片高宽为12px * 12px,这张图片将会由48px * 48px个物理像素来显示,因为图片只有12px * 12px,这样就会有一半的物理像素没有真实的RBG值来显示,只能从临近物理像素来获取RBG值,呈现的效果就是图片模糊。要解决这个问题,只需要将图片替换成48px * 48px即可,css保持不变,图片在页面上的高宽不变,用于显示图片的48px * 48px个物理像素能从元素图片中获取到真实RBG值,因此图片也能高保真显示了。

Viewport

viewport是页面的一组参数,会影响可通过html的meta标签来设置,常用的参数如下:

参数意义
width viewport容器宽度
initial-scale 页面初始缩放比例
minimum-scale 页面最小缩放比例
maximum-scale 页面最大缩放比例
user-scalable 是否允许手工缩放页面(no:不允许;yes:允许)

viewport容器可以把它理解为页面html元素的父容器,当html设置宽度为100%时,页面宽度值与viewport的宽度值相等。在PC浏览器上,viewport的宽度与浏览器可视区域的宽度一致,在手机浏览器上则不一定,大多数手机浏览器默认的viewport宽度是980px。

当未通过代码设置viewport的值时,手机浏览器打开页面有两种现象:

现象一:页面不出现滚动条,占满浏览器的可视区域

image

从图片能看出页面被缩放了,因为viewport的width默认值是980px,因此可以计算出页面缩放的比例(以华为P9手机为例,屏幕的横向渲染虚拟像素数量为360px):

980 / 360 ≈ 2.7

因此,系统给viewport的默认设置为:

<meta name="viewport" content="width=980, initial-scale=2.7" />

现象二:页面缩放正常,页面出现了横向滚动条

image

此时,页面缩放正常并且横向滚动的宽度为980px, 系统给viewport的默认设置为:

<meta name="viewport" content="width=980, initial-scale=1" />

移动页面可以在html的头部添加下面的代码:

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />

这个设置让viewport的容器宽度和屏幕横向上的渲染虚拟像素数量值相等,同时页面缩放比例为1,这样通过相应式代码实现的页面,既不会出现横向滚动条,页面字体大小也正常。

实践方案

  • 在html的头部添加下面的代码
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />

这段代码将页面容器的宽度设置为跟屏幕渲染虚拟像素宽度一致,并将页面缩放比例锁定为1。这么设置避免响应式布局的页面出现横向滚动条,确保了通过css以px设置的字体和元素高宽,通过各类设备的浏览器访问时,大小都一致。

  • 设计稿用750px * 1334px尺寸

因为绝大部分手机的设备像素比都是2或3,因此为了避免出现图片模糊问题,设计稿需要按屏幕渲染虚拟像素宽(高) * 设备像素比的尺寸来提供,这样同一个设计稿就需要提供n份不同尺寸的,从工作量和现实效果上折衷一下按iphone 6的屏幕渲染虚拟像素宽高尺寸来出一份设计稿。页面字体和元素高宽的样式都按设计稿的大小的一半来设置即可。

  • 雪碧图样式

为雪碧图添加下面的样式,雪碧图来源于750px * 1334px尺寸的设计稿:

background-image: url([雪碧图路径]); 
background-size: (雪碧图宽度/2)px (雪碧图高度/2)px;
  • 部分元素用rem单位设置样式

因为设计稿是按iphone 6的尺寸来的,屏幕的横向虚拟渲染像素总数为375px,而其它设备的这个值有320px,360px和414px等,比375px小的设备会出现设计稿有部分内容无法显示的情况,比375px大的设备则会出现多余空间的情况。

设计稿应按纵向流式布局来设计,前端代码按响应式方式来实现,可以避免上面提到的问题,但有些场景会出现一行有多个元素,这时就需要折算每个元素占屏幕宽度的比例,再设置元素的样式宽度。

解决上面的问题可以引入手淘的flexsible.js库,从设计稿上计算元素的rem单位的高宽值(750/元素在设计稿上的尺寸),然后这个值可以直接设置为页面上对应元素的样式的高宽值,单位为rem。


参考文章
posted @ 2015-03-10 18:48  蓼椮  阅读(1513)  评论(0编辑  收藏  举报