IPhone X 适配

关于底部

~'' 是控制忽略编译,不然css-loader在解析的时候会报错

@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
  .bottom-bar {
    bottom: calc(~'1.2267rem +  constant(safe-area-inset-bottom)');
    bottom: calc(~'1.2267rem +  env(safe-area-inset-bottom)');
  }
}

env() 和 constant()

iOS11 新增特性,Webkit 的一个 CSS 函数,用于设定安全区域与边界的距离,有四个预定义的变量:

  • safe-area-inset-left:安全区域距离左边边界距离
  • safe-area-inset-right:安全区域距离右边边界距离
  • safe-area-inset-top:安全区域距离顶部边界距离
  • safe-area-inset-bottom:安全区域距离底部边界距离

这里我们只需要关注 safe-area-inset-bottom 这个变量,因为它对应的就是小黑条的高度(横竖屏时值不一样)。

注意:当 viewport-fit=contain 时 env() 是不起作用的,必须要配合 viewport-fit=cover 使用。对于不支持env() 的浏览器,浏览器将会忽略它。

在这之前,笔者使用的是 constant(),后来,官方文档加了这么一段注释(坑):

The env() function shipped in iOS 11 with the name constant(). Beginning with Safari Technology Preview 41 and the iOS 11.2 beta, constant() has been removed and replaced with env(). You can use the CSS fallback mechanism to support both versions, if necessary, but should prefer env() going forward.

这就意味着,之前使用的 constant() 在 iOS11.2 之后就不能使用的,但我们还是需要做向后兼容,像这样:

padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */

注意:env() 跟 constant() 需要同时存在,而且顺序不能换。
更详细说明,参考文档:Designing Websites for iPhone X

iOS滚动定位问题

iOS12非浏览器滚动默认没有弹性问题

Q:增加弹性样式,-webkit-overflow-scrolling: touch;

思考题:到底都有哪些ios容器会有这个问题

如果容器高度变化,从有滚动条变成没有滚动条,里面的元素定位会继承有滚动条时的定位,而导致位置错误

Q:让当前容器初始化的时候就一定会出现滚动条可以避免这个问题,比如设置height: 101%;另外这个问题还要注意一下,如果你是rem布局,不要在height这里用calc(100% + 1px),因为rem有亚像素问题,一像素可能解决不了这个问题,非要优化的话建议+3px。

IOS不支持浏览器自动播放音乐

说到这个东西,肯定是碰到了这个需求。

直接上文档:
苹果官方文档地址
文档里面有一段注意:

To prevent unsolicited downloads over cellular networks at the user’s expense, embedded media cannot be played automatically in Safari on iOS—the user always initiates playback. A controller is automatically supplied on iPhone or iPod touch once playback in initiated, but for iPad you must either set the controls attribute or provide a controller using JavaScript.

大意就是为了避免不可预期的网络流量,而造成手机用户额外的下载费用,嵌入式的媒体没有办法在ios中自动播放,你需要加个控制器或者按钮(竟然没有机翻我也看得懂了)。

但是需求为大,还是要尽量解决这个问题,难道要我用js写音乐么~
如果这个问题可以得到解决欢迎大家提示我=。=

关于小米3安卓4.4ROM浏览器兼容问题

经过一些测试,小米3安卓4.4ROM回有一些不可预计的css和js不兼容问题。

可能是小米的开发在浏览器是做了一些优(wan)化(xiao)。

暂时看比较单行的问题是一个老版本swiper插件的拖拽有问题,更具体的还在测试中。

 

从用户的角度,碰到这种问题,影响了浏览,可以通过对浏览器设置->高级->浏览器标识的调整(应该只要不是默认就可以),来恢复正常浏览。

从开发者,用其他插件类库,或者干脆用自己写的东西,来规避这个问题。

android 4.4.2 KitKat 更新对wap页面的一些影响

问题写在前面。

有的时候我们要跟app进行通讯或者跳转,会用到设定好的URL Schemes去做跳转。

