`
天梯梦
  • 浏览: 13732454 次
  • 性别: Icon_minigender_2
  • 来自: 洛杉矶
社区版块
存档分类
最新评论

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

 
阅读更多

英文:http://www.quirksmode.org/mobile/viewports2.html

翻译:http://weizhifeng.net/viewports2.html

 

在这个迷你系列的文章里边我将会解释viewport,以及许多重要元素的宽度是如何工作的,比如<html>元素,也包括窗口和屏幕。

 

这篇文章我们来聊聊关于移动浏览器的内容。如果你对移动开发完全是一个新手的话,我建议你先读一下第一篇关于桌面浏览器的文章,先在熟悉的环境中进行下热身。

 

移动浏览器的问题

当我们比较移动浏览器和桌面浏览器的时候,它们最显而易见的不同就是屏幕尺寸。为桌面浏览器所设计的网站在移动浏览器中显示的内容明显要少于在桌面浏览器中显示的;不管是对其进行缩放直到文字小得无法阅读,还是在屏幕中以合适的尺寸只显示站点中的一小部分内容。

 

移动设备的屏幕比桌面屏幕要小得多;想想其最大有400px宽,有时候会小很多。(一些手机声称拥有更大的宽度,但是它在撒谎-或者也可以说它给我们提供了没用的信息。)

 

平板设备中的像素中间层会在桌面环境和移动环境的缺口之间架起一段桥梁,比如像iPad或者传说中HP基于webOS所研发的设备,但是这并没有改变根本问题。站点必须也能在移动设备上工作,所以我们不得不让它们能在小尺寸的屏幕上正常显示。

 

最重要的问题在CSS上,特别是viewport的尺寸。如果我们照搬桌面环境的模式,那么我们的CSS就要立马熄火了(译者:即显示混乱)。

 

让我们看下之前sidebar为width: 10%的例子。如果移动浏览器想要实现跟桌面浏览器一样的行为,它们最多为元素设置40px的宽度,但是这太窄了。你的流式布局会看起来被挤乱了。

 

解决这个问题的一个方法是为移动浏览器建立一个特定的站点。先抛开你是否有必要这么做这个基本问题,而实际的情况是只有很少的网站拥有者真正知道要对移动设备做特殊的处理。

 

移动浏览器厂商想给它们的客户尽可能的提供最好的体验,这现在指的就是「尽可能的跟桌面一样」。因此耍一些花招是必要的。

 

两个viewport

viewport太窄了,以至于不能正常展示你的CSS布局。明显的解决方案是使viewport变宽一些。无论如何,需要把它分成两部分:visual viewport和layout viewport。

 

George Cummins在Stack Overflow上对基本概念给出了最佳解释:

把layout viewport想像成为一张不会变更大小或者形状的大图。现在想像你有一个小一些的框架,你通过它来看这张大图。(译者:可以理解为「管中窥豹」)这个 小框架的周围被不透明的材料所环绕,这掩盖了你所有的视线,只留这张大图的一部分给你。你通过这个框架所能看到的大图的部分就是visual viewport。当你保持框架(缩小)来看整个图片的时候,你可以不用管大图,或者你可以靠近一些(放大)只看局部。你也可以改变框架的方向,但是大图 (layout viewport)的大小和形状永远不会变。

也看一下Chris给出的解释

 

visual viewport是页面当前显示在屏幕上的部分。用户可以通过滚动来改变他所看到的页面的部分,或者通过缩放来改变visual viewport的大小。

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

无论怎样,CSS布局,尤其是百分比宽度,是以layout viewport做为参照系来计算的,它被认为要比visual viewport宽。

所以<html>元素在初始情况下用的是layout viewport的宽度,并且你的CSS是在屏幕(译者注:宽度等于layout viewport的虚拟屏幕)好像明显比电话屏幕宽(物理屏幕)要宽的假设基础上进行解释的。这使得你站点布局的行为与其在桌面浏览器上的一样。

layout viewport有多宽?每个浏览器都不一样。Safari iPhone为980px,Opera为850px,Android WebKit为800px,最后IE为974px。

一些浏览器有特殊的行为:

  • Symbian WebKit会保持layout viewport与visual viewport相等,是的,这意味着拥有百分比宽度元素的行为可能会比较奇怪。但是,如果页面由于设置了绝对宽度而不能放入visual viewport中,那么浏览器会把layout viewport拉伸到最大850px宽。
  • Samsung WebKit (on bada)使layout viewport和最宽的元素一样宽。
  • 在BlackBerry上,layout viewport在100%缩放比例的情况下等于visual viewport。这不会变。

 

缩放

很 显然两个viewport都是以CSS像素度量的。但是当进行缩放(如果你放大,屏幕上的CSS像素会变少)的时候,visual viewport的尺寸会发生变化,layout viewport的尺寸仍然跟之前的一样。(如果不这样,你的页面将会像百分比宽度被重新计算一样而经常被重新布局。)

 

理解layout viewport

为了理解layout viewport的尺寸,我们不得不看一下当页面被完全缩小后会发生什么。许多移动浏览器会在初始情况下以完全缩小的模式来展示任何页面。

重点是:浏览器已经为自己的layout viewport选择了尺寸,这样的话它在完全缩小模式的情况下完整的覆盖了屏幕(并且等于visual viewport)。

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

所以layout viewport的宽度和高度等于在最大限度缩小的模式下屏幕上所能显示的任何内容的尺寸。当用户放大的时候这些尺寸保持不变。

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

layout viewport宽度一直是一样的。如果你旋转你的手机,visual viewport会发生变化,但是浏览器通过轻微的放大来适配这个新的朝向,所以layout viewport又和visual viewport一样宽了。

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

这对layout viewport的高度会有影响,现在的高度比肖像模式(竖屏)要小。但是web开发者不在乎高度,只在乎宽度。

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

 

度量layout viewport

我们现在有两个需要度量的viewport。很幸运的是浏览器战争给我们提供了两个属性对。

document.documentElement.clientWidth-Height包含了layout viewport的尺寸。

document.documentElement.clientWidth/Height

  • 意义:Layout viewport的尺寸
  • 度量单位:CSS像素
  • 完全支持Opera, iPhone, Android, Symbian, Bolt, MicroB, Skyfire, Obigo。
  • 在Iris中Visual viewport有问题
    • Samsung WebKit在页面应用了<meta viewport>标签的时候会返回正确的值;否则使用<html>元素的尺寸。
    • Firefox返回以设备像素为单位的屏幕尺寸。
    • IE返回1024x768。然而,它把信息存储在document.body.clientWidth/Height中。这和桌面的IE6是一致的。
    • NetFront的值只在100%缩放比例的情况下是正确的。
    • Symbian WebKit 1 (老的S60v3设备)不支持这些属性。
  • BlackBerry不支持。
HTML5: 两个viewport的故事(第二部分)

朝向会对高度产生影响,但对宽度不会产生影响。

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

 

度量visual viewport

对于visual viewport,它是通过window.innerWidth/Height来进行度量的。很明显当用户缩小或者放大的时候,度量的尺寸会发生变化,因为屏幕上的CSS像素会增加或者减少。

window.innerWidth/Height

  • 意义:Visual viewport的尺寸。
  • 度量单位:CSS像素。
  • 完全支持iPhone,Symbian,BlackBerry。
  • 问题
    • Opera和Firefox返回以设备像素为单位的屏幕宽度。
    • Android,Bolt,MicroB和NetFront返回以CSS像素为单位的layout viewport尺寸。
  • 不支持IE,但是它在document.documentElement.offsetWidth/Height中提供visual viewport的尺寸。
    • Samsung WebKit返回的是layout viewport或者<html>的尺寸,这取决于页面是否应用了<meta viewport>标签。
  • Iris,Skyfire,Obigo根本就是扯淡。
HTML5: 两个viewport的故事(第二部分)

不幸的是这是浏览器不兼容问题中的一部分;许多浏览器仍然不得不增加对visual viewport度量尺寸的支持。但是没有浏览器把这个度量尺寸存放任何其他的属性对中,所以我猜window.innerWidth/Height是标准,尽管它被支持的很糟。

 

屏幕

像桌面环境一样,screen.width/height提供了以设备像素为单位的屏幕尺寸。像在桌面环境上一样,做为一个开发者你永远不需要这个信息。你对屏幕的物理尺寸不感兴趣,而是对屏幕上当前有多少CSS像素感兴趣。

screen.width and screen.height

  • 意义:屏幕尺寸
  • 度量单位:设备像素
  • 完全支持Opera Mini,Android,Symbian,Iris,Firefox,MicroB,IE,BlackBerry。
  • 问题:Windows Mobile上的Opera Mobile只提供了风景模式(横屏)的尺寸。S60上的Opera Mobile返回的值是正确的。
    • Samsung WebKit返回layout viewport或者<html>的尺寸,这取决于是否在页面上应用了<meta viewport>标签。
    • iPhone和Obigo只提供了肖像模式(竖屏)的尺寸。
    • NetFront只提供风景模式(横屏)的尺寸。
  • Bolt,Skyfire依旧在扯淡。
HTML5: 两个viewport的故事(第二部分)

 

缩放比例 zoom level

直接读出缩放比例是不可能的,但是你可以通过以screen.width除以window.innerWidth来获取它的值。当然这只有在两个属性都被完美支持的情况下才有用。

幸运的是缩放比例并不太重要。你需要知道的是当前屏幕上有多少个CSS像素。你可以通过window.innerWidth来获取这个信息,如果它被正确支持的话。

 

滚动距离Scrolling offset

你还需知道的是visual viewport当前相对于layout viewport的位置。这是滚动距离,并且就像在桌面一样,它被存储在window.pageX/YOffset之中。

window.pageX/YOffset

  • 意义:滚动距离;与visual viewport相对于layout viewport的距离一样。
  • 度量单位:CSS像素
  • 完全支持iPhone,Android,Symbian,Iris,MicroB,Skyfire,Obigo。
  • 问题:Opera,Bolt,Firefox和NetFront一直返回0。
    • Samsung WebKit只有当<meta viewport>被应用到页面上时候才返回正确的值。
  • 不支持IE,BlackBerry。IE把值存在document.documentElement.scrollLeft/Top之中。
HTML5: 两个viewport的故事(第二部分)

 

\<html> 元素

就像在桌面上一样,document.documentElement.offsetWidth/Height提供了以CSS像素为单位的<html>元素的整个尺寸。

document.documentElement.offsetWidth/Height

  • 意义:<html>元素的整体尺寸。
  • 度量单位:CSS像素。
  • 完全支持Opera,iPhone,Android,Symbian,Samsung,Iris,Bolt,Firefox,MicroB,Skyfire,BlackBerry,Obigo。
  • 问题:NetFront的值只在100%缩放比例的情况下才正确。
    • IE使用这个属性对来存储visual viewport的尺寸。在IE中,去document.body.clientWidth/Height中获取正确的值。
HTML5: 两个viewport的故事(第二部分)

 

媒体查询Media queries

媒体查询和其在桌面环境上的工作方式一样。width/height使用layout viewport做为参照物,并且以CSS像素进行度量,device-width/height使用设备屏幕,并且以设备像素进行度量。

 

换句话说,width/heightdocument.documentElement.clientWidth/Height值的镜像,同时device-width/heightscreen.width/height值的镜像。(它们在所有浏览器中实际上就是这么做的,即使这个镜像的值不正确。)

媒体查询

  • 意义:度量<html>元素的宽度(CSS像素)或者设备宽度(设备像素)。
  • 完全支持Opera,iPhone,Android,Symbian,Samsung,Iris,Bolt,Firefox,MicroB。
  • 不支持Skyfire,IE,BlackBerry,NetFront,Obigo。
  • 注意我在这里测试的是浏览器是否能从正确的「属性对」获取它们的数据。这些属性对是否提供正确的信息不是这个测试的一部分。
HTML5: 两个viewport的故事(第二部分)

现在哪个度量的尺寸对web开发者更有用?我的观点是,不知道。

我开始认为device-width是最重要的那一个,因为它给我们提供了关于我们可能会使用的设备的一些信息。比如,你可以根据设备的宽度来更改你的布局的宽度。不过,你也可以使用<meta viewport>来做这件事情;使用device-width媒体查询并不是绝对必要的。

 

那么width究竟是不是更重要的媒体查询呢?可能是;它提供了某些线索,这些线索是关于浏览器厂商认为在这个设备上网站应该有的正确宽度。但是这有些模糊不清,并且width媒体查询实际上不提供任何其他信息。

所以我不做选择。目前我认为媒体查询在分辨你是否在使用桌面电脑,平板,或者移动设备方面很重要,但是对于区分各种平板或者移动设备并没有什么用。

或者还有其他用处。

 

事件坐标

这里的事件坐标与其在桌面环境上的工作方式差不多。不幸的是,在十二个测试过的浏览器中只有Symbian WebKit和Iris这两个浏览器能获取到三个完全正确的值。其他所有浏览器都或多或少有些严重的问题。

pageX/Y仍然是相对于页面,以CSS像素为单位,并且它是目前为止三个属性对中最有用的,就像它在桌面环境上的那样。

Event coordinates

  • 意义:见正文
  • 度量单位:见正文
  • 完全支持Symbian,Iris
  • 问题:Opera Mobile在三个属性对中提供的都是pageX/Y的值,但是当你滚动一段距离后就出问题了。
    • 在iPhone,Firefox和BlackBerry上clientX/Y等于pageX/Y。
    • 在Android和MicroB上screenX/Y等于clientX/Y(换句话说,也就是以CSS像素为单位)。
    • 在Firefox上screenX/Y是错的。
    • IE,BlackBerry和Obigo不支持pageX/Y。
    • 在NetFront上三个属性对的值都等于screenX/Y。
    • 在Obigo上clientX/Y等于screenX/Y。
    • Samsung WebKit一直返回pageX/Y。
  • 没有在Opera Mini,Bolt,Skyfire上测试过。
HTML5: 两个viewport的故事(第二部分)

clientX/Y是相对于visual viewport来计算,以CSS像素为单位的。这有道理的,即使我还不能完全指出这么做的好处。

 

screenX/Y是相对于屏幕来计算,以设备像素为单位。当然,这和clientX/Y用的参照系是一样的,并且设备像素在这没有用处。所以我们不需要担心screenX/Y;跟在桌面环境上一样没有用处。

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

 

viewport meta标签

Meta viewport

  • 意义:设置layout viewport的宽度。
  • 度量单位:CSS像素。
  • 完全支持Opera Mobile,iPhone,Android,Iris,IE,BlackBerry,Obigo。
  • 不支持Opera Mini,Symbian,Bolt,Firefox,MicroB,NetFront。
  • 问题:Skyfire不能处理我的测试页面。
    • 如果在Samsung WebKit中对页面应用<meta viewport>,一些其他属性的意义会发生变化。
    • Opera Mobile,iPhone,Samsung和BlackBerry不允许用户进行缩小。

最后,让我们讨论一下<meta name="viewport" content="width=320">;起初它是苹果做的一个扩展,但是与此同时被更多的浏览器所借鉴。它的意思是调整layout viewport的大小。为了理解为什么这么做是必要的,让我们后退一步。

 

假设你创建了一个简单的页面,并且没有给你的元素设置「宽度」。那么现在它们会被拉伸来填满layout viewport宽度的100%。大部分浏览器会进行缩放从而在屏幕上展示整个layout viewport,产生下面这样的效果:

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

所有用户将会立刻进行放大操作,这个是工作的,但是大部分浏览器完好无缺的保持元素的宽度,这使得文字很难阅读。

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

(值得注意的例外是Android WebKit,它实际上会减小包含文字的元素的大小,所以文字就能适配屏幕。这简直太有才了,我觉得所有其他浏览器应该借鉴这个行为。我过阵子将会完整的写一下这个议题。)

 

现在你应该尝试设置html {width: 320px}。现在<html>元素收缩了,并且其他元素现在使用的是320px的100%。这在用户进行放大操作的时候有用,但是在初始状态是没用的,当用户面对一个缩小了的页面这几乎不包含任何内容。

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

为了绕开这个问题苹果发明了viewport meta标签。当你设置<meta name="viewport" content="width=320">的时候,你就设置了layout viewport的宽度为320px。现在页面的初始状态也是正确的。

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

你可以把layout viewport的宽度设置为任何你想要的尺寸,包括device-widthdevice-width会把screen.width(以设备像素为单位)做为其值,并相应的重置layout viewport的尺寸。

 

但这里有一个隐情。有时候正规的screen.width不那么明了,因为像素的数量太大了。比如,Nexus One的正规宽度是480px,但是Google的工程师们觉得当使用device-width的时候,layout viewport的宽度为480px,这有些太大了。他们把宽度缩小为三分之二,所以device-width会返回给你一个320px的宽度,就像在iPhone上一样。

 

如果,像传闻那样,新的iPhone将会炫耀一个更大的像素数量(并不意味着一个更大的屏幕),如果苹果借鉴了这个行为我将不会感到惊讶。也许最终device-width就意味着320px。

 

相关研究

一些相关的主题不得不需要进行更深一步的研究:

  • position: fixed。一个固定的元素,就像我们知道的那样,是相对于viewport来进行定位的。但是相对于哪个viewport?我正在同时做这个研究。
  • 其他媒体查询:dpi,orientation,aspect-ratio。尤其是dpi,那是一个灾难地区,不仅仅是因为所有浏览器都返回96dpi,通常都是错的,也是因为我完全不确定对于web开发者来说哪个值是他们最感兴趣的。
  • 当一个元素比layout viewport/HTML元素宽的时候会发生什么?比如我把一个拥有width: 1500px属性的元素插入到我的测试页面中的一个?这个元素将会从HTML元素中伸出来(overflow: visible),但这意味着实际的viewport可以变得比layout viewport要宽。除了这个以外,旧Android(Nexus One)还会当这个发生的时候放大HTML元素。这是个好主意吗?

(完)

 

本文转自:HTML5: 两个viewport的故事(第二部分)

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    前端大厂最新面试题-html.docx

    Viewport有两个视口:可见视口和视窗视口。Viewport的属性值包括: * width:设置layout viewport的宽度,为一个正整数,或字符串"width-device"。 * initial-scale:设置页面的初始缩放值,为一个数字,可以带小数...

    一步一步开发HTML5 Mobile Apps--Adamlu.pdf

    HTML5移动应用的开发流程大致可以分为两个步骤: 第一步是搭建基础(Boilerplate),包括设置HTML、CSS和JavaScript的基本框架。在这个阶段,开发者需要考虑的关键点有: - HTML部分:使用viewport元标签来控制...

    免费宽屏响应式html5模板-免费 宽屏 响应式 responsive 手机 html5 展示.rar

    这个压缩包包含了两个文件:“README.md”和“免费宽屏响应式html5模板_免费 宽屏 响应式 responsive 手机 html5 展示”。`README.md`通常是项目或资源的说明文件,里面可能包含了模板的安装指南、使用方法、许可...

    H5+JS页面直接查看PDF文件

    3. **加载PDF.js**:在HTML文件中引入PDF.js库,通常包括`pdf.js`和`pdf.worker.js`两个文件。 4. **初始化PDF.js**:在JavaScript中设置PDF.js的全局配置,并加载PDF数据。 ```javascript PDFJS.getDocument(blob...

    html5 css3适用于手机端网站入口引导页模板_html单页模板

    HTML5和CSS3是现代网页开发的两大核心技术,它们在构建手机端网站入口引导页模板中扮演着至关重要的角色。本文将深入探讨这些技术如何应用于创建高效、吸引人的手机端单页网站模板。 HTML5(超文本标记语言第五版)...

    html网页预览pdf

    在这个主题中,我们将探讨如何在HTML页面上实现PDF的预览,重点是`PDFObject`和`PDF.js`这两个工具。 首先,`PDFObject`是一个轻量级的JavaScript库,它允许你在HTML页面中嵌入PDF文件,无需依赖任何其他插件或框架...

    H280_html手机网站_网页源码移动端前端_H5模板_自适应响应式源码.zip

    HTML5是超文本标记语言的第五个主要版本,它在HTML4的基础上增加了许多新功能和元素,强化了网页的多媒体支持,如音频、视频、图形和动画等。此外,HTML5还提供了更好的数据结构和语义,使得网页内容更容易被搜索...

    求两个数组的交集,配合去重方法使用.html

    第二次调用 item = 2 arr2.indexOf(item) !== -1=== arr2.indexOf(2) !== -1 条件成立 会把item添加到新的数组 进行下一次调用 */ // res得到两个数组中交集 [2,2,3,4] var res = arr1.filter(function (item...

    vue H5 查看pdf文件pdfjs

    H5(HTML5)是当前Web标准的一部分,它增强了网页的多媒体功能和离线存储能力。当需要在Vue.js构建的H5应用中查看PDF文件时,可以利用pdf.js库来实现这一功能。pdf.js是由Mozilla开发的一个JavaScript库,专门用于在...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    第二章 多窗口类浏览器设计 11 2.1 多窗口类浏览器需求分析 11 2.1.1 Activity简介 11 2.1.2 Fragment简介 11 2.1.3 多窗口类浏览器需求 12 2.2 多窗口浏览器模式的实现机制 12 2.2.1安卓移动端多窗口浏览器框架 12 ...

    基于HTML5 div+css布局的视频网站,实现视频播放、音乐播放以及图片浏览功能.zip

    通过这两个元素,开发者可以直接在网页上添加视频和音频文件,无需依赖Flash或其他第三方插件。`&lt;video&gt;`元素支持多个源文件(`&lt;source&gt;`),以适应不同的浏览器和格式需求,如MP4、WebM、Ogg等。 2. **CSS3布局**...

    专门为手机用户设计浏览的网页模板Html5+Css3

    Html5是超文本标记语言的第五个版本,相较于之前的版本,Html5引入了许多新特性,旨在增强网页的语义性、可访问性和兼容性。其中,重要的知识点包括: 1. **响应式设计**: Html5提供了`&lt;meta name="viewport"&gt;`标签...

    pdf.js使用文件流预览pdf

    这两个文件分别包含了主库和工作线程代码,它们是PDF.js运行所必需的。 接着,我们需要一个容器来显示PDF内容。在HTML中创建一个`&lt;div&gt;`元素,并为其设置一个ID,例如`"pdfContainer"`,这样我们可以通过JavaScript...

    HTML语言从零到精通.zip

    在&lt;html&gt;内,有两个主要部分和,前者包含元数据(如标题、字符集等),后者包含实际的可见网页内容。 2. **HTML标签**:HTML由各种标签组成,它们以尖括号包围,如、、等。每个标签都有特定的含义,例如定义一级...

    《HTML5与CSS3实战指南》

    - **定义**:HTML5是HyperText Markup Language(超文本标记语言)第五代版本,是用于创建网页的标准标记语言。 - **特点**: - 改善了对多媒体的支持; - 新增了对本地存储的支持; - 增加了新的语义化标签; -...

    html前端js代码pdfjs在线预览pdf兼容ie\chrome

    通常,我们需要在HTML文件中链接到`build/pdf.js`和`build/pdf.worker.js`,这两个文件分别是PDF.js的核心库和工作线程脚本。 接下来,我们需要编写JavaScript代码来加载和显示PDF。以下是一个简单的示例: ```...

    html登录页面代码.rar

    在`&lt;html&gt;`内,有两个主要的部分:`&lt;head&gt;`和`&lt;body&gt;`。`&lt;head&gt;`包含了元信息,如标题,而`&lt;body&gt;`则包含实际可见的内容。 2. **标题元素**:在`&lt;head&gt;`中,`&lt;title&gt;`标签定义了浏览器标签页上的页面标题,这对于...

    前台代发示例

    这里有两个例子: #### 3.1 基础 Panel 示例 ```javascript var obj = { title: "hello", width: 300, height: 200, html: 'Hello, easyjfopensource' }; var panel = new Ext.Panel(obj); panel.render(...

    html文本教程比较简单的

    1. **HTML结构**:HTML文档通常由头部(`&lt;head&gt;`)、主体(`&lt;body&gt;`)两大部分组成,头部包含元信息如字符集、标题等,主体则包含网页的实际内容。 2. **基本元素**:HTML由各种标签构成,如`&lt;p&gt;`表示段落,`&lt;h1&gt;`...

Global site tag (gtag.js) - Google Analytics