译—— a tale of viewport2

这一页我们将讨论移动浏览器。如果您对移动设备完全陌生,我建议您首先阅读第一部分关于桌面浏览器的内容,以便在熟悉的环境中做好准备。

移动浏览器的问题

移动浏览器和桌面浏览器比较,最明显的差异是屏幕大小。移动浏览器如果要显示桌面优化网页,要么字体会缩小到无法阅读,要么只能显示网页的一部分。

移动设备屏幕要比桌面小得多,最大的宽度大概是400px,有些还要更小一些。(有些手机声称更大一些的尺寸,但是他们在说谎——或至少给了我们无用的信息)

作为中间层的平板电脑例如iPad等,弥补了台式电脑和手机支架的差距(让差距显得不突兀吧),但是这么有改变根本性问题。网站依然需要在手机设备上运行,我们需要让其在小屏幕上良好显示。

最重要的问题集中在CSS上,特别是viewport(视口)的大小。如果在移动设备上直接使用桌面网页,CSS将会出现严重错误。

让我们回到之前的一个例子,侧边栏宽度width:10%。如果移动浏览器同桌面浏览器一样运行,侧边栏的宽度大概是40px,这是在太窄了。流布局被严重压缩。

一个解决办法就是针对移动浏览器重新构建一个特殊的网站。抛开是否应该这么做来解决根本问题,实际上能有多少网站提供专门针对于移动设备的网站。

移动浏览器供应商想要给用户提供最好的体验,需要做的就是“尽可能跟桌面网页类似”。如果想要做到这样,就必须耍些花招。

两个viewport

对于你的CSS布局来说,目前的viewport太窄了。明显的解决办法就是让viewport更宽些。为了这个目的,需要将viewport分为两个种类:the visual viewport 和the layout viewport。

George Cummins在Stack Overflow上对基本概念做了最好的解释:

Imagine the layout viewport as being a large image which does not change size or shape. Now image you have a smaller frame through which you look at the large image. The small frame is surrounded by opaque material which obscures your view of all but a portion of the large image. The portion of the large image that you can see through the frame is the visual viewport. You can back away from the large image while holding your frame (zoom out) to see the entire image at once, or you can move closer (zoom in) to see only a portion. You can also change the orientation of the frame, but the size and shape of the large image (layout viewport) never changes.

将布局视图端口想象成一个不改变大小或形状的大图像。再想象你有一个相框,可以通过相框看到那幅大图像。相框外周都是不透明的,只有通过中间部分可以看见图像。可以透过相框看到的那部分就是the visual viewport(可视窗口)。你可以拿着相框后退距离图像远一点,就可以看到整个图像。也可以距离更近一些,只看图像的一部分。图像的大小和形状(the layout viewport)并不会发生任何改变。

(可以去看原文,其实英文挺直观的。并且还有作者引用的其他解释)

the visual viewport(可视窗口)是当前显示在屏幕上的页面的一部分。用户可以通过滚动操作移动去查看页面的其他部分,也可以缩放改变the visual viewport (可视窗口)的大小。

然而,CSS布局,特别是百分比宽度,是根据layout viewpor(布局视图)t计算的,它比visual viewport宽得多。

<html>元素最初会采用layout viewport的宽度,css将会被解释为当前屏幕比手机屏幕宽得多。这可以确保你的站点布局和桌面布局一致。

layout viewport到底多宽呢?每个浏览器都不一样。Safari Iphone使用980px,Opera使用850px,Android Webkit是800px,IE是974px。

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

  • Symbian Webkit试图让layout viewport和visual viewport一致,这会让百分比宽度表现的很奇怪。但是,如果页面由于绝对宽度不适合vidual viewport(可视视图),浏览器会将布局视图扩展到最大850px。
  • samsung webkit 使layout viewport跟最宽的元素的宽度一致。
  • BlackBurry的layout viewport和100%缩放的visual viewport一致,并且不会改变。

缩放(zooming)

显而易见,两个viewport都是CSS像素单位。但是当visual viewport随着缩放改变时(如果放大,屏幕显示的CSS像素就会减少),layout viewport始终保持不变。

理解layout viewport

为了理解layout viewport 的尺寸先来看一下当页面完全缩小的时候发生了什么。许多移动浏览器最初以完全缩小模式显示任何页面。