有的开发者可能习惯了驼峰式命名,所以把地址协议也设置成firstSecond://这样的形式。

以前应该是没什么问题,新版本的安卓会把协议强制转换为小写,那么如果你的脚本对大小写敏感的话就要注意这个问题了。

 

下面列举一下官方的更新说明:

 

支持蓝牙MAP

Android现在支持消息访问协议(MAP)。因此,支持蓝牙功能的汽车可与您的设备交换消息。

支持Chromecast

借助Android设备和Chromecast,您可以在高清电视上尽情欣赏喜爱的精彩在线娱乐内容(例如来自Netflix、YouTube、Hulu Plus和Google Play的内容)。

Chrome网页视图

嵌入网页内容的应用现可使用Chrome快速、准确地呈现此类内容。

可选字幕

Android现在支持可选字幕和翻译字幕。要启用可选字幕,请转至“设置”>“辅助功能”,然后开启“字幕”。

内置设备管理功能

如果您丢失了设备,可以通过Android设备管理器找到该设备或清空设备数据。

经过重新设计的“下载”应用

“下载”应用经过重新设计,提供了新的排序选项、列表和网格视图,方便您管理下载的文件。

轻松切换主屏幕

如果您喜欢对设备进行个性化设置,并已安装一个或多个可供替换的主屏幕,则可以在“设置”>“主屏幕”中轻松切换。

经过重新设计的“电子邮件”应用

“电子邮件”应用经过全新设计,面貌焕然一新!现在,该应用不但提供文件夹嵌套、联系人照片等功能,还改善了邮件浏览体验。

全屏壁纸,支持预览

壁纸现在可延伸至通知栏和系统按钮区域。更换壁纸时,您可以先预览其效果再进行设置。*

HDR+拍摄模式

Nexus 5提供HDR+拍摄模式,可自动快速连拍多张照片,并将这些照片合成一张,实现绝佳的单张效果。白天拍摄的照片鲜活生动、光影分明;夜间拍摄的照片轮廓清晰、噪点寥寥。*

红外线遥控

在搭载红外(IR)遥控器的设备上,Android现在支持应用对电视和其他附近设备进行远程控制。

“快捷设置”中的位置信息设置

通过“快捷设置”中的新选项,您可以从任何地方快速调整您的位置信息设置。

位置信息模式和监测

如果您想要节省电池电量,请转至“设置”>“位置信息”,然后在“准确度高”和“耗电量低”位置信息模式之间切换。您无需在GPS、WLAN和移动网络设置之间切换。要查看最近有哪些应用申请使用您的位置信息,请转至“设置”>“位置信息”。

音频播放更省电

搭载Android 4.4的Nexus 5极大地延长了您收听音乐的时间,音频播放时间最长可达60小时。*

在锁定屏幕上调整音乐和电影播放进度

您可以在锁定屏幕上跳至歌曲或视频的某个片段。只需长按播放或暂停按钮,然后选择所需时间点即可。

安全的应用沙盒

应用沙盒功能已通过Security-Enhanced Linux得以强化。

内置计步功能

在Nexus 5上使用健身应用(如Moves)时,手机就相当于一个计步器,可用来计算步数。Android 4.4和新硬件可让您以更省电的方式评估自己的运动量。

以全新方式支持碰触付款

Android 4.4采用了全新的开放式NFC支付架构,支持所有移动运营商,允许应用管理您云端或设备上的支付信息。现在,您可以使用Google电子钱包或其他应用,在超过一百万家商店中使用碰触付款功能。

改进触摸屏

结合改进后的软件和Nexus 5的最新硬件,Android现在能以前所未有的速度和准确度,响应您的触摸操作。*

移动端上的点击事件

刚接触手机的时候,前端工程师喜欢用click去处理点击/触摸事件。
渐渐地,通过体验和看过一些文章,我们知道手机上还有touch专用事件,于是我们开始专用touchstart或者touchend来处理触摸事件,然后我们就碰到了各种问题…

Click的延迟问题

