转: 关于viewport的理解

最近我做了一点儿针对手机的Web开发和相关研究。按说,Web自设计之初,就已经考虑了设备无关性。然而,现实总是不尽如人意

我们知道大多数网页都是针对桌面显示器开发和测试的,但是手机屏幕通常要比桌面显示器小很多,比如iPhone也就是320px。那么那些网页在手机上如何浏览呢?

一种是把网页缩放到很小,你可以看到整个网页但是看不清字了;或者只看网页的一个局部,然后上下左右移动来看其他部分。现在的手机浏览器把两种模式结合使用。(或许还有第三种——分析网页,将其中内容抽取出来,重组,然后呈现,不过这里不讨论这种方式。)

如果仅仅是出现横向滚动条,那问题倒不是很大。对于那些采用固定布局的“像素级精确设计”确实就是如此。但是使用自适应布局的网页就有问题了。比如一个三栏布局,其中一个边栏可能只有20%宽度,320px的屏幕上只有60多像素,只能放5个汉字,排版不美观不要说,如果里面有一些图片,很可能图片的宽度都超过60像素,造成overflow,从而破坏了布局。另一种常见布局方式是采用固定大小的边栏,例如240px宽,而主体部分则自适应宽度。然而对于320px的屏幕来说,本来是次要的边栏占据了3/4空间,主要部分却只有1/4空间,另外也极有可能因为内容包含图片等造成overflow。

手机浏览器厂商发明了两个viewport

简单来说,就是手机浏览器把自己冒充为拥有一个更宽的屏幕(~~layout viewport),这样页面的布局就能跟桌面浏览器一样了。不同浏览器冒充的数值不一样:iPhone是神奇的980——960它表弟;Android是保守的800——冒充一个800*600的显示器;而Windows Phone 7则是1024——冒充一个1024*768的显示器(充分体现微软的庸俗特质)。

原本布局就是按照layout viewport(桌面上的浏览器窗口)大小来进行的,现在决定布局的layout viewport和窗口分裂了,产生了两个viewport。 
~~~在桌面浏览器中 layout viewport 和 visual viewport是一样的都是 浏览器窗口可见区域的宽高,也可以说桌面浏览器没有2个viewport的概念

两个viewport其实并不新鲜。就像前面说的,所有做固定布局的同学其实都在不自觉使用两个viewport——固定布局,其实相当于人为设定了布局viewport。

使用独立的布局viewport还有一个好处,那就是缩放变得很简单,不用引起relayout。

在浏览器的历史上,主要有两种不同的缩放方式,一种是以IE6为代表的缩放(文字大小),实质是改变root元素的字体大小。另一种是像素缩放,实质是改变CSS pixel的大小(即1个css像素不再对应1个物理像素),或者说改变了浏览器的内部DPI。(Firefox还支持真正的字体缩放,与改变root元素的字体大小不同,它会缩放所有元素的font-size最终使用的值(used value),因此不仅对于以em设定的字体大小有效,对于以px和pt等所有单位设定的字体大小都有效。)

在桌面浏览器上,因为缩放时viewport的物理大小是固定的,如果进行像素缩放,实际就意味着viewport以CSS pixel计算的宽度和高度会随之改变,比如若放大到200%,CSS宽高就会缩小到原来的50%。而这必然引起relayout。

相反,在mobile浏览器上,像素缩放时,布局viewport的物理大小可随之缩放,因此其CSS宽高值是不变的,就不必引起relayout。这不仅避免了relayout的大量计算,也更符合移动设备上的用户体验(考虑一下你如何缩放地图就明白了)。

虽然两个viewport能比较好的解决在手机上浏览过往网页的问题,然而,这毕竟是一个向后看的方案,体验毕竟是受限的。想象在320宽的窗口里看960固定布局的网页,不可避免的要时常缩放和使用横向滚动条。在触摸屏上我们可以用手势来控制,会方便一点,但是仍然很麻烦。所以绝大多数移动Web开发者最终还是选择针对小屏幕(重新)进行设计。