重点是:浏览器选择了layout viewport的大小以致于它以完全缩小的模式覆盖屏幕(因此同visual viewport 一致)

 因此,layout viewport的宽高等于以最大缩小模式显示在屏幕的内容的宽高。即使用户放大,也不会发生改变。

layout viewport总是保持不变。当你旋转你的手机,visual viewport发生改变,但是浏览器适配器会适当放大使得layout viewport和visual viewport一样宽。

这对layout viewport的高度有影响,layout viewport的高度大大低于竖屏模式。但是web开发人员并不关心高度,只关心宽

测量layout viewport

现在有了两个viewport尺寸需要测量。非常幸运的是,浏览器大战给了我们两对属性。

document.documentElement.clientWidth/Height表示layout viewport的大小。

方向与高度有关,但与宽度无关。

 

测量visual viewport

至于visual vireport,可以通过window.innerWidth/Height获得。很显然,当用户进行缩放时,这个数值会发生变化,使更多或者更少的CSS像素适合屏幕。

不幸的是,这是一个没有完全兼容的领域。许多浏览器仍然需要添加对测量visual viewport的支持。但是,没有浏览器将此测量存储在任何其他属性对中,我猜测window.innerWidth/Height是一个标准,尽管支持力度不够。

window.innerWidth/Height

Meaning
    Visual viewport dimensions
Measured in
    CSS pixels
Full support
    iPhone, Symbian, BlackBerry
Problems
    Opera and Firefox return the screen width in device pixels.
    Android, Bolt, MicroB, and NetFront return the layout viewport dimensions in CSS pixels.
Not supported
    IE, but it gives the visual viewport dimension in document. documentElement. offsetWidth/Height.
    Samsung WebKit reports either the dimensions of the layout viewport or of the <html>, depending on whether a <meta viewport> tag has been applied to the page or not.
Gibberish
    Iris, Skyfire, Obigo

 

屏幕(the screen)

就像在桌面,screen.width/height给出屏幕的大小,使用设备像素。如同桌面一样,作为web开发者,不需要知道这个信息。您感兴趣的不是屏幕的物理大小,而是它当前适合多少CSS像素。

screen.width and screen.height

Meaning
    Screen size
Measured in
    Device pixels
Full support
    Opera Mini, Android, Symbian, Iris, Firefox, MicroB, IE, BlackBerry
Problems
    Opera Mobile on Windows Mobile only gives the landscape size. Opera Mobile on S60 gets it right.
    Samsung WebKit reports either the dimensions of the layout viewport or of the <html>, depending on whether a <meta viewport> tag has been applied to the page or not.
    iPhone and Obigo only give portrait sizes.
    NetFront only gives landscape sizes.
Gibberish
    Bolt, Skyfire

 

缩放级别

不可能直接读取缩放级别,但是分割screen.width和window.innerWidth得到。问题是如果这两个属性对都得到完全的支持才可以。

幸运的是缩放级别并不重要。你需要知道的是,屏幕适合多少CSS像素。可以从window.innerWIdth获取I信息——如果它被正确支持。

滚动偏移量

如果需要知道相对于layout viewport当前页面的位置。也就是滚动偏移量,跟桌面一样,存在window.pageX/YOffset中。

window.pageX/YOffset

Meaning
    Scrolling offset; which is the same as the visual viewport’s offset relative to the layout viewport.
Measured in
    CSS pixels
Full support
    iPhone, Android, Symbian, Iris, MicroB, Skyfire, Obigo.
Problems
    Opera, Bolt, Firefox, and NetFront always return 0.
    Samsung WebKit reports correct values only if a <meta viewport> is applied to the page. 
Not supported
    IE, BlackBerry. IE stores the values in document. documentElement. scrollLeft / Top

html元素

和桌面一样,document.documentelement.offsetWidth/Height给出了以CSS像素为单位的<html>元素的总大小。

document. documentElement. offsetWidth / Height

Meaning
    Total size of the <html> element.
Measured in
    CSS pixels
Full support
    Opera, iPhone, Android, Symbian, Samsung, Iris, Bolt, Firefox, MicroB, Skyfire, BlackBerry, Obigo.
Problems
    NetFront’s values are only correct at 100% zoom.
    IE uses this propery pair to store the dimensions of the visual viewport. In IE, see document. body. clientWidth/Height for the correct values.

媒体查询

媒体查询和桌面查询相同。width/height使用layout viewport作为参考,使用CSS像素作为单位。device-width/height采用设备屏幕,设备像素作为单位。