click从功能上讲问题不大,但是响应有延迟,传说300毫秒,其实根据机能不同会有更长时间的延迟。

据说一些安卓机用click会出现其他的问题,我没碰到过所以不细说了。

各种touch先天不足

touch响应快,但是你碰到屏幕就是一个touchstart事件,离开屏幕就是一个touchend事件,就算你去拖动屏幕也会执行触发这两个事件,产生的问题我们叫误点击。

解决响应时间和误点击的几个方案

首先我这里不谈jqueryMobile。

那么我知道的几个解决方案为:

fastclick,https://github.com/ftlabs/fastclick;

MBP.fastButton,https://github.com/h5bp/mobile-boilerplate

zepto的tap和singleTap事件,http://zeptojs.com/

上面几个方案都可以很好的解决响应和误点击问题。

那么我们进入正题——“连点”问题

什么是“连点”?
当你点击一个层,而这个层因为事件控制而隐藏了,这时候恰巧这个层下面的区域点击的同一个位置也有点击事件被触发了,那么就是“连点”了。

这个问题发生在弹出层的情况比较多。

上面提到的三个方案在新的手机里面都不太容易(总有特殊情况)出现“连点”问题,但是在老的安卓里面,比如我手上的三星Note中fastclick就会出现连点。

而其他方案表现就很好,所以从这个角度fastclick基本被淘汰了。

还有一种“连点”!

连点还有一种情况,就是你可能在事件里面写了个window.location.href跳转,你这个跳转非常快的完成了,然后又恰巧你跳转的页面在你点击的位置也有个点击事件/链接,那么这个事件/链接也会被触发。
这个是点击问题中最丧心病狂的~
而且关键的是除了click和a标签本身,其他方案都无法避免这个问题。

所以请避免使用点击事件做跳转。

父子Dom的点击事件关系

如果我的一个大dom上有个点击事件,dom中的子dom也有个点击事件,那么点击子dom会执行谁的事件呢?

如果你用click和fastclick就都会执行,其他的方案是执行子dom的事件。

综上所述

如果你在项目中用了zepto,请优先用zepto的相关点击事件,来避免可能发生的问题。
当然了fastclick还有其他的响应功能,如果你需要的话可以在合适的时候去使用它。

一段以userAgent判断是否为手机浏览器的js代码

虽然我不关心,但同事说腾讯是这么用的。
其实就是写了个正则字典穷举手机的可能。个人感觉适用性能覆盖90%以上的用户(只要“安全”浏览器不把userAgent改的太奇葩,或者用户不太奇葩)。
if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){
if(window.location.href.indexOf("?mobile")<0){
try{
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
//移动端
}else if(/iPad/i.test(navigator.userAgent)){
//这里对ipad做了处理
}else{
//移动端
}
}catch(e){}
}
}else{
//pc端
}

wp是个特殊的存在(IE),要怎么单独判断wp呢。
var ISWP = !!(navigator.userAgent.match(/Windows\sPhone/i));
因为wp的特殊性海量的方法给你判断,具体情况再具体分析。

【转】IE6下DIV容器中双Float元素字符重影bug(IE6重复文字bug)

转载前说明:感谢作者,我终于找到个说法了,之前因为没有相关资料一直是通过改变代码结构来解决该问题的,现在看到这些总结也总算不会无计可施,同样碰到问题的同学有福了。

转载自:http://www.yuzi.me/Share/ie6floatbug.html

ie6floatbug1

IE7 的web标准之道IE历来被web标准的拥护者所诟病,而当FireFox横空出世以后,更多的网页制作者开始关注web标准设计。看着FireFox的 市场占有率不停的上升,微软终于推出了IE7。但IE7是否真的能够力挽狂澜,是否真的能够得到用户的信任,是否真的能够得到网页设计者的认可呢?

估 计很多的朋友都是因为这个华丽的“重复文字”一词进来的,其实这纯粹是一个bug作为。这个bug在国际上比较获得认可的名字叫做——“IE6重复文字 bug”。这是一个非常好玩但是有很令人摸不到头脑的bug。如果,你不知道产生原因的话,将会令人非常头痛。这也是我在现实工作中真正遇到过的情况。

