Viewport那些事(一)

来源:互联网 发布:全景图像拼接算法 编辑:程序博客网 时间:2024/05/01 04:03
这段时间一直在看viewport相关的内容,打算写一个小系列,前两篇是翻译的网上一个写得很不错的viewport文章,主要介绍viewport的基本概念,相关的javascript结构。

概念:设备像素和CSS像素

     需要了解的第一个概念是CSS像素,以及它和设备像素之间的区别。
     设备像素由你的设备决定,并且可以通过screen.width/height来获取。
     如果有一个width:128px的元素,你的设备是1024px宽,并且你最大化你的浏览器窗口,这个元素会占据你设备的八分之一大小。如果用户进行缩放,那么计算会发生变化。如果用户缩放到200%的大小,width:128px的元素将会充满设备的四分之一。
     换句话说,缩放200%使一个CSS像素增长到四个设备像素的大小。
     一些图片可以说明这个概念,这里是缩放为100%时的四个像素,CSS像素完全覆盖在设备像素之上。
           
     现在我们缩小,CSS像素开始收缩,意味着一个设备像素现在重叠了几个CSS像素。
         
     如果你放大,CSS像素开始增长,现在一个CSS像素覆盖了几个设备像素。

100%缩放
     
     可以明确地给出如下定义


在缩放率为100%的级别上,一个CSS像素等价于一个设备像素。


Screen大小
     来看看一些实用的尺寸。我们从screen.width和screen.height开始。他们表示用户屏幕的总宽度和高度。这些尺寸以设备像素为单位,因为它们永远不会改变,是物理设备而非浏览器的一个特性。

     事实上,Screen的大小对网页开发者来说并不重要

Window大小
     相反地,网页开发者最想知道的是浏览器的窗口大小。它能确切地告诉用户当前有多少可用的空间来布局。可以通过window.innerWidth和window.innerHeight属性来获取。                  
     显然,这些尺寸都是以CSS像素为单位的。所以如果用户放大网页,那么你在窗口中就会有更小的可用空间,window.innerWidth/Height对应的也会减少。
      (原文提到Opera是一个意外,它的window.innerWidth/Height是以设备像素为单位的,即不会随着缩放比例的改变而改变,但是我在测试最新版的Opera时这个问题已经得到了修复)
     
Scrolling offset
     window.pageXOffset和window.pageYOffset,表示文档水平和垂直方向的滚动偏移。
     
     这些尺寸同样也是以CSS像素为单位。网页开发者想要知道的是文档已经滚动了多少,和具体的缩放比例无关。
     理论上说,如果用户滚动之后再进行了缩放操作,window.pageX/YOffset会发生变化。然而,浏览器通常都会试图在用户缩放是保持同样的元素在可视的页面顶部,这个功能通常并不是很完美,但是这意味着实际上滚动之后再缩放时,window.pageX/YOffset可能不会发生改变。
     
概念:viewport
     viewport的功能是限制<html>元素,网页中最顶层的容器。
     假设你有一个页面布局,其中一个侧边栏具有属性width:10%。那么这个侧边栏会随着你调整窗口的大小对应地增大或者缩小。
     技术上说,侧边栏以从它父亲获取的宽度的10%作为自己的宽度,我们假定是从<body>元素,那么问题就是<body>的宽度从哪里来?
     正常地,所有块元素具有它父亲宽度的100%的宽度(忽略一些特殊情况)。那么<body>就和它的父亲,<html>元素一样宽。
     那么<html>元素的宽度又是怎么来的咧?它和浏览器的窗口一样款。这就是为什么width:10%的侧边栏会占据整个窗口大小的10%的原因。
     理论上,<html>元素的宽度受viewport的宽度的限制。
     对于桌面浏览器来说,它就是切好等于浏览器的窗口。viewport并不是一个HTML结构,所以无法通过CSS来影响它。对于桌面浏览器来说,它具有和浏览器窗口一样的宽度和高度。在移动设备上会稍微复杂一点。

现象
     将原文的网页缩放几级让网页内容超出浏览器窗口,然后横向滚动一点,你会发现顶部蓝条这时候没有再排满整个页面。
 
     这种现象是由于viewport的定义导致。这个蓝条的宽度为width:100%。也就是和<html>元素一样宽,即和浏览器窗口一样宽。
     关键点是:蓝条的内容溅出了<html>元素,但是因为该元素具有overlfow:visible属性(默认值),意味着它的内容总会被显示。
     但是蓝条本身并没有溅出。它的宽度为width:100%,所有的浏览器都会遵循规则给他viewport的宽度,而不去理会窗口是否过窄。
文档宽度
     网页开发者通常想知道的是网页的整个内容导致有多宽,包括在外面的部分。目前据我所知无法获取这个宽度。
     
(如原文作者所说,w3c标准中并没有定义这么一个属性,但是Webkit浏览器支持通过document.width来获取这个宽度,而firefox和opera没有提供支持,document.width最早是ie定义的属性,它被定义于等于document.documentElement.clientWidth的宽度,后来被废弃,而chrome恰好用来表示文档的宽度,但是要注意和ie最初的定义的意思不一样)
     
Viewport的尺寸
     我们可以通过document.documentElement.clientWidthHeight来获取viewport的尺寸
     
     如果你熟悉DOM,你知道document.documentElement实际上就是<html>元素:任何HTML文档的跟元素。然而,viewport可以认为是更高的一层;可以认为是一个包含<html>元素的元素。
     有种情况,当你给了<html>元素一个宽度时(不推荐这么做,但是有这种可能),这时候document.documentElement.clientWidth 和 Height仍然返回的是viewport的大小,而不是<html>元素的(这是一种特殊情况,仅针对这一个元素的这一对属性,其它元素都使返回元素的宽度)。
   
     所以,document.documentElement.clientWidth 和 Height总是返回viewport的尺寸,而和<html>元素的尺寸没有关系。

两对属性
     但是,window.innerWidth/Height是否总是返回viewport的尺寸?答案是不确定的。
     这两对属性的区别的官方解释是:document.documentElement.clientWidth 和 Height没有包含滚动条的宽度,而window.innerWidth/Height包含了滚动条的宽度。
     事实上,这两对属性是浏览器大战时的遗留产物。那时,Netscape只支持window.innerWidth/Height而IE仅支持document.documentElement.clientWidth 和 Height。后来所有其他浏览器都开始支持clientWidth/Height,但是IE没有放弃window.innerWidth/Height。
     这两对定义相似属性对桌面浏览器来说比较讨厌,但是后面我们会看到对于移动浏览器来说确实一种福音。

<html>元素的尺寸

     由于clientWidth/Height在任何情况下都使返回viewport的尺寸。但是我们从哪里获取<html>元素自己的尺寸呢?它们被放在document.documentElement.offsetWidth 和 Height里了。
 

     这两个属性真实地反映了<html>元素的大小,如果你设置width给<html>,offsetWidth会相应的改变。

     

事件坐标
  1. pageX/Y,返回相对于<html>元素的坐标,以CSS像素为单位。
  2. clientX/Y, 返回相对于viewport的坐标,以CSS像素为单位。
  3. screenX/Y, 返回相关与屏幕的坐标,以设备像素为单位。

Media queries
     
  1. width/height使用和documentElement.clientWidht/Height(换句话说就是viewport)一样的值,以CSS像素为单位。
  2. device-width/device-height使用和screen.width/height(屏幕大小)一样的值,以设备像素为单位。


原文:http://www.quirksmode.org/mobile/viewports.html 

原创粉丝点击