什么是 Viewport,为什么需要 Viewport:
Viewport:视口,视觉窗口,显示区域。
在显示面积上手机屏幕相对桌面显示器要小很多,在几年前(现在也如此)大部分网站都是为桌面显示器浏览而设计,很少考虑到适应手机屏幕,所以如果用手机浏览大多网站时会出现问题,比如常见固定宽度的网页会出现横向竖向滑动条,当然这不算什么大问题;但如果是浏览流动布局的网页那情况会非常糟糕,设想一个宽度为 30% 的侧边栏对于 320px 手机屏幕而言也就 96px,只能容纳八个 12px 的汉字,可阅读性非常差。
为了让手机也能获得良好的网页浏览体验,Apple 找到了一个办法:在移动版的 Safari(iOS平台)中定义了 viewport meta 标签①,它的作用就是创建一个虚拟的窗口(viewport),而且这个虚拟窗口的分辨率接近于桌面显示器,Apple 将其定位为 980px②。
以一代 iPhone 下的 Safari 来说就是:
在 iPhone 的 320px 物理屏幕上——视觉窗口(visual viewport),创建出了一个 980px 的虚拟窗口——布局窗口(layout viewport),在视觉窗口(visual viewport)中我们可以拖动横向竖向滑动条或者放大缩小网页,来达到最佳的浏览效果(类似桌面浏览器);而布局窗口(layout viewport)用来配合 CSS 渲染布局,例如当我们设置一个容器的宽度为 100% 时,这个容器的实际值为 980px 而不是 320px。如此一来大部分网页就能以缩放的形式正常的显示在手机屏幕上了。
如何设置 Viewport
有了 layout viewport似乎解决手机浏览网页的难题,但如果遇到专门为手机优化的网页就又有新的问题:
是的,因为 iPhone 的 layout viewport默认为 980px,导致专为其优化的 320px 宽的页面只能以缩放的方式显示,这时就需要对 viewport 进行设置:
<head>
...
<metaname="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no"/>
...
</head>
这个是最常见的一条 viewport meta 代码,将 viewport 定义为:宽度为设备宽度,初始缩放比例为 1 倍,禁止用户缩放。设置好后我们的页面就显示完美了:
<meta name="viewport"
content="
height = [pixel_value | device-height] ,
width = [pixel_value | device-width ] ,
initial-scale = float_value ,
minimum-scale = float_value ,
maximum-scale = float_value ,
user-scalable = [yes | no] ,
target-densitydpi = [dpi_value | device-dpi |
high-dpi | medium-dpi | low-dpi]
" />
viewport 全部属性&值如下:
width: viewport宽度
height: viewport高度
initial-scale: 初始缩放比例
maximum-scale: 最大缩放比例
minimum-scale: 最小缩放比例
user-scalable: 是否允许用户缩放
例:
width=960 或 device-width
height=1000 或 device-height
initial-scale=0.5
maximum-scale=2
minimum-scale=1
user-scalable=1 或 0 (yes 或 no)
layout viewport的默认值
在Apple实现viewport后,其他浏览器也加入了对viewport meta的支持,但彼此间还是有些差异,差异最大的是layout viewport的表现:
Safari iPhone:980px
Opera: 850px
Android WebKit: 800px
IE: 974px
最后关注下 width=device-width
其实这个属性&值很有意思,字面意应该是 viewport 宽度等于设备宽度,但在实际中不同的浏览器都给出了个定值:320px;这个值还是源于 Apple,因为早期 iPhone 的分辨率为 320px × 480px,大量为 iPhone 量身定制的网站都设置了width=device-width,并且按照宽度 320px 来设计制作,所以其他浏览器加入 viewport 支持时为了兼容性也将 device-width 定义为了 320px。
<meta name="viewport"content="width=device-width,target-densitydpi=high-dpi,initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
最初执行viewport meta加入如下
<metaname="viewport" content="width=device-width,initial-scale=1.0">
编译过程会转化成如下的语意,
@viewport {
width: device-width;
initial-scale:1.0
}
基本说明
width=device-width
先提一下几个注意的地方,首先在viewport里面的width通常会看到设定为device-width ,主要是为了让整个页面宽度与手机可视宽度相同,如此就可以简单相容于不同机型萤幕大小,如果这边width没有设定的话,就会依照html css给予的width当作预设值。
因为解析度不同,device-width有时候不一定是view width ,所以在类似iphone 4高解析度机器上,device-width=320,可是实际解析度为480,这时候就需要利用javascript针对UA下去做动态调整。user-scalable 从属性名称来看就是允许开启、关闭的设定,使用者能否放大、缩小页面,如果页面不允许手机使用者缩放,就直接设定为0,或者no,反之要启动缩放功能,给予1或者是yes。接下来将说明几种常用的方式,以及测试验证提供给大家参考。基本宽度(并不是指html body width),
注解
①除此之外不同移动浏览器厂商也有不同的解决方案,例如 UCweb 就是使用中间件技术。
②不同的浏览器厂商对于 layout viewport的大小定义不同,详见”layout viewport的默认值”。
参考文章:
http://dev.w3.org/csswg/css-device-adapt/
http://www.quirksmode.org/mobile/viewports2.html
https://developer.mozilla.org/en/Mobile/Viewport_meta_tag
http://blogs.msdn.com/b/iemobile/archive/2010/11/22/the-ie-mobile-viewport-on-windows-phone-7.aspx
Media queries &Viewport
解决问题的关键就是Media queries和Viewports。下面的内容是关于如何最好的使用Media queries和Viewports的。但是我并不会深入的讲怎样增强响应的细节,如果感兴趣,可以查看这篇博文的最后一部分:“参考文章”。
● @media queries
作为一个网页设计师或前端开发者,我们希望我们的网页总能很容易的自适应不同的设备和屏幕尺寸,不管我们用户使用的是21″台式显示器,13″笔记本电脑,10″的iPad或者更小的智能手机。响应式网页设计使用@media queries根据浏览器的宽度和CSS来改变页面的布局。我们可以这样使用的CSS:
1. /* Default wide-screen styles */
2. @media all and (max-width: 1024px) {
3. /* styles for narrow desktop browsers andiPad landscape */
4. }
5. @media all and (max-width: 768px) {
6. /* styles for narrower desktop browsersand iPad portrait */
7. }
8. @media all and (max-width: 480px) {
9. /* styles for iPhone/Android landscape(and really narrow browser windows) */
10. }
11. @media all and (max-width: 320px) {
12. /* styles for iPhone/Android portrait */
13. }
14. @media all and (max-width: 240px) {
15. /* styles for smaller devices */
16. }
是的,我们可以设置更小的width,或者中间尺寸。我待会再讨论。CSS media queries是非常强大和复杂的,在这里不想过多的讨论,因为上面的代码已经足够应付响应式Web设计了。如果你想要知道更多关于Media Queries的细节,请阅读参考文献里的相关文章。
● viewports
现在,当我们调整我们浏览器的大小时,上面的代码已经可以非常不错的完成工作了。但这并不能满足移动端的浏览器。原因是移动端浏览器(iPhone/Safari, Android/Chrome和Fennec)会默认页面是为宽屏幕设计的,所以将它缩小整个页面来适应小屏幕。这就表明了上面的代码完全不足于适应移动端的浏览器,因为设备无法识别正确的宽度。解决方法:在文档的头部使用苹果提供的viewport meta标签,并结合@media queries:
1. <meta name="viewport"content="...">
以上的代码中,content为空,因为我觉得有必要详细讲一下,而不是直接给出来,这样我们就能更清楚的记住,并且知道content里应该填些什么,并且为什么这样填
● width=device-width
我们看见很多网站都建议把content属性的值设置为width=device-width。这相当于告诉浏览器将页面宽度假设为设备宽度。不幸的是,只有当设备是纵向时假设才是正确的。当我们把设备旋转成横向时,device-width还是和纵向的一样(比如,320px),这意味着,即使我们把页面设计成适应了480px横向设备,它还是会返回320px的效果。
曾经尝试在media query里使用orientation来解决这个问题,但是orientation不会真正的告诉我们实际的设备宽度,因为它只告诉我们设备的宽度是大于还是小于设备的高度。正如有人指出,由于大部分网页往往垂直滚动,所以这是无关紧要的。
如果我们的页面在纵向和横向设备中样式相同,那么我们就可以用width=device-width就足够了,需要注意的是这个是唯一告诉android设备使用设备宽度的方法。
● initial-scale=1.0,maximum-scale=1.0
initial-scale=1设置告诉浏览器初始化页面时不要对页面进行缩放。解决了没有使用viewport时出现的页面缩放问题。但还是有 bug,当我们把移动端设备从纵向转成横向时,你就会发现这个问题了。这是因为initial-scale只在页面完全加载后有作用。在我们把移动设备从纵向转成横向的过程中,浏览器就会认为页面不变,但scales会设置为1.5,为了使320px的页面适应480px。但是,因为我们在@media queries中设置了480px这个宽度,那么页面CSS规则也会是适应480px的。结果就是,页面CSS规则是适应480px的,另外scale还是1.5。这个结果并不可怕,但是不可取。
为解决这个bug,我们可以添加maximum-scale=1这个设置。它的作用是阻止页面在旋转时放大,但它同时带来了更严重的问题:也阻止了用户手动放大或缩小页面。同样user-scalable=no设置也会让用户不能缩放页面。所以一般情况下,不要使用以上俩个设置。
是不是无法解决这个bug了?首先这个bug最多只是在显示层面,带来的后果一点不严重,因为即使页面自动缩放了,它还是成比例的。
● width=<actual width>
有些人建议在viewport里使用特定的width,并且也按这个width设计页面。如果你可以为每个种类的device编写页面的话,这个设置是可行的,但需要我们明白的是它不是响应式设计。打印时,使用固定宽度布局是必要的,但我们网页应该适应用户的各种样式的设备。总之,不要这样使用。
● @media all and (device-width:480)
这是个media query而不是viewport标签里的选项, 我在很多地方看到过这样的代码,但我并不认为这是好的做法。为什么?根据CSS3对media queries的描述,device-width在media queries里表示的是输出设备表面渲染的宽度。对于continuous media来说,device-width就是屏幕的宽度;对于paged media来说,device-width就是页面尺寸的宽度。以continuous media为例,device-width就是设备屏幕的宽度。除非浏览器最大化,它始终大于viewport的width。
测试表明,大多数桌面浏览器把device-width和width当作同义词。而移动端浏览器对此会有点混淆。至于viewport标签里,device-width只在纵向时等于设备的width。例如,一个320*480的设备,device-width总是320px,不论方向。然而对于CSS media queries,device-width是基于其目前方向上屏幕的width。
如果你一定要这样使用,请和orientation一起使用。但绝对不要使用max-device-width和min-device-width,因为用max-width和min-width替换会比较好。同样需要注意的是,新型号设备的宽度可能会改变。
● 中间尺寸
上面我提到过,我们可以为任意数量的width来设计页面。最重要的是在不同width的浏览器中测试他们,通过调整window浏览器的大小来测试是最简单的方法。随着设计页面的width越来越小,我们可以去掉(Display:none;)一些不重要的内容,比如 footer,sidebars,menu等,为主要内容留足够大的空间。我们的网站也许需要一个可以在所有width屏幕上运行良好的布局,也许只需要满足两到三个布局。这是非常容易设计和测试的,所以没有理由不做。
● 推荐设置
最后,是我推荐的做法:
1. 使用viewport标签
2. 使用media queries来选择最适合页面尺寸的CSS
3. 在viewport标签里,使用width=device-width,initial-scale=1或者单独使用width=device-width
4. 不要使用maximum-scale=1和user-scalable=no
5. 不要使用width=<specific width>
6. 不要使用@media all and (*-device-width: xxx)