测试一下:复制以下代码放IE6下测试

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>
<html xmlns=”http://www.w3.org/1999/xhtml“>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<meta name=”author” content=”Yuzi,煜子,网页设计师网站” />
<meta name=”Copyright” content=”Yuzi,煜子” />
<title>IE6重复文字bug</title>
</head><body><div style=”width:200px; height:100px; padding-left:70px;”><div style=”float:left;”></div>
<!–如果是IE6,你将多看到一个“影”字–>
<div style=”float:left; width:200px;”>IE6下DIV容器中双Float元素字符重影</div>
</div>
</body>

下面是测试页面分别在IE6,IE7,IE8,FireFox(火狐浏览器),Chrome(谷歌浏览器),Oepra以及Safari(苹果浏览器)中显示效果截图

ie6floatbug2

通过截图,你会惊讶的看到在IE6中,多出了一个“影”字。下面来讲讲出现这个“影”字的一些条件(bug重现条件)

一个容器包含2两个具有“float”样式的子容器。

第二个容器的宽度大于父容器的宽度,或者父容器宽度减去第二个容器宽度的值小3(说到3,这里稍微多说一句——IE7还修正了IE6中的一个bug,bug名字就叫做“3像素bug”)

在第二个容器前存在注释(这也是为什么此bug也叫做“IE6注释bug”的原因)

为何会出现重影

bug虽然的的确确的存在,但是为什么会出现这样的bug依然没有统一的定论。不同的高手也是各执一词,谁也说服不了谁。真正的原因也许只有当时的IE6团队才能道出来,但是现在仍然没有官方的说法。下面列出来的这两种说法,只是现在网上认可度比较高的而已。

说法一:

IE6浏览器对<!– –>注释的解释存在bug引起的。“3像素bug”的扩展后遗症。

说法二:

其他的一些说法,如何消灭重影 引起的原因,也许我们可以不知道,但是如何消除却是我们一定要关注的。”重影bug”已经在IE7中得到修正,在FireFox和Opera中也不会出现,所以bug的修正主要是针对IE6的。

针对于上文中讲到的“bug重现条件”,如果要修正bug,只要让任何一个条件满足即可。有些网友对IE6 重影bug做出了一些想法及议论。

解决方法一:

改变结构,不出现【一个容器包含2两个具有“float”样式的子容器】的结构。
此解决方案的评论:疯了!因噎废食的做法。

解决方法二:

减小第二个容器的宽度,使父容器宽度减去第二个容器宽度的值大于3,例如将本文示例中第二个子容器的宽度改为197px。
此解决方案的评论:在满足页面布局的前提下可以使用。但是当情况比较复杂的时候,可能实施起来比较困难。

解决方法三:

去掉所有的注释。
此解决方案的评论:最直接的做法,但是“没有注释的代码”,的确不是一个好的代码写作习惯。

解决方法四:

修正注释的写法。将 <!– 这里是注释内容 –>写成<!–[if !IE]>这里是注释内容<![endif]–>
此解决方案的评论:还不错的解决方案,但是并不是每个人都对<!–[if !IE]>这里是注释内容[endif]–>这种注释写法很欣赏。

解决方法五:

在第二个容器后面加一个或者多个<div style=”clear”></div>来解决。
此解决方案的评论:另人感觉很不爽的解决方案,但是的确能解决,影响网页效率。

关于此bug的一些文章资料,其实很早以前就有外国的朋友关注过这个bug,而且在中国也有过一些朋友关注过这个bug。我在写这篇文章的时候,也一定程度上参照了他们的研究成果,在此向研究此问题的前辈们表示感谢。

html5开发之viewport使用

转自:http://www.php100.com/html/webkaifa/HTML5/2012/0831/10979.html

结合坑爹的viewport一起了解