不过一个显然的问题是,如果我的网页已经考虑了小屏幕,甚至就是专门为手机设计的,那么我其实不需要两个viewport(也不需要缩放),这时候怎么办?更一般的问题是,如果我设计的网页不是针对960或者800或者1024的呢(至少你选了960,就排除了800和1024;你选了800,就排除了960和1024;你选了1024,就排除了800和960……)?

于是Apple发明了viewport的meta标签,例如: 
<meta name="viewport" content="width=320, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">

其中width表示网页的布局layout宽度。initial-scale表示初始时的缩放比例,minimum-scale和maximum-scale分别表示最小和最大缩放比例。这样,上面这个meta就表示布局宽度320像素,初始缩放为1倍(即不缩放),且禁止用户缩放(因为最大最小缩放都为1倍)——一个专为iPhone优化的网页通常就会用这样的设置。

如果你是针对960设计的,那么可以用这样一个meta: 
<meta name="viewport" content="width=960, initial-scale=0.33"> 
这表示布局宽度为960像素,初始缩放为0.33,也就是,会缩小到大约1/3,这样正好可以在320像素的宽度里看到整个网页。你也可以不设initial-scale,因为手机浏览器大多默认会初始缩放到可容纳整个网页宽度。

嗯,看上去不错吧。

可是,说到底,手机浏览器的这种设计,实际上揭示了一个难堪的真相——你们这些网页仔,其实从来没真正做好过屏幕适应。因为一个能自动完美适应不同屏幕大小的“正确”方案,width的取值就不应该是一个固定数字。幸好,safari的工程师在发明viewport时还是给我们留了点面子,width的取值除了像320或960这样的数字,也可以是关键字device-width(其实我认为更合适的词是auto),表示采用设备宽度。

然而,历史总是杯具的重复自己。微软就又(嗯,我为什么要说“又”呢?)贡献了这样一个例子:Window Phone 7的设备宽度通常至少是480,那么按理说,如果viewport中设置了width=device-width,layout宽度应该是480像素,可是IE mobile会将viewport设为320!这是神马原因呢?

原来据说微软收集的数据表明,有大量站点使用了device-width,但是其实只为320像素宽(也就是iPhone的宽度)优化——比如直接用一个固定宽度320px的<div>将内容wrap起来!我勒个去,诸位移动Web开发者,你们有木有这么干?有木有!

那后面的故事就不用说了。微软当然是做出了一个“正确”的选择。

另外需要注意的是,width只是设置layout宽度,还要乘上缩放比例,才能得到最终的显示宽度。那么对于480像素的屏幕来说,若device-width“被320”,那initial-scale应该是1.5才能占满整个屏幕宽度。可是如前所述,针对性优化的网页会把initial-scale设成1.0!

对此微软是如何处理的呢?文档语焉不详,而其模拟器要在Windows 7上才能运行,所以我也暂时没有进行实测,不过据我推测,其initial-scale应该仍旧会保持1.0,也就是这1.5会变成额外的缩放因子。实际上其他移动浏览器已经这样做了,比如Fennec(Firefox的移动版)就是如此。Android和iPhone 4也都有类似的设计,为什么会这样?这样会不会产生新问题?留待下一篇博客再讨论。

------------------------------------------------

在响应式设计或移动Web开发当中经常见到的一句代码:

<meta name=”viewport” content=”width=device-width” >

content属性还包括initial-scale,user-scalable等,不过这里不谈,它们的意思都很容易理解。这里要谈得是:viewport代表什么?device-width又是啥?

先来理解两个概念:device pixels与CSS pixels。

device pixels指设备的物理像素,在PC端就是你在操作系统里设置的屏幕分辨率y,其值可以通过 screen.width/screen.height 获取。在移动端下面再说。

CSS pixels指在CSS文件中设置的字体大小、元素宽度等,如font-size: 14px; width: 100px; 。在PC端,浏览器缩放比例为100%,也即默认情况下,1 CSS pixel = 1 device pixel。

