8.5 最后两个问题

还有最后两个问题需要解决。一个是有详细文档说明的iOS(苹果移动操作系统)设备上的重绘和缩放的bug,另一个是让下拉菜单也支持触摸。

8.5.1 移动Safari中的缩放bug

Safari Mobile(iPhone浏览器)中有一个bug,在设备从竖屏旋转到横屏时会导致缩放和重绘问题,如图8-8所示。enter image description here图8-8 在从竖屏旋转到横屏时,WebKit中的bug会导致屏幕重绘

有一个JavaScript脚本可以解决这个重绘问题,我已经把它包含在完成后的HTML示例文件中了。要了解关于这个bug的更多信息,请参考这里:http://webdesignerwall.com/tutorials/iphone-safari-viewport-scaling-bug。访问这里下载脚本:https://gist.github.com/901295

8.5.2 让下拉菜单支持触摸

最后,还有一个问题要解决。那就是让下拉菜单支持触摸操作。还记得吗,上一章,我们组合使用了opacityvisibility属性,实现了下拉菜单淡入淡出的效果。当时使用的CSS如下。

  1. nav.menu li ul { /*隐藏下拉菜单*/
  2. opacity:0; visibility:hidden;
  3. -webkit-transition:1s all; /*同时过渡opacity和visibility属性*/
  4. -moz-transition:1s all;
  5. transition:1s all;
  6. }
  7. nav.menu li:hover ul {opacity:1; visibility:visible;} /*鼠标悬停时显示下拉菜单*/

问题在于,支持触摸的设备会跳过:hover规则中对visibility属性的过渡。似乎也不算太意外,毕竟这个属性只是简单地切换了一个布尔值的状态,从而实现显示和隐藏。但这也说明visibility属性不是过渡动画的理想对象。除非我去掉visibility属性,否则菜单在触摸屏上没法用。可是如果真这样做,在非触摸屏上只要鼠标经过菜单下方,就会导致下拉菜单显示出来。因为下拉菜单虽然处于完全透明状态,但它对鼠标还是“可见的”。解决方案是使用Modernizr检测设备是否支持触摸,如果支持再去掉对visibility属性的过渡。如果设备支持触摸,Modernizr会给根元素html添加一个touch类,我们就可以针对触摸设备单写一条规则:

关于使用Modernizr,这里有一篇非常精彩的文章:http://webdesignernotebook.com/css/how-to-use-modernizr/

  1. .touch nav.menu li ul { /*Modernizr检测到触屏,再去掉妨碍菜单过渡的visibility属性*/
  2. -webkit-transition:1s opacity;
  3. -moz-transition:1s opacity;
  4. transition:1s opacity;
  5. }

这条规则对(不支持触摸的)非移动设备是不适用的。在触摸设备上,有了它用户在触摸相关菜单项时,下拉菜单就会显示出来。不过,当用户再触摸别的地方时,菜单会立即消失,而不是淡出屏幕。实际上,淡出效果的唯一好处,就是当用户鼠标意外离开时,再移回去还能把菜单“召回”。因此,在不使用鼠标的触摸设备上,这种“突然消失”的效果还是可以接受的。

请大家注意,这个菜单只有在触摸屏幕其他地方的时候才会消失。因为触摸其他地方会触发收缩bug的代码(上一节介绍过),强迫JavaScript运行,这样就足以让菜单意识到当前已经不再是悬停状态而关闭了。另一个实现这种“触摸其他地方关闭”效果的方法是执行某个JavaScript函数。比如,下面就是执行jQuery的noop函数(英文noop的意思是“无操作”)的例子。虽然这个函数什么也不做,但只要通过触摸屏幕其他地方来调用它,就可以关闭菜单了。

  1. (function(){ $(window).on('touchstart',$.noop); })();

当然,这完全是一种对付的手段。不过,JavaScript专家Isaac Shapira(他告诉我的这个技巧)跟我说:“这是一种优雅的对付。”假如你不需要修复缩放bug,那么只要加上这行代码就可以关闭菜单了。

要是你连jQuery都不想用,可以只在<body>标签上添加ontouchstart=" "。这样也会在用户触摸屏幕其他地方时触发JavaScript运行,从而关闭菜单。

博客圈里一直都在热烈地讨论怎么让触摸设备支持下拉菜单。我给大家提供这么一个链接,大家有空可以看一看,里面有一个试验性的例子:http://css-tricks.com/convert-menu-to-dropdown

我是在写这本书的时候,才最终找到这个让下拉菜单既能在鼠标设备又能在触摸设备上使用的方法。这个方法并不完美,我还会继续完善它。因此,请大家有空就到我的博客上瞧瞧,没准儿我又找到了更可靠的办法,或者又发现了其他问题。不过,当前这个方法在iPad和iPhone,以及有限几款Android设备上都没问题,我都测试过了。

好吧,就这样了。我们这个几乎能在任何设备上恰当展示的网页已经可以告一段落了。随着移动设备在人们工作生活中扮演的角色越来越重要(越来越多的互联网流量来自移动设备),开发响应式网站也只会越来越重要。