随着高端手机(Andriod,Iphone,Ipod,WinPhone等)的盛行,移动互联应用开发也越来越受到人们的重视,用html5开发移动应用是最好的选择。然而,每一款手机有不同的分辨率,不同屏幕大小,如何使我们开发出来的应用或页面大小能适合各种高端手机使用呢?学习html5
viewport的使用能帮你做到这一点……viewport 语法介绍:

01<!– html document –>
02<meta name=”viewport”
03content=”
04height = [pixel_value | device-height]
,
05width = [pixel_value | device-width ]
,
06initial-scale = float_value ,
07minimum-scale = float_value ,
08maximum-scale = float_value ,
09user-scalable = [yes | no] ,
10target-densitydpi = [dpi_value | device-dpi | high-dpi | medium-dpi
| low-dpi]
11″
12/>

width

控制 viewport 的大小,可以指定的一个值或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS
的像素)。

height

和 width 相对应,指定高度。

target-densitydpi

一个屏幕像素密度是由屏幕分辨率决定的,通常定义为每英寸点的数量(dpi)。Android支持三种屏幕像素密度:低像素密度,中像素密度,高像素密度。一个低像素密度的屏幕每英寸上的像素点更少,而一个高像素密度的屏幕每英寸上的像素点更多。Android
Browser和WebView默认屏幕为中像素密度。

下面是 target-densitydpi 属性的 取值范围

  • device-dpi –使用设备原本的 dpi 作为目标 dp。 不会发生默认缩放。
  • high-dpi – 使用hdpi 作为目标 dpi。 中等像素密度和低像素密度设备相应缩小。
  • medium-dpi – 使用mdpi作为目标 dpi。 高像素密度设备相应放大, 像素密度设备相应缩小。 这是默认的target density.
  • low-dpi -使用mdpi作为目标 dpi。中等像素密度和高像素密度设备相应放大。
  • <value> – 指定一个具体的dpi 值作为target dpi. 这个值的范围必须在70–400之间。
1<!– html document –>
2<meta name=”viewport” content=”target-densitydpi=device-dpi” />
3<meta name=”viewport” content=”target-densitydpi=high-dpi” />
4<meta name=”viewport” content=”target-densitydpi=medium-dpi” />
5<meta name=”viewport” content=”target-densitydpi=low-dpi” />
6<meta name=”viewport” content=”target-densitydpi=200″ />

为了防止Android Browser和WebView
根据不同屏幕的像素密度对你的页面进行缩放,你可以将viewport的target-densitydpi 设置为
device-dpi。当你这么做了,页面将不会缩放。相反,页面会根据当前屏幕的像素密度进行展示。在这种情形下,你还需要将viewport的width定义为与设备的width匹配,这样你的页面就可以和屏幕相适应。

initial-scale

初始缩放。即页面初始缩放程度。这是一个浮点值,是页面大小的一个乘数。例如,如果你设置初始缩放为“1.0”,那么,web页面在展现的时候就会以target
density分辨率的1:1来展现。如果你设置为“2.0”,那么这个页面就会放大为2倍。

maximum-scale

最大缩放。即允许的最大缩放程度。这也是一个浮点值,用以指出页面大小与屏幕大小相比的最大乘数。例如,如果你将这个值设置为“2.0”,那么这个页面与target
size相比,最多能放大2倍。

user-scalable

用户调整缩放。即用户是否能改变页面缩放程度。如果设置为yes则是允许用户对其进行改变,反之为no。默认值是yes。如果你将其设置为no,那么minimum-scale
和 maximum-scale都将被忽略,因为根本不可能缩放。

所有的缩放值都必须在0.01–10的范围之内。

例:

(设置屏幕宽度为设备宽度,禁止用户手动调整缩放)

<meta name=”viewport” content=”width=device-width,user-scalable=no”
/>

(设置屏幕密度为高频,中频,低频自动缩放,禁止用户手动调整缩放)

<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

转载自:http://hax.iteye.com/blog/978184

 