当你放大页面到200%时,字体大小与元素宽度的像素值不会改变,是因为这些像素值是用CSS pixels表示的,实际上放大的是CSS pixels,此时 1 CSS pixel = 4 device pixels,高和宽都是200%。此时你获取 screen.width/screen.height的值,并没有变化,而 window.innerWidth 和 window.innerHeight 的值变成了原来一半,是因为 window.innerWidth/window.innerHeight 的值也是用CSS pixels来表示的。

当你进行流式布局时,会用百分比设置元素的宽度,比如一个块级元素宽度为10%,那么你也知道10%实际上是父级元素宽度的10%。但是你并没有设置父级元素的宽度啊,好吧,你也知道父级元素的宽度与其父级元素宽度一样(通过继承得来,假设这些元素都是块级元素)。然后向上到body元素的宽度,最终为html元素的宽度,其值可以通过 document.documentElement.clientWidth 获取。那这个宽度怎么来得呢?

Viewport

viewport,翻译为视口,也即可视区域的大小,PC端通过window.innerWidth 和 window.innerHeight 获取。

html元素也即文档的宽度,来自于viewport的宽度,在PC端要加上滚动条的宽度才会与viewport的宽度一样。因此,文档的宽度最终来自于viewport的宽度,PC端通过 window.innerWidth 获取。

而在移动端,情况将变得复杂。

首先,上面提到文档的宽度来自于viewport的宽度,我们把这个viewport称为layout viewport,因为它和布局有关。在手机上面,因为手机的屏幕很小,当初iphone发布时,为了显示完整的桌面网页,就把给layout viewport设置了一个980px的值。手机上,可以通过 document.documentElement.clientWidth 来获取,我在安卓手机上测试也是980px。

但是这样显示网页,那网页的字体、元素都很小,小到打开这样一个网页,首先要做的就是放大页面。为了提高可读性,Apple允许通meta标签来设置layout viewport的宽度,也即文章开头的那行代码。

但是,device-width又是什么呢?

第一代iphone的分辨率为320*480,屏幕尺寸为3.5寸。当时把layout viewport设置成与浏览器宽度一样(而手机上浏览器宽度与手机屏幕宽度一样)时,不用每次打开网页放大了,而且显示的字体与桌面上差不多,可读性很好。因此就定义了一个device-width,即是手机的屏幕分辨率,此时device翻译为“设备”还合适。

但是第二代iphone发布时,屏幕的分辨率变成了480*960,而屏幕尺寸仍然为3.5寸,如果device-width仍然为手机的屏幕分辨率宽度,那么字体将会比第一代小很多。所以,维持device-width的值不变将会是个很好得选择,能与前面兼容。也因此,iphone上的device-width的值一直为320,只不过device再表示“设备”已经不合适了,实际上代表的是一个中间层。而Android也采用了这一概念,其device-width的值为360的多,360=540/1.5,360=720/2。

如何获取device-width的值呢?

浏览器并没有提供一个获取device-width的属性或方法,但是通过window.innerWidth 可以获取,需要注意的是,必须添加文章开头那行代码才可以跨浏览器获取。如果不添加那行代码,我自己在HTC G18/ Andoird OS 4.0.3中测试,自带浏览器/UC9.6/QQ5.0可以获取,而在Chrome33和Opera20中通过screen.width可以获取。iPhone与iPad我没测试。这是测试网页地址:

http://www.xiaocaoge.com/demo/viewport-screen-device-width-mobile.html

Chrome与Opera比较深入实现了中间层的概念,屏幕的实际分辨率与Web开发关系并不大,Chrome与Opera就将 screen.width 返回中间层的宽度。这里我也不明白哪种设计更好些。

这里 有个链接 可以查看各种手机型号的device-width/device-height大小,虽然链接称为viewport size。

----------------------------------

看了以上的参考资料对于 <meta name="viewport" content="width=divice-width, initial-scale=1.0, target-densitydpi=hight-dpi" />感到还是不怎么清晰。

设备的屏幕宽度 == 浏览器的视口宽度

