[译] 关于两种视口(viewport)的故事:其一

原文地址:http://quirksmode.org/mobile/...css

这篇小短文中,我将会介绍关于viewport与诸如html元素,window 对象,screen 对象这类重要对象在呈现方面的原理。html

本篇讨论桌面浏览器,其目的是为了后续讨论相似的移动端行为提供必定基础。大量web开发者早已凭直觉理解了许多桌面端的概念。可是,在移动端这些概念将变得复杂起来,因此预先对这些咱们熟知的术语进行讨论将有助于你对移动端浏览器行为的理解。web

有关概念之:设备像素与CSS像素

你首先须要理解什么是CSS像素,它与设备像素又有何区别。数据库

设备像素是咱们直觉上认为是“正确”的像素。它能给予一个关于你使用何种设备的正式结论,而且能经过'screen.width/height'得到。浏览器

假设有一个宽为128px的元素,屏幕宽度为1024px。当你最调整合适时,元素会占屏幕的1/8.ide

若是你缩放屏幕,你将获得不一样的结果。假设你将屏幕放大到200%,你的128像素的元素将会占1024像素的屏幕的1/4。布局

缩放在现代浏览器中的应用无非用像素尺寸的变化来实现。这并非说元素的宽度由128增大到256像素,而是像素点变为原来的两倍。形式上,即使元素占了256的设备像素,它依旧只有128的CSS像素。学习

换言之,一个放大到200%的CSS像素点是设备像素点尺寸的四倍。(宽度两倍,高度两倍,整体四倍)。网站

如下图片将更直观的描述这一律念。在一个四像素100%缩放的例子中:CSS像素与设备像素彻底重叠。ui

csspixels_100.gif

如今进行缩小操做,CSS像素尺寸开始缩小,这意味着一个设备像素能够覆盖多个CSS像素。

csspixels_out.gif

若是你进行放大操做,CSS像素尺寸开始扩大,如今一个CSS像素能够覆盖多个设备像素。

csspixels_in.gif

这里的关键点在于CSS像素。它决定了你的样式表的呈现。

设备像素对于你来讲几乎是彻底无用的。当页面不方便阅读时,用户将经过缩放操做来达到温馨的阅读体验。可是,当缩放的水平没法达到你的要求时,浏览器会自动调整CSS布局的放大或缩小。

100%缩放

咱们经过假定一个100%缩放的例子展开话题。是时候给一个略微严格的定义了:

在缩放水平为100%时,一个CSS像素实际上等价与一个设备像素。

这个关于100%缩放的概念对于后续的阐释是很是重要的。但你没必要太过纠结平常的工做,由于在桌面端你的站点一般都是以100%缩放被打开的,即使用户使用了缩放,CSS的像素魔法也会确保样式以相同的比例呈现。

屏幕尺寸

让咱们来关注一些实际的尺寸,首先先从screen.widthscreen.height提及。即用户屏幕的高度与宽度。咱们用设备像素来描述这一尺寸,由于其永远不会变化:注意这是显示器的特性而非浏览器,不要混淆。

desktop_screen.jpg

这看起来至关有趣!但咱们能有这些信息作什么?

事实上,对于咱们屏幕尺寸并没什么卵用。除非你你想要记录它们并在web统计数据库中使用,那么它会有那么点用。

window 尺寸

相反,你须要知道的是浏览器window的内在尺寸。它能反映出用户能使用多少空间来进行CSS布局。你能经过window.innerWidthwindow.innerHeight获取。

图片描述

能够明显看出,window的内部宽度使用CSS像素衡量。你必需要知道你的布局有多少显示在浏览器窗口中,而且当用户放大时它们的尺寸时如何减小的。所以,若是用户进行放大操做时,你在window上的可用空间将会变小而且window.innerWidth/Height也将变小。

(注:这里虽然进行了放大操做,但因为只是每一个css像素点变大(设备宽度无变化)且css的尺寸并无改变,因此能呈如今窗口中的尺寸反而时减少的)