最近我做了一点儿针对手机的Web开发和相关研究。按说,Web自设计之初,就已经考虑了设备无关性。然而,现实总是不尽如人意。 

我们知道大多数网页都是针对桌面显示器开发和测试的,但是手机屏幕通常要比桌面显示器小很多,比如iPhone也就是320px。那么那些网页在手机上如何浏览呢?

一种是把网页缩放到很小,你可以看到整个网页但是看不清字了;或者只看网页的一个局部,然后上下左右移动来看其他部分。现在的手机浏览器把两种模式结合使用。(或许还有第三种——分析网页,将其中内容抽取出来,重组,然后呈现,不过这里不讨论这种方式。)

如果仅仅是出现横向滚动条,那问题倒不是很大。对于那些采用固定布局的“像素级精确设计”确实就是如此。但是使用自适应布局的网页就有问题了。比如一个三栏布局,其中一个边栏可能只有20%宽度,320px的屏幕上只有60多像素,只能放5个汉字,排版不美观不要说,如果里面有一些图片,很可能图片的宽度都超过60像素,造成overflow,从而破坏了布局。另一种常见布局方式是采用固定大小的边栏,例如240px宽,而主体部分则自适应宽度。然而对于320px的屏幕来说,本来是次要的边栏占据了3/4空间,主要部分却只有1/4空间,另外也极有可能因为内容包含图片等造成overflow。

说到这里,那些喜欢固定布局的人(比如那些热衷于960px grid排版的同志们——哦,最近淘宝升级成1000并放弃了栅格!不过那仍然是固定布局)可能要乐了,你们倡导了半天流式布局,结果在mobile设备上表现反而很糟糕,真是费力不讨好。

真正掌握CSS的同志(是的,珍稀动物!)肯定会反驳。上面这些问题其实都很容易解决。比如设定min-width。还有,适应不同屏幕大小的“正确”的方案,应该用media
query。

问题是,大多数网页没有这么做!或者说不是按照“正确”的方式写的!未必是网页作者不懂CSS,而只是他们压根没费心考虑过手机大小的屏幕(毫不惭愧的说,本人也是其中一份子)。你可以试着把桌面浏览器收缩成320px宽(或者可以试着zoom
in到300%),可以看到不少网页会发生严重的布局错乱,至少也是浏览体验上的大幅下降。为了迎合这些网页,手机浏览器厂商发明了两个viewport

简单来说,就是手机浏览器把自己冒充为拥有一个更宽的屏幕,这样页面的布局就能跟桌面浏览器一样了。不同浏览器冒充的数值不一样:iPhone是神奇的980——960它表弟;Android是保守的800——冒充一个800*600的显示器;而Windows
Phone 7则是1024——冒充一个1024*768的显示器(充分体现微软的庸俗特质)。

原本布局就是按照viewport(桌面上的浏览器窗口)大小来进行的,现在决定布局的viewport和窗口分裂了,产生了两个viewport。

两个viewport其实并不新鲜。就像前面说的,所有做固定布局的同学其实都在不自觉使用两个viewport——固定布局,其实相当于人为设定了布局viewport。

使用独立的布局viewport还有一个好处,那就是缩放变得很简单,不用引起relayout。

在浏览器的历史上,主要有两种不同的缩放方式,一种是以IE6为代表的缩放(文字大小),实质是改变root元素的字体大小。另一种是像素缩放,实质是改变CSS
pixel的大小(即1个css像素不再对应1个物理像素),或者说改变了浏览器的内部DPI。(Firefox还支持真正的字体缩放,与改变root元素的字体大小不同,它会缩放所有元素的font-size最终使用的值(used
value),因此不仅对于以em设定的字体大小有效,对于以px和pt等所有单位设定的字体大小都有效。)

在桌面浏览器上,因为缩放时viewport的物理大小是固定的,如果进行像素缩放,实际就意味着viewport以CSS
pixel计算的宽度和高度会随之改变,比如若放大到200%,CSS宽高就会缩小到原来的50%。而这必然引起relayout。