浏览器的默认layout viewport 一般都比屏幕宽度要大,模拟桌面环境的分辨率,没有设置 <meta name="viewport" ... />时,layout viewport采用默认宽度(960px 800px...因设备而异, px为 css pixel),

比如说一个320像素宽的手机(假如默认的layout viewport为800),为了在320像素中能容纳800px的内容,初始缩放会变为 320/800, 1css pixel被缩小为了320/800 css pixel, 所以一个800像素宽的页面能被完整显示在手机屏幕上,但是内容都缩小了,如原来css定义的12px字体,变为 12 * 320/800 px;

当我们在 <meta name="viewport" content="width=divice-width, initial-scale=1.0 " />

initial-scale, minimum-scale, maximum-scale 其实缩放的是 css pixel.

以上为自己的一些理解,不一定正确

target-densitydpi是做什么的呢,有待研究。

------------------------------

关于target-densitydpi

  1. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" >

但发现页面依旧不根据手机屏幕进行自动缩放,后来找其他同事帮忙解决了,我看了源代码发现了是在原来的viewport中增加了target-densitydpi属性。看之初不太了解,也因为当时自己手上有其他需求在处理,最近突然想起了这件事,准备对它做一些了解,以备不时之需。

首先来了解一下这个属性到底是做什么的,从网上摘录了一段简介,如下:

一个屏幕像素密度是由屏幕分辨率决定的,通常定义为每英寸点的数量(dpi)。Android支持三种屏幕像素密度:低像素密度(~~120dpi),中像素密度(~~160dpi),高像素密度(~~240dpi)。一个低像素密度的屏幕每英寸上的像素点更少,而一个高像素密度的屏幕每英寸上的像素点更多。Android Browser和WebView默认屏幕为中像素密度。

下面是 target-densitydpi 属性的 取值范围

  • device-dpi –使用设备原本的 dpi 作为目标 dp。 不会发生默认缩放。
  • high-dpi – 使用hdpi 作为目标 dpi。 中等像素密度和低像素密度设备相应缩小。
  • medium-dpi – 使用mdpi作为目标 dpi。 高像素密度设备相应放大, 像素密度设备相应缩小。 这是默认的target density.
  • low-dpi -使用mdpi作为目标 dpi。中等像素密度和高像素密度设备相应放大。
  • <value> – 指定一个具体的dpi 值作为target dpi. 这个值的范围必须在70–400之间。

注:以上信息取自http://www.php100.com/html/webkaifa/HTML5/2012/0831/10979.html

上面的信息我也从android官网找到了相关资料,这个资料在上面URL页面中都进行了翻译!

http://developer.android.com/guide/webapps/targeting.html

从这段简介可以得到如下信息:

1、它是指的屏幕分辨率,现在绝大多数智能手机屏幕都是可以通过viewport中的width来调整页面宽度的,而是浏览器通过width值来进行计算得出。

2、target-densitydpi这个属性只对android系统起作用,专有属性。IOS不支持它,所以说起来,还是有兼容性问题,如果页面是兼容IOS和android的话。

转: 关于viewport的理解,布布扣,bubuko.com

时间: 2024-10-11 22:11:36

转: 关于viewport的理解的相关文章

移动前端开发之viewport的理解

在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或响应各种不同分辨率的移动设备. 一.viewport的概念 通俗的讲,移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,在具体一点,就是浏览器上(也可能是一个app中的webview)用来显示网页的那部分区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览

对于viewport的理解

刚看到viewport的时候, 各种搜索,各种概念, 看得头大. 各种博客 / 文档看过来,整理下自己心得, 希望可以帮助需要的童鞋. (本文是自己的理解, 只对于移动端来说) 好多博客有介绍n种视口,n种像素.准确的概念我也记不住.  我只说下对dpr的理解.   dpr = 设备物理像素 / 设备的逻辑分辨率.(不知道dpr的自己百度一下)   设备物理像素是多少 : 就是屏幕的分辨率. 比如 :1334*750 设备逻辑分辨率是什么 : 理解这个概念之前先要理解设备独立像素. 设备独立像素