(对于Opera存在例外状况,即当用户进行放大操做时,其浏览器的window.innerWidth/Height并无缩小。这是因为在Opera 使用设备宽度而非CSS宽度衡量。这在桌面端无关痛痒,但在移动端确实致命的,咱们将在稍后进行讨论。)

desktop_inner_zoomed.jpg

滚动偏移(offset)

window.pageXOffset与window.pageYOffset用来衡量文档中垂直与水平方向上的偏移量。所以,经过这它们你能够获取用户页面的此刻的滚动状况。

desktop_page.jpg

它们也是经过CSS像素衡量的。不管是否处于放大状态,你均可以经过其来获取文档被向上滚动的状况信息。

理论上讲,若是用户向上滚动页面而且进行放大操做,window.pageX/YOffset将会变化。但浏览器默认会保持页面先后一致,即在用户放大时保证同一元素出如今页面顶部可见区域。虽然,这并不老是奏效,但这意味着实践中window.pageX/YOffset并不真的须要变化。

desktop_page_zoomed.jpg

视口(viewport)的概念

在咱们继续讨论更多JS属性前,让咱们先学习另外一个概念视口(viewport)。

视口(viewport)的做用是限制<html>元素,<html>元素是全部网页块元素中最高一级的元素。

这可能听着有点晕,因此举一个实际的例子。假设在一个流式布局中,你其中一个边栏的宽度是10%。如今当你改变浏览器宽度时,边栏会一致的缩放。那么问题来了,他到底是如何工做?

原理上说,当你给sidebar一个10%的宽度,实际上它得到了父级宽度的10%。让咱们来考察一下(你并无设定宽度的)body元素。那么问题来了,body元素的宽度是多少?

一般,全部块级元素的宽度都会等于父元素(这里有些特例,但不要在乎细节)。因此<body>元素与其父级<html>元素等宽 element。

那么<html>元素的宽度又如何?为什么他与浏览器窗口等宽?因为与浏览器窗口等宽,这也就是为何你设置边栏宽度为10%他就占据了整个浏览器宽度的10%。这是一条全部的web开发人员感性上承认并使用的原理。

你不知道的只是在理论上,这条原理如何实现。理论上,<html>元素的宽度被视口限制。而<html>元素占据了100%的视口宽度的。

视口宽度又正好等于浏览器宽度:就是这么定义的。视口并不是一个HTML结构,其不受CSS控制。在桌面端,其与浏览器窗口长宽一致。但在移动端状况略微复杂。

结论

在这种状况下会有许多有趣的现象,用这个页面你能够观察到其中的一个现象。滚动到顶部,放大一到两次,这样内容区域就溢出窗口了。

如今当你向右滚动时,会发现顶部蓝色区块并非充分填充的。

desktop_htmlbehaviour.jpg

正是由于咱们将视口定义成如此,才形成了这种现象。咱们定义了蓝色区块的宽度为100%。那到底是什么的100%?是<html>元素的100%,<html>元素是和视口等宽的,也是和浏览器窗口等宽的。

重点是:上诉结论是在100%缩放的条件下成立的。如今在放大的状况下,视口宽度将会小于网站的宽度。这对于元素自身影响不大,但对于元素的内容则会溢出<html>元素,而且元素具备overflow: visible属性,这意味着溢出的内容在任何状况下都会被显示。

不过蓝色区块并无溢出。已经将其宽度设为100%,毕竟,浏览器要遵照视口的宽度设定,而非关心当下宽度是否过于狭小。

desktop_100percent.jpg

文档宽度?

咱们真正须要只晓得是页面内容区域的真实宽度(包括延伸的部分)。但据我所知不可能得出这个值(固然若是你能计算出页面中全部元素独自的狂高,但请你牢记,这极容易出错)。

我开始相信我门须要一组JS属性对来获取被咱们称之为“文档宽度”的值。(固然是以CSS像素为单位)

desktop_documentwidth.jpg

若是我门真的自我感受时尚,何不将该值引入CSS?我更愿意让蓝色区块基于文档宽度的100%,而不是<html>元素。(这确是一个难题,即使,若是不能实现我也不会感到惊讶)