换句话说,width/height反映的是document.documentElement.clientWidth/Height的值。device-width/height反映的screen.width/height的值。(它们实际上在所有浏览器中都这样做,即使反映的值可能不正确。)

所以到底哪个数值对于开发是有用的呢。其实我也不知道

我开始认为device-width是最重要的,因为它给的是设备的信息,我们可能会需要这个信息。例如,可以改变布局的宽度以适应设备的宽度。不过,您也可以使用<meta viewport>;使用device-width的媒体查询并不是绝对必要的。

那么,width到底是不是更重要的媒体查询呢?也许;它提供了一些线索,关于浏览器供应商认为什么是该设备上一个网站的良好宽度。但这是相当模糊的,宽度媒体查询实际上没有提供任何其他信息。

所以我犹豫不决。就目前而言,我认为媒体查询对于判断您是在台式机、平板电脑还是移动设备上非常重要,但对于区分不同的平板电脑或移动设备并不是非常有用。

事件坐标

事件坐标或多或少与桌面坐标相同。不幸的是,在12个经过测试的浏览器中,只有两个,即Symbian WebKit和Iris,完全正确地实现了这三个功能。所有其他浏览器都有或多或少的严重问题。

pageX/Y依然是相对于页面坐标,使用的是CSS像素。这是目前三对属性中最有用的信息,跟桌面一样。

clientX/Y是相对于visual viewport的坐标,使用的是CSS像素单位。这是有道理的,尽管我不完全确定它有什么好处。

screenX/Y是相对于屏幕的,使用的是设备像素单位。当然,当然,这是clientX/Y使用的相同参照物,设备像素是无用的。所以我们不需要担心screenX/Y,它和在桌面一样毫无用处。

meta viewport

最后,来讨论<meta name="viewport' content="width=320">;最开始是苹果手机的扩展,现在已经在其他浏览器广泛使用。它的意思是调整layout viewport。为了理解这个操作的必要性,先回退一步。

如果你构建了一个简单的页面,并且没有给任何元素宽度。他们会拉伸到l填充layout viewport。大多数浏览器多会缩小使得能够在页面上显示整个layout viewport,效果如下图

所有用户都会立即放大,这是可行的,但大多数浏览器保持元素的宽度不变,这使得文本难以阅读。

(Android WebKit是一个显著的例外,它实际上减少了包含文本的元素的大小,使它们适合显示在屏幕上。这非常棒,我觉得所有其他浏览器都应该复制这种行为。稍后我会详细记录下来。)

现在,你设置<html>的宽度width:320px。现在,<html>元素缩小了,所有其他元素也缩小了,它们现在占用了320px的100%。这在用户放大时有效,但在最初,当用户面对一个放大后的页面,整个页面大包含大部分空白。

为了解决这个问题,苹果发明了meta viewport标签。当您设置<meta name="viewport" content="width=320">时,您将布局viewport的宽度设置为320px。现在页面的初始状态也是正确的。

你可以设置layout viewport为任何值,可以是device-width。device-width采用screen.width作为参考,并且可以响应调整layout viewport。

不过这里有个陷阱。有时候screen.width没有多大意义,以为像素值太高了。比如,Nexus One的正式宽度为480px,但是谷歌的工程师认为,当使用device-width时,将layout viewport的宽度设置为480px实在是太大了。他们缩小它至三分之二。所以device-width变为320px,就像在iPhone上一样。

如果真的像传言的那样,新款iPhone的像素会更大(这并不一定意味着屏幕更大!)也许最终设备的宽度就是320像素。

结论

结论其实和桌面浏览器差不多,但是由于移动浏览器对于许多属性对没有完全支持,移动设备有很多种,使得在移动设备上实现良好的布局比较不容易。

  • screen.width/height,设备的屏幕尺寸。

  • window.innerWidth/Height,包含滚动条尺寸的浏览器完整尺寸。

  • document.documentElement.clientWidth/Height,viewport 的尺寸。

  • document.documentElement.offsetWidth/Height<html>的尺寸。

  • window.pageX/YOffset,页面的移位。

  • window.pageX/Y,从<html>原点到事件触发点距离。

  • window.clientX/Y,从 viewport 原点(浏览器窗口)到事件触发点的距离。

  • window.screenX/Y,从用户显示器窗口原点到事件触发点的距离。

参考

  1. 原文
posted @ 2019-05-23 16:57  Jamie0327  阅读(135)  评论(0编辑  收藏  举报
levels of contents