两个viewport的故事(第二部分)

在这个迷你系列的文章里边我将会解释viewport,以及许多重要元素的宽度是如何工作的,比如<html>元素,也包括窗口和屏幕. 这篇文章我们来聊聊关于移动浏览器的内容.如果你对移动开发完全是一个新手的话,我建议你先读一下第一篇关于桌面浏览器的文章,先在熟悉的环境中进行下热身. 移动浏览器的问题 当我们比较移动浏览器和桌面浏览器的时候,它们最显而易见的不同就是屏幕尺寸.为桌面浏览器所设计的网站在移动浏览器中显示的内容明显要少于在桌面浏览器中显示的:不管是对其进行缩放直到文字小得无法阅读,还是在

CSS之viewport 2

在这个迷你系列的文章里边我将会解释viewport,以及许多重要元素的宽度是如何工作的,比如<html>元素,也包括窗口和屏幕. 这篇文章我们来聊聊关于移动浏览器的内容.如果你对移动开发完全是一个新手的话,我建议你先读一下第一篇关于桌面浏览器的文章,先在熟悉的环境中进行下热身. 移动浏览器的问题 当我们比较移动浏览器和桌面浏览器的时候,它们最显而易见的不同就是屏幕尺寸.为桌面浏览器所设计的网站在移动浏览器中显示的内容明显要少于在桌面浏览器中显示的:不管是对其进行缩放直到文字小得无法阅读,还是在

Html5移动端页面自适应布局详解(阿里rem布局)

在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport,通读网上的各种对于viewport的解释之后 大概viewport可以理解为三种 1.layout viewport ,也就是这个浏览器默认的viewport 2.visual viewport  , 浏览器可视区域viewport 3. ideal viewport  ,移动设备的理想viewport 通俗点讲,pc端css中的1px并不会等于移动端,原理很简单,举个例子说 通过chrome浏览器可以知道,一个I

移动开发中“单位”的那些事儿

前言 在移动开发中我们常常会考虑度量单位的问题,在传统pc的web开发中用的比较多的是px(css像素),在android开发中一般则用dp.sp.px(物理像素)等,而移动web开发中同样也是用px(css像素)做单位,通常会结合viewport进行缩放.本篇blog就梳理一下在移动开发中用到的各种单位以及他们之间的联系和区别. 绝对单位和相对单位 如题,首先来看看什么是绝对单位和相对单位: 绝对单位:即值在任何环境下都不会变化的常量,如我们日常生活中经常会用到的in(inch英寸).cm(厘

移动端适配方案

Flexible适配方案 最早的文章,是15年阿里手淘团队的移动端适配方案. 设计师常选择iPhone6作为基准设计尺寸,交付给前端的设计尺寸是按750px * 1334px为准(高度会随着内容多少而改变). 前端开发人员通过一套适配规则自动适配到其他的尺寸. 先了解一些基本概念 视窗viewport 简单理解,viewport是严格等于浏览器的窗口,在桌面浏览器中,viewport就是浏览器窗口的宽度高度. 但是在移动端的viewport太窄,为了能更好的为css布局服务,所以提供了两个vie

移动前端开发之viewport的深入理解

在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或响应各种不同分辨率的移动设备. 一.viewport的概念 通俗的讲,移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,在具体一点,就是浏览器上(也可能是一个app中的webview)用来显示网页的那部分区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览

viewport理解

参考:移动前端开发之viewport的深入理解 对以上的文章中的知识点,感觉换另一个角度更好理解一点,记录如下: 屏幕的像素密度:区域像素点总数 / 区域大小 css中的1px显示在像素密度高的屏幕上时,所占据的像素点要多,之所以要这样是因为可以保证,无论在什么分辨率的手机上显示css的1px时,都能保证视觉距离是一致的. 缩/放屏幕时,css中的px所占据的屏幕像素点也会在原来的基础上按照倍数来进行减少/增加 默认情况下(没有设置viewport属性),移动设备上浏览器默认的画布宽度为980p