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。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论