9 解决跨浏览器问题
在最后一章,我们将学习以下内容
渐进增强和优雅降级之间的根本区别
如何让老版本Internet Explorer支持响应式设计
何如使用Modernizr按需加载CSS文件
何如使用Modernizr按需加载JavaScript补丁文件
如何将超长导航列表在小视口中转换为选择菜单
如何为高分辨率(视网膜)显示屏提供匹配图片
在学习最后一章之前,先回顾一下我们当前的处境和状况。
移动设备使用量呈爆炸式增长。因此用户会使用各种各样的视口(不同的尺寸和方向)和带宽来浏览网页。在可预见的未来,我们需要以基本内容、分层特性和渐进增强为基准来设计和制作网站。此外,考虑到带宽差异,网站代码应该尽可能保持简洁和灵活。从设计角度看,我们已经完整学习了Ethan Marcotte提出的响应式设计的三种方法。CSS3媒体查询(第2章)用于创建设计断点,从而使网页布局可以完美匹配各种视口。而结合流动布局的弹性图片和多媒体技术(第3章),则可以保证网页在这些媒体查询断点之间的平滑过渡。响应式设计的结果就是设计不仅在今天流行的视口上表现完美,而且是面向未来的。
为了保持代码简洁,第4章我们将页面标签换成了HTML5。HTML5能提供更加精简和语义丰富的代码,而且为我们带来了诸如离线访问等新特性。此外,我们还在页面代码中使用了一些无障碍网页应用技术(WAI-ARIA)以增强可用性,为依赖屏幕阅读器和辅助技术的用户提供额外的帮助。
在第5章和第6章,我们领略了CSS3的强大威力和灵活性,学习了新的RGBA和HSLA颜色模式,以及如何不依赖图片而仅使用CSS3来制作盒阴影、文字阴影、背景渐变等各种常见的设计效果。此外,强大的CSS3选择器可以让我们选择DOM中任意需要的元素,而这种能力以往必须依靠JavaScript才能实现。但CSS3不只能用来调整设计效果或者大幅降低浏览网页所需的带宽消耗,更重要的是还为我们带来了一些在以往没有Flash或JavaScript就不敢奢望的新特性:自定义字体(第5章)以及不同视觉状态间的优雅平滑的过渡效果(第7章)。放眼未来,我们还了解了一些比较复杂的特性,如CSS3的3D转换。
最后在第8章,我们告别了单调乏味的表单制作体验,享受着使用HTML5标签来处理表单验证和创建表单元素的惬意。值得称道的是,我们还有条件地为一些老版本浏览器如IE6、7和8插入了JavaScript备用方案以提升用户体验。
从本书的开头到现在,我们用HTML5和CSS3完成了一个名为And The Winner Isn’t….的响应式网站。你可以通过http://www.andthewinnerisnt.com访问该网站。
下图展示了网站首页在iPhone上的显示效果:
在iPad上的显示效果:
在Android(模拟器)浏览器中的显示效果:
在现代桌面版浏览器(Google Chrome v16)中的显示效果:
以及在Internet Explorer 8中的效果:
我的妈呀!给我一把左轮手枪……
Internet Explorer 8中的效果惨不忍睹,因为它不支持<aside>、<header>、<nav>和<footer>等HTML5元素,这自然就引入了本章的主题——解决跨浏览器问题。 9.1 渐进增强与优雅降级 你可能听过“渐进增强”和“优雅降级”这两个词。它们是处理多浏览器支持的两种方法论,并在Web社区中引发过激烈的辩论。虽然最初它们看起来是两个可互换的概念,但本质上则完全相反。下面是我的理解。
优雅降级指的是为现代浏览器制作网站,然后保证为某些老版本浏览器提供基本可用的体验。新特性在老版本浏览器中会降级,且一般会有一个分界点,声明不支持那些老掉牙的浏览器。有些时候用户也仅会被警告他们所使用的浏览器有问题,建议其更换(如“您的浏览器老得让人笑话——建议下载最新版浏览器!”)。
渐进增强与优雅降级恰好相反。渐进增强以恪守Web标准的标签为基础,意味着它在所有浏览器中均可用。然后通过CSS样式和必要的JavaScript来为更先进的浏览器提供渐进式的增强体验。
讨论过这两种方法优劣的文章数以百计。我们先来看看来自Opera开发者社区的这篇:http://dev.opera.com/articles/view/graceful-degradation-progressive-enhancement/,以及来自Aaron Gustafson的经典之作:http://www.alistapart.com/articles/understandingprogressiveen hancement。
现状
目前,渐进增强被普遍认为是开发网站的最佳实践。然而,冰冷的现实是,我虽然打心眼里喜欢渐进增强并用它来制作网站,但很多情况下可以说我是用优雅降级的方式来做的。怎么会这样呢?
www.andthewinnerisnt.com这个网站是使用HTML5制作的。IE6、7、8是在HTML5之前就已被开发和发布出来了(你应该知道,HTML5虽然日益普及,但它还不是一个被正式批准的标准),所以无法识别<aside>、<section>和<footer>这样的标签。因此,从纯粹意义上讲我不应该使用HTML5元素。追加一段JavaScript来解决这个功能问题——这就是真正的渐进增强吗?
尽管如此,除非有什么让我信服的理由,否则我都一直选用HTML5来替代HTML 4.01。现实是,根据我的日常工作经验,HTML5利大于弊。在使用HTML5时,一定要编写与标准兼容的HTML代码(可以使用HTML5验证工具来排除代码错误,地址是:http://validator.nu/或http://validator.w3.org/),好让所有设备都能以原生方式完美渲染。
无论如何,有时你肯定会选择(或是被逼无奈)去实现一些现代浏览器提供的增强功能,可能是为了那些老弱的IE。比如你想让它能支持圆角,不过在你这么做之前,请再听我啰嗦几句…… 9.2 该不该修复老版本IE 我想再次重申以前的观点:通过打补丁的方式可以为老版本浏览器增加大多数HTML5和CSS3特性,但导致的结果是用户体验将严重依赖JavaScript,且可用性相较于不使用补丁有所减弱。毫无疑问,影响这个抉择最关键的因素是性能。因为我只是告诉你能这么做,并不代表你应该这么做!
此外,即使不使用补丁(我们稍后会谈谈这个话题),以我的经验,为了能让IE6和IE7(以及少量IE8和IE9)的页面渲染效果尽可能与现代标准浏览器类似,开发、测试和配置专属CSS代码所花费的时间,至少也和为现代浏览器提供渐进增强所花费的时间一样多——这很让人不爽!你和你的客户就准备这样用掉开发时间? 9.2.1 统计数据(再看看世界的变化) 我们来重温一下第1章说过的话题。我们注意到从2010年7月到2011年7月,全球移动浏览器的使用率(数据来自Global Stats网站http://gs.statcounter.com)不断上升,从2.86%涨至7.02%,而IE7的使用率则继续下跌,低至5.45%。2011年最后一个月的统计数据则更加令人警醒:IE7的使用率只剩了4%,IE6的使用率仅有1.78%。而与此同时移动浏览器的使用率则增长至8.04%。
另一个更加有趣的现象是截止2011年12月,Google Chrome(包括v15和v16)仅凭一己之力就占据了全球浏览器市场的25.7%,几乎与IE 6、7、8的总和(27.9%)持平。再加上其他现代浏览器的份额,如Safari(4.3%,不包括iOS版)和所有版本的Firefox(21.01%)以及各种移动浏览器,就不难发现为现代浏览器开发增强的用户体验,远比为那些老不死的玩意修补漏洞更有意义。至少对我来说是这样的!
结论就是:老弱的IE(6、7、8)的使用率正在不断减少,而现代浏览器(包括桌面版和移动版)的使用率则正在不断增加。 9.2.2 个人选择 目前我个人的态度是,针对全新制作的网站,要确保其在最新版本的IE(编写本书时最新版本是IE9)以及前一个版本(IE8)中效果完美。而针对老版本IE的布局和样式调整则由于需要额外的时间,所以另行商议。
这样做并不表示我完全不管IE7等老版本浏览器的基本可用性问题。我只是将有限的开发时间用于保证基本布局和功能正常,所以会忽略一些微小的对齐问题,以及一些由于浏览器不支持背景渐变、圆角、盒阴影新特性而导致的视觉差异问题。这些东西不影响可用性,多半都属于渐进增强的效果,我也没期望在老弱浏览器上看到什么效果。
在多个浏览器中测试网站
通常,标准浏览器如Chrome、Safari、Firefox在渲染使用HTML5和CSS3制作的网页时,效果基本一致。目前,大多数智能手机使用的也是和桌面版Safari、Chrome一样的Webkit内核,所以其渲染效果也满足你的期望。但是,不同版本的IE渲染效果差别较大,所以毫无疑问你需要在各版本的IE中测试一下网站效果(除非你默认就使用IE浏览器——哎哟,我得向老同志表示一下慰问)。我通常都使用IE Tester(http://www.mydebugbar.com/wiki/IETester/HomePage)这个免费的工具,利用它可以在一台机器上同时运行多个版本的IE。不过还有很多类似的替代软件,Smashing Magazine上的这篇文章对这类工具做了一个很好的总结:http://www.mashingmagazine.com/2011/08/07/a-dozen-cross-browser-testingtools/。
为了说明这种方法,在看完http://www.andthewinnerisnt.com网站在IE8中的效果之后,很明显我们得做点什么,好让网站基本正常。我们准备使用一个名为Modernizr的JavaScript工具和一个补丁来修补老版本IE的缺陷。我不太确定IE是否值得这么做,因为毕竟问题是因它而起的,但谁让我心肠软呢。在我们开始之前,先来了解一下Modernizr。 9.3 前端的瑞士军刀:Modernizr 在线社区总能发现各种浏览器的兼容性问题,并不断为我等凡人贡献解决方案,这一点让我既赞叹又着迷。我们在第4章简要介绍过Modernizr,到了最后一章又一次讲到它。Modernizr是一个用于检测浏览器功能的开源JavaScript库。Modernizr的第一版由Fauk Ate?开发,目前由Alex Sexton和才华横溢的Paul Irish担当首席开发人员。一些知名的公司已经开始使用这个工具,包括Twitter、微软和谷歌。我说这些不只是为了吹捧 Modernizr的开发团队(他们确实值得吹捧),更重要的是想说明Modernizr是JavaScript杰作,绝不会昙花一现。坦率地说,它是一个值得深入理解和学习的工具。
那它到底做了什么?既能给老版本浏览器打补丁,又能保证新浏览器渐进增强的用户体验,它是怎么做到的,而我们又如何使其听任差遣呢?好好听着……
从实际操作来看,Modernizr默认做的事很少,除了(在你选择的情况下)给不支持HTML5标签的浏览器如IE6、7、8追加一点由Remy Sharp开发的HTML5垫片脚本,使其可以识别<aside>、<section>等 HTML5元素之外,它主要做的就是浏览器“功能检测”。因此,它知道浏览器是否支持各种HTML5和CSS3特性。这就为我们根据浏览器特性采取不同行动提供了依据,剩下的事情就是我们如何具体实施了。所以,我们来给页面加入Modernizr来试试效果。
第一步,下载Modernizr(http://www.modernizr.com)。
如何选择Modernizr版本——开发版还是生产版?
如果你对Modernizr的运行原理感兴趣,那就下载开发版,因为每一个选项和功能测试都有相应文档。不过,开发版可以让你只选择仅和你的网站或Web应用相关的功能检测,这样可以保证文件既小巧又有的放矢。
接下来,将文件保存在某个适当位置(和之前一样,我保存在根目录下的js文件夹中),然后在页面的<head>中调用:
使用了Modernizr之后,再通过Firebug或类似开发工具查看页面源代码时,就会看到HTML标签上追加了一堆不同的类名。在Firefox v9.01中查看的示例效果如下:
这种做法很棒。这样就可以区别具体的浏览器,告知我们它检测了那些特性,其中该浏览器支持哪些,不支持哪些(对不支持的特性,对应的类名前有no-前缀)。基于此我们就可以做两件事:在CSS文件中逐个特性地修正样式,以及按需加载额外的CSS或JS文件。 9.3.1 使用Modernizr辅助修正样式问题 And the winner isn’t…网站非常适合使用Modernizr来辅助修正一个样式问题。我们的问答页面在支持3D变形的浏览器中效果正常,在不支持该特性的浏览器中则仅做了一个简单的悬停效果。现在,无论浏览器是否支持3D变形,我们在页面上都有一段备注告知用户:该页面效果需要3D变形的支持。如果你没看到海报图片的3D翻转效果,试试Safari或Chrome。
有了Modernizr追加的额外类名,就有办法仅在不支持3D变形特性的浏览器中显示备注信息了。
分析一下,首先将备注设置为默认不显示:
这意味着支持3D变形特性的浏览器(如Google Chrome 16)就不会看到备注信息(如下图):
接下来的规则使用了Modernizr追加的额外类名来为不支持3D变形的浏览器显示备注:
下图显示了同一页面在Firefox 9中的效果:
Modernizr让我们抛弃浏览器的角度,转而从功能特性的角度考虑问题。 9.3.2 使用Modernizr让老版本IE支持HTML5元素 我选择了一个含有HTML5垫片脚本的Modernizr自定义生产版,然后在IE8中刷新页面,可以看到页面效果比之前好太多了:
我不用再做什么。因为Modernizr使老版本IE可以识别HTML5的结构化元素,所以之前的很多标准CSS样式现在都可以识别了,页面呈现出了它应有的样子。
对于我这个自由职业者的钱包来说,这是天大的好事。如果你之前没有在现代浏览器中看过这个网站的效果,你应该都不知道两者有什么区别。不过,由于IE8缺少CSS3支持,所以相对于现代浏览器来说有一些明显的视觉效果上的缺陷。导航链接上没有交替颜色(如果需要,我们可以通过给奇数导航链接追加额外类名来解决这个问题),按钮没有圆角,没有文字阴影和盒阴影。最重要的一点是,虽然我们的流式布局很灵活,但缺少CSS3意味着不支持媒体查询。没有媒体查询,在IE 6、7、 8中就不会有不同视口中精心设计的布局变化。
虽然我怎么都不认为IE8中这样的布局“毁”了设计效果,但只要你愿意,Modernizr也可以帮你修补老版本浏览器。为了证明这一点,我们来给IE 6、7、8追加min/max-width媒体查询支持,从而使网页在这些浏览器的不同视口中也能正确响应。 9.3.3 给IE6、7、8追加min/max媒体查询功能 我选择的给老版本IE添加媒体查询支持的垫片脚本,仅支持追加min/max-width媒体查询功能。还有很多类似的垫片脚本,可以追加很多媒体查询特性。但对于响应式设计来说,Scott Jehl开发的Respond.js使用简单、速度快,我一直用得很顺手。
Respond.js(https://github.com/scottjehl/Respond)可以独立于Modernizr使用——只需将其引入到需要的页面,然后就如其作者Scott Jehl所说:“撬开IE,击掌相庆。”
在将Respond.js整合到Modernizr之前,我们先来单独使用一下。将Respond.js直接丢到页面上(即将其插入到Modernizr文件之后),然后检查看看它对IE做了哪些处理。具体做法是将Respond.js保存到某个适当的路径,然后在<head>中引用:
现在,只要在IE8中加载页面并调整浏览器窗口,就会看到我们的响应设计效果又回来了(如下图所示):
不错,我们现在给IE添加了垫片脚本,使其可以支持min-width和max-width,但有一个问题:垫片脚本在每一种浏览器中都会被加载——不论它们需要与否。一种解决办法就是将脚本文件链接放置在IE条件注释中,像下面这样:
你以前肯定见过条件注释。这是一种非常简便的方法,可用来为相应版本的IE加载CSS或JS文件(甚至是内容)。其他浏览器会将这些代码看做注释而直接忽略。
在本例中,我们的条件注释是说:“如果你的浏览器版本低于或等于(lte)IE8,就执行其中的代码。”
详细了解条件注释
相较于功能检测来说,条件注释并不太受欢迎,但如果你想了解更多有关条件注释的知识,请参阅如下网址:http://msdn.microsoft.com/en-us/library/ms537512%28v=vs.85%29.aspx
这样问题就解决了。但我们真要使用IE特有的条件注释来污染我们的标签代码吗?那针对其他浏览器的垫片脚本又该怎么办呢?还是得用Modernizr呀。 9.3.4 使用Modernizr按需加载资源 Modernizr在保证网站或Web应用的代码精简方面有一个极大的优势,就是它能按需加载资源(CSS和JS文件)。其实我们只需要加载用户真正需要的资源,而不是采用“贪大求全”的策略(不管他们是不是真正需要就)加载每一个用户可能用到的资源。这样就可以保证对每一个用户,我们的页面都足够简洁,加载足够快速。
之前Modernizr已经被追加到了页面头部,接下来我们来为那些不支持CSS3媒体查询的浏览器(如IE6、7、8)加载Respond.js文件。
Modernizr中包含一个名为YepNope.js的小型JavaScript库文件(http://yepnopejs.com/)。使用方法很简单:
首先调用Modernizr的资源加载方法:
加载方法中包含功能检测,以及根据检测结果将要采取的一系列动作。在本例中,我们检测的是浏览器是否支持媒体查询:
如果不支持,则会加载respond.min.js这个文件:
此处的only all表示“你能识别媒体查询吗?”,老版本IE的检测结果肯定是不支持,所以对应nope中的动作,即加载相应的资源文件。这样就可以让respond.min.js仅在需要的时候加载。
还可以一次加载多个文件:
上面的代码中使用了一个数组来同时加载respond.min.js和一个名为extra.css的CSS文件。这种方法可以让你根据实际的需要来加载独立的样式。还有一点值得一提,即还可以根据不同的检测结果来加载不同的资源文件:
上面的代码在检测通过时加载一个文件,检测失败时加载三个文件,最后无论检测结果如何,都加载一个名为for-all.js的文件。
按需加载资源的代码可以单独写在一个JavaScript文件里。本例中我将其命名为conditional.js,并将其与modernizr.js和respond.min.js一起放在js文件夹。这样整理之后,<head>部分看起来就是下面这个样子:
注意我已经移除了respond.min.js,因为现在该文件可以根据需要自动加载。
有关使用Modernizr按需加载资源的更详细文档,请见此处:http://www.modernizr.com/docs/#load。
下载垫片脚本
下面的这个github库中有很多有用的垫片脚本:https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills。 9.4 必要时将导航链接转换为下拉菜单 在小视口屏幕中,响应式设计普遍存在一个问题,即页面上一大堆导航链接会占据宝贵的屏幕空间。
例如,And the winner isn't…网站只有6个导航链接,目前页面在小视口中的效果如下所示:
我想在浏览器视口小于一定宽度时,将这些导航链接转换为一个下拉菜单。你可以自己编写一段代码来做这件事。可敬的Chris Coyier写过一篇文章来讲怎么做(http://css-tricks.com/convert-menu-to-dropdown/)。不过,你还可以选择别人已经写好的脚本。为了简便起见,我就选了个现成的脚本。下图显示了在小视口中将导航链接转换为下拉菜单后的效果:
点击“Select a page”按钮就会显示出导航,效果如下:
这就是渐进增强的典型代表——它不是一个必需的功能,但为使用小屏幕设备的用户提供了更多的第一屏内容。那我们来继续看看如何实现它。首先下载Responsive Menu脚本(https://github.com/mattkersley/Responsive-Menu),和以前一样将其(jquery.mobilemenu.js)存放在js文件夹。接下来再给每个页面的导航链接部分设置一个id:
不做上面这一步也行,但jQuery选择器搭配特定id速度比较快。接下来,在conditional.js文件中追加如下代码:
在为老版本IE按需加载Respond.js之后,我们增加了另一个检测:
这个检测是问浏览器视口是否能识别媒体查询,如果可以,那视口的最大宽度是否是600像素?如果是,则:
上面这行代码同时加载了jQuery库文件和Responsive Menu文件,
complete这块代码意思是,一旦文件下载并执行之后,运行如下代码:
这里有几个针对Responsive Menu的配置参数。最重要的第一个参数,定义了在视口多宽的情况下,将导航链接转换为下拉菜单(此处我设置为600px)。
此处我们使用Modernizr又一次保证了不需要该效果的用户不会加载多余代码,而需要的用户则会享受到这种渐进增强体验。
对于网页设计师,尤其是那些不熟悉JavaScript代码的人来说,一看到Modernizr就会心生畏惧。Modernizr当然值得深入挖掘,但这个简单的教程已经足够说明Modernizr的用处了,它在你将来的响应式项目中一定会大显身手。 9.5 高分辨率设备(未来趋势) 设备及其性能总是与时俱进。事实上,我们不仅仅要面对不同的视口尺寸,还得考虑高分辨率显示屏。iPhone 4是第一款被广泛使用的高分辨率设备。它的屏幕大小为960乘以640像素,分辨率为每英寸326个像素,是上一个版本iPhone(iPhone 3GS)及2011年的15" MacBook Pro笔记本分辨率的两倍。预计其他设备,从平板电脑到笔记本电脑再到台式机都会跟风。幸好,我们的响应式工具已经提供了方法,可以为这类设备提供增强支持。
假设我们要为使用高分辨率设备的用户加载一个高分辨率版本的网站标志图片。最近在重新设计个人网站http://www.benfrain.com时,我就遇到了这种情况。我的网站标志区域的代码如下:
对应的CSS规则如下:
最初显示效果如下:
看起来很好,但我想让标志在高分辨率设备上也尽可能清晰。所以,我制作了两个新版本的图片(一个用于默认状态,一个用于悬停状态),图片尺寸是原来的两倍,然后将其分别命名为logo2@x2.png和logo2Over@x2.png。之后在CSS中追加如下代码:
上面的媒体查询匹配最小设备像素比为1.5的设备。因此,像iPhone 4以及后续出现的高分辨率设备就会使用该媒体查询内的样式。你可能注意到样式中包含了-webkit-前缀。和以前一样,记得针对各种设备添加对应的私有前缀。
现在,在高分辨率设备上就会显示对应的高分辨率标志图片,效果如下:
无法否认,修改前后的差别微不足道。你最好还是使用真机亲身体验一下那种微妙的差别,图片的细节越丰富,在高分辨率屏幕上显示的效果也就越清晰。
使用这个技巧时需要慎重。图片尺寸越大,文件体积也越大,所需的加载时间会更长,所以再重申一遍:你可以这么做,但不一定应该这么做。
另外,如果浏览器支持可缩放矢量图形(SVG),那使用该技术替代图片可以解决我们目前面临的很多图片缩放问题。顾名思义,可缩放矢量图形能生成可任意缩放但显示清晰的矢量图片。不过,媒体查询和SVG对嵌入在页面中的高分辨率图片无能为力。在这种情况下你需要考虑基于JavaScript的解决方案。 9.6 小结 本章,我们分析了渐进增强与优雅降级的本质区别。随后使用垫片脚本让老版本IE可以识别媒体查询,从而使我们的设计在这些老弱浏览器中也能响应。接着,我们学习了使用Modernizr根据一系列功能检测按需加载CSS和JavaScript文件,从而为缺少某个特性的浏览器提供垫片脚本,以及额外或独立的样式。最后,我们还简单介绍了在不久的将来会极为常用的CSS3技巧,为相应的设备提供更好的增强体验。
此时此刻,关于制作响应式网站或Web应用所需的技术和工具,相信我都已经讲到了(但愿如此)。
我坚信,对目前的大多数网站来说,采用HTML5和CSS3的响应式网站设计,绝对是最佳方案。只要对现有的工作流程、实际做法和开发技巧稍作调整,就可以制作出快速、灵活、易维护的网站,最重要的是,无论在何种视口下网站都能表现完美。
随着移动设备的日益普及,我们之前从未预见到的新设备也将陆续加入上网冲浪的队伍。响应式设计无疑为我们提供了一套可靠且面向未来的方法,让我们的响应式网站无论在任何设备、任何视口中,也无论是否在线,都能快速响应。