浏览器厂商们,大家怎么认为的?

度量视口

你也许会想获取视口的值,能够经过document.documentElement.clientWidth-Height得到。

desktop_client.jpg

若是你熟悉DOM,你就会知道document.documentElement其实是<html>元素(HTML文档的根元素)。然而,能够这么说视口比它(<html>元素)要高一级,它包含了<html>元素。若是你给<html>元素设置了宽度,这会生效。(虽然这可行,但我并不推荐)

在此状况下document.documentElement.clientWidth-Height仍旧给出视口尺寸而非<html>元素尺寸。(这是一个奇特的规则只有在documentElement元素的这个属性对才起做用,在其余例子中使用的仍是实际宽度。)

desktop_client_smallpage.jpg

因而document.documentElement.clientWidth-Height老是给出视口尺寸不论<html>元素的宽度如何。

两对属性对

另外,视口的尺寸也能由window.innerWidth/Height获取?这样的说法也对也不对。

这二者的正是区别就在于:document.documentElement.clientWidth-Height不把滚动条计算在内,而window.innerWidth/Height则将滚动条计算在内。这算是一些细枝末节的概念了。

实际上这二者是浏览器争霸时代的产物。当时,Netscape 只支持window.innerWidth/Height而IE系列只支持document.documentElement.clientWidthHeight。从那时起,全部其余浏览器开始支持document.documentElement.clientWidthHeight,但IE依旧不支持window.innerWidth/Height

在桌面端上拥有两个属性对是有一些累赘,可是咱们即将看到的,在移动端这是多么大的福音。

度量<html>元素

咱们已经知道,经过clientWidth/Height能够在任意状况下获取视口尺寸。那么如何获取<html>元素尺寸?经过document.documentElement.offsetWidthHeight

desktop_offset.jpg

该属性为你提供一个方法去获取块级<html>元素的宽高。若是你设置了一个宽度,offsetWidth将会从新计算。

事件坐标

下面让咱们谈谈事件坐标。当一个鼠标事件产生,有很多于五种属性能够为你提供关于事件确切位置的信息,在咱们的讨论中,如下三种是比较重要的:

  1. pageX/Y 提供以CSS像素度量的相对于<html>元素的位置信息
    desktop_pageXY.jpg

  2. clientX/Y 提供以CSS像素度量的相对于视口的位置信息
    desktop_clientXY.jpg

  3. screenX/Y 提供以CSS像素度量的相对于屏幕的位置信息
    desktop_screenXY.jpg

90%的情形你在使用pageX/Y,你一般发生在你想要知道发生事件的地点相对文档的位置。而另外10%的情形,你会用到clientX/Y。你基本不会须要处理事件想对于浏览器位置的情形。

媒体查询

最后来谈谈媒体查询吧。这是一个很是简单的概念:由你定义一个特殊的CSS规则,仅在页面大于,等于,或小于某一特定的值时生效。例如:

div.sidebar {
    width: 300px;
}

@media all and (max-width: 400px) {
    // styles assigned when width is smaller than 400px;
    div.sidebar {
        width: 100px;
    }

}

目前,sidebar的宽度时300px,但当宽度低于400px,sidebar的宽度将变为100px。

那么问题来了:我门以哪一个宽度做为基准?

存在两个相关的媒体查询:width/heightdevice-width/device-height

width/height使用与documentElement.clientWidth/Height相同的值 (即视口的宽度)。使用CSS像素宽度。
device-width/device-height使用与screen.width/height相同的值 (即设备的宽度)。使用设备像素宽度。

desktop_mediaqueries.jpg

那我门应该使用哪个?那还用问,固然是width。web开发者历来对设备宽度不来电,他们衷情于浏览器宽度。

所以,在桌面端忘记device-width/device-height拥抱width/height吧。我门将会看到在移动端状况变的复杂起来。

结论

本文是对桌面端浏览器行为的初步探索。

注:翻完发现已经有翻译版了,质量也不错,连接给上

相关文章
相关标签/搜索