本文由99根据Patrick H. Lauke的《A pixel is not a pixel is not a pixel》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html,以及作者相关信息
译者:99
本篇文章主要解释了CSS像素跟设备像互的区别,媒体查询跟Viewport在识别设备像素上的应用,以及iPhone的分辨率增加后对我们Web前端的影响。
在译这篇文章时,文章很多知识引用了神飞的《移动端webapp开发必备知识》和www.MyException.Cn的《什么是viewport,为啥需要viewport》。在此特向作者表示衷心的感谢。
译者:——99
昨天,来自John Gruber的文章中谈到最新的苹果手机提升了像素密度(960X640替代了480X320),并分析了苹果这么做的原因,他同时提出了一个问题,这对Web开发者会有什么影响呢?
我最近在深入研究移动端跨浏览器的宽高表现,可以这么说,在99%的情况下,苹果此举不会对web开发者有任何影响。
但剩下的1%就比较蛋疼了,不过我期待苹果可以像android一样采用一个中间过渡像素层来解决此问题。(John指出)在Android中存在这样的一个层。
首先我要申明一点,对于web开发者来说“标准尺寸”是没啥用处的,所以我忽略了这个,而且我也不会讨论显示的细节以及其他一些复杂问题,因此我对其中的一些概念描述的可能不是很专业,在此表示抱歉。
Web开发者到底需要啥
在开始下面的内容之前,大家先了解一下CSS Pixels与Device Pixels之间的区别:
- CSS pixels: 浏览器使用的抽象单位, 主要用来在网页上绘制内容。
- device pixels: 显示屏幕的的最小物理单位,每个dp包含自己的颜色、亮度。
——99
我确信对于web开发者来说,他们需要的是“css像素”,即类似width:300px跟font-size:14px 这类css语句中的px.
Css中的px跟设备自身的px是没什么关系的,即使将来出现了所谓“中间过渡层”,结果也是一样的。这是专门为web开发者提出的一个抽象概念。
通过页面缩放这个过程,我们可以很清楚的明白这个道理。如果我们放大页面,一个给了width:300px的元素会占据屏幕更大的空间,当然测量时会占据更多的设备(物理)像素。而css中的像素始终是300px。放大效果即是尽可能的扩展每一个css像素,使其占据更多的屏幕空间。
当缩放比率为100%时,一个css像素与一个设备像素是相同的(未来提供的中间过渡层,会代替“设备像素”)。下面图片表示当前状态时css像素与设备像素是重叠的。
(要提醒大家的是,缩放比例100% 在web开发中是没啥意义的,缩放级别对我们也没啥意义。我们需要知道的是当前有多少像素在适配屏幕!)
下面两张图诠释了当我们缩放页面时发生了啥。第一张图,用户缩小页面,注意观察浅色像素块(css像素)跟深色像素块(设备像素)。此时css像素变小,一个设备像素可能覆盖了多个css像素。
第二张图片跟上面正好相反,用户放大页面,此时css像素变大,因此一个css像素覆盖了多个设备像素
因此,元素仍然是300px(css像素) 而此时元素覆盖了多少的设备像素,是由当前的缩放比例决定的。
你可以通过在iphone上计算screen.width跟window.innerWidth的比来得到这个比例。这里会出现很多恼人的兼容性问题。除此之外 web开发者不需要对这个比例下太多心思,还是要注意像素是怎么适配屏幕的。
Window.innerWidth这里代表的视窗宽度,Screen.width 代表的屏幕分辨率。
这里大家可以做个实验就明白了,大家可以在网页100%的时候打印下screen.width跟window.innerWidth会发现是1:1。而我们利用浏览器的缩放功能,缩小网页时,发现screen.width不变,window.innerwidth变大,意思是同样的屏幕可以容纳的css像素更多了,放大网页正好相反!
——99
以上原理是不会改变的。因此以前在iphone上显示完美的网页,到了高设备像素的iphone上可能就会变得面目全非,这也是苹果极力想要避免的。
因此网页仍然会按照980px来渲染,但是占了多少个设备像素。。天知道。。
那些比较蛋疼的东西
有两个比较麻烦的东西:媒体查询的"device-width"和html标签中的"<meta name="viewport" width="device-width" / >"。这两个都与设备像素有关系的,但与css像素没关系,因为他们都是根据页面展现出的内容来定义的,而不是内部是什么css决定的。
媒体查询
device-width 这个媒体查询可以测量设备像素。Width这个媒体查询可以测量页面的总宽度,但这个是css像素。这个数在iphone上一般是980以上,原因我会在后面解释。
Device-width这个媒体查询以下面方式来定义
div.sidebar { width: 300px; } @media all and (max-device-width: 320px) { // styles assigned when device width is smaller than 320px; div.sidebar { width: 100px; } }
通过css定义宽度,sidebar现在的宽度是300px(css像素),但经过媒体查询,当设备宽度小于320像素时(设备像素),触发条件,sidebar的宽度变为100px(css像素)(还跟得上不,确实比较绕)。
CSS3中的Media Queries增加了更多的媒体查询,同时你可以添加不同的媒体类型的表达式用来检查媒体是否符合某些条件,如果媒体符合相应的条件,那么就会调用对应的样式表。换句简单的说,“在CSS3中我们可以设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表”。
有关于Media Queries介绍和使用可以参考下面:
- CSS3 Media Queries
- iPads和iPones的Media Queries
- CSS3 Media Queries模板
- 使用em单位创建CSS3的Media Queries
- Responsive设计和CSS3 Media Queries的结合
——大漠
同时理论上你可以利用媒体查询来根据厘米与英寸识别屏幕。(@media all and (max-device-width: 9cm))。但很不幸绝大多数情况下都不支持,包括iphone。这是因为很多情况下,物理尺寸(比如英寸)会被系统“翻译”为css尺寸。我测试过 大部分浏览器一英寸会被认为是96px(css像素)。因此上述根据物理尺寸进行的媒体查询,结果是没有什么参考价值的。
这里的物理尺寸跟设备像素比有专门的术语叫做dpi。
PPI,有时也叫DPI,所表示的是每英寸所拥有的像素(pixel)数目,数值越高,即代表显示屏能够以越高的密度显示图像。(注:这里的像素,指的是device pixels。)
注意,这里仍然是设备里的参数,与css像素是没有任何关系的!但是mediaquery却认成了css像素!
——99
<meta>标签
关于meta标签的介绍可以参考《<meta>》一文,但我们主要应用的是viewport标签,可以参考《Using the viewport meta tag to control layout on mobile browsers》一文。
——99
大多数情况下 <meta name="viewport" width="device-width"> 这个标签比上面要给力的多。viewport起源于apple,但现在被绝大多数移动浏览器所支持。这个标签的写法可以让你的layout viewport完全适配设备宽度
layout Viewport到底是啥呢?
这里文章写的比较简单,但是不好翻译。我大概给大家讲讲viewport。
两个概念,visual viewport跟layout viewport.
这里visualviewport可以认为是设备自己的宽度,那么注意,当你打开一个960px设计的网页时,手机会根据css中的百分比进行缩放。比如总长960的页面,导航条是20%。(实际解析出来就是192px)但是你不可能每个属性都是百分比吧,比如文字大小。
那么我用320px屏幕打开,导航条就成了64px了,但是我的字体大小是12px啊,完了,本来能显示很多汉字的(192/12)现在只能显示64/12个汉字了。
Apple找到了一个办法:在移动版(iOS)的Safari中定义了viewport meta标签①,它的作用就是创建一个虚拟的窗口(viewport),而且这个虚拟窗口的分辨率接近于桌面显示器,Apple将其定位为980px②。
①除此之外不同移动浏览器厂商也有不同的解决方案,例如UCweb就是使用中间件技术。
②不同的浏览器厂商对于layout viewport的大小定义不同
- Safari iPhone: 980px
- Opera: 850px
- Android WebKit: 800px
- IE: 974px
以一代iphone下的Safari来说就是:
在iphone的320px物理屏幕上——视觉窗口(visual viewport),创建出了一个980px的虚拟窗口——布局窗口(layout viewport),在视觉窗口(visual viewport)中我们可以拖动横向竖向滑动条或者放大缩小网页,来达到最佳的浏览效果(类似桌面浏览器);而布局窗口(layout viewport)用来配合CSS渲染布局,例如当我们设置一个容器的宽度为100%时,这个容器的实际值为980px而不是320px。如此一来大部分 网页就能以缩放的形式正常的显示在手机屏幕上了。
但是。。。。。。。。。。。。道高一尺魔高一丈,当我们“为了”解决手机端的问题,而特意制作了320px的页面时,悲剧发生了。。
因为iphone的layout viewport默认为980px,导致专为其优化的320px宽的页面只能以缩放的方式显示,(可以想象在你的浏览器里打开一个320px的页面的情景。。。)这时就需要对viewport进行设置
<meta name=”viewport” content=”width=device-width, initial-scale=1.0, user-scalable=no”/>将viewport定义为:宽度为设备宽度,初始缩放比例为1倍,禁止用户缩放。
这其实是故意舍弃了viewport的做法,大家一定要明白这个道理。给大家理一下:
普通的页面(960,980)显示很差? Apple去开发viewport,我们要求设计师设计320px的网页
好了,apple开发完viewport了,以前的烂网页能看了,这时候,我们换上320px的网页,我擦,怎么变的这么小了!
变回来!content=”width=device-width 就是这个过程。。。
更多viewport的知识,可以参考《Using the Viewport》和《响应式新首页设备适配(Device Adaptation)小结》
——99
一般来说layout Viewport要比设备屏幕大。 下面那张图让网页直接覆盖在屏幕上,大家可以看看视窗有多大。
当我们使用<meta name="viewport" width="device-width">后,页面视口被强制伸缩为屏幕宽度,比如320(iphone)。
这决定了你的网页视口会以怎样的宽度适配屏幕。当你的网页跟下图一样,设计成320px的宽度时,你又不使用width跟meta标签,页面就会被缩放了。如下图:
这种屏幕当然没法阅读了。如果你想让字体大小适配屏幕, meta标签就要出场了。当你增加这个标签后,视口会自动调整到屏幕大小(比如iphone会变成320px)
Apple的改变
我们回到开头的问题,当apple的屏幕像素增大后,会对我们上文提到的媒体查询跟meta标签造成什么影响。我当然不确定,但我希望不会对web开发造成影响。
<meta>标签
Meta标签很好说,这本来就是苹果发明的标签,为了让原始网页适配苹果的屏幕,而且已经推进给web开发者了。这意味着苹果不会改变meta标签识别出来的设备像素值了。
事实上,nexus one 另辟蹊径。在竖屏时屏幕宽度为480px,而应用meta标签识别出的屏幕宽度却是320px,是实际屏幕宽度的2/3
为什么会出现nexus的问题呢?
width=device-width
其实这个属性&值很有意思,字面意应该是viewport宽度等于设备宽度,但在实际中不同的浏览器都给出了个定值:320px;这个值还是源于 Apple,因为早期iphone的分辨率为320px × 480px,大量为iphone量身定制的网站都设置了viewport:width=device-width,并且按照宽度320px来设计制作,所 以其他浏览器加入viewport支持时为了兼容性也将device-width定义为了320px。
——99
如果我理解正确的话,这就是为什么nexus显示网页的时候缺失了1/3像素的原因。这与nexus对meta标签的解释是一致的。(因为认成320了。。)
因此谷歌为了解决这个问题,插入了一个中间层。这个层“层如其名”: “与设备无关的层”。这个层在实际屏幕与我们开发的css网页之间。
我期望iphone也会采取nexus的方案,建立中间层,保持meta标签识别出来仍然是320px(实际像素的一半)(作者的意思这样我们就不用改网页了)
媒体查询
Device-width仍然是问题重灾区。尽管nexus识别出480px作为设备宽度,我仍然觉得320px会更适合。我们且看apple是怎么办的。
最根本的问题是 设备独立像素(dips)在媒体查询中的继续应用。我们当然期待这东西的应用了,因为设备尺寸我们并不关心,我们只是想了解我们从屏幕上呈现的东西,dips应该很适合这个。
为什么dips有这个作用呢?这里要引入一个概念。
window.devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例。
公式表示就是:window.devicePixelRatio = 物理像素 / dips
详细的大家可以参考:《设备像素比devicePixelRatio简单介绍》一文。
——99
不幸的是nexus依然故我,media query查询出来的设备宽度仍然是480px而不是320px。但我觉得apple会为web开发者解决这个问题的。
因此结论很明显,meta的仍然故我,媒体查询的可就要掂量下了。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载烦请注明出处:
英文原文:http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html
中文译文:http://www.w3cplus.com/css/A-pixel-is-not-a-pixel-is-not-a-pixel.html