相反,在mobile浏览器上,像素缩放时,布局viewport的物理大小可随之缩放,因此其CSS宽高值是不变的,就不必引起relayout。这不仅避免了relayout的大量计算,也更符合移动设备上的用户体验(考虑一下你如何缩放地图就明白了)。

虽然两个viewport能比较好的解决在手机上浏览过往网页的问题,然而,这毕竟是一个向后看的方案,体验毕竟是受限的。想象在320宽的窗口里看960固定布局的网页,不可避免的要时常缩放和使用横向滚动条。在触摸屏上我们可以用手势来控制,会方便一点,但是仍然很麻烦。所以绝大多数移动Web开发者最终还是选择针对小屏幕(重新)进行设计。

不过一个显然的问题是,如果我的网页已经考虑了小屏幕,甚至就是专门为手机设计的,那么我其实不需要两个viewport(也不需要缩放),这时候怎么办?更一般的问题是,如果我设计的网页不是针对960或者800或者1024的呢(至少你选了960,就排除了800和1024;你选了800,就排除了960和1024;你选了1024,就排除了800和960……)?

于是Apple发明了viewport的meta标签,例如:
<meta
name=”viewport” content=”width=320,
initial-scale=1.0, minimum-scale=1.0,
maximum-scale=1.0″>

其中width表示网页的布局layout宽度。initial-scale表示初始时的缩放比例,minimum-scale和maximum-scale分别表示最小和最大缩放比例。这样,上面这个meta就表示布局宽度320像素,初始缩放为1倍(即不缩放),且禁止用户缩放(因为最大最小缩放都为1倍)——一个专为iPhone优化的网页通常就会用这样的设置。

如果你是针对960设计的,那么可以用这样一个meta:
<meta name=”viewport”
content=”width=960, initial-scale=0.33″>

这表示布局宽度为960像素,初始缩放为0.33,也就是,会缩小到大约1/3,这样正好可以在320像素的宽度里看到整个网页。你也可以不设initial-scale,因为手机浏览器大多默认会初始缩放到可容纳整个网页宽度。

嗯,看上去不错吧。

可是,说到底,手机浏览器的这种设计,实际上揭示了一个难堪的真相——你们这些网页仔,其实从来没真正做好过屏幕适应。因为一个能自动完美适应不同屏幕大小的“正确”方案,width的取值就不应该是一个固定数字。幸好,safari的工程师在发明viewport时还是给我们留了点面子,width的取值除了像320或960这样的数字,也可以是关键字device-width(其实我认为更合适的词是auto),表示采用设备宽度。

然而,历史总是杯具的重复自己。微软就又(嗯,我为什么要说“又”呢?)贡献了这样一个例子:Window Phone
7的设备宽度通常至少是480,那么按理说,如果viewport中设置了width=device-width,layout宽度应该是480像素,可是IE mobile会将viewport设为320!这是神马原因呢?

原来据说微软收集的数据表明,有大量站点使用了device-width,但是其实只为320像素宽(也就是iPhone的宽度)优化——比如直接用一个固定宽度320px的<div>将内容wrap起来!我勒个去,诸位移动Web开发者,你们有木有这么干?有木有!

那后面的故事就不用说了。微软当然是做出了一个“正确”的选择。

另外需要注意的是,width只是设置layout宽度,还要乘上缩放比例,才能得到最终的显示宽度。那么对于480像素的屏幕来说,若device-width“被320”,那initial-scale应该是1.5才能占满整个屏幕宽度。可是如前所述,针对性优化的网页会把initial-scale设成1.0!

对此微软是如何处理的呢?文档语焉不详,而其模拟器要在Windows
7上才能运行,所以我也暂时没有进行实测,不过据我推测,其initial-scale应该仍旧会保持1.0,也就是这1.5会变成额外的缩放因子。实际上其他移动浏览器已经这样做了,比如Fennec(Firefox的移动版)就是如此。Android和iPhone
4也都有类似的设计,为什么会这样?这样会不会产生新问题?留待下一篇博客再讨论。