1. 引子:腾讯视频首页的条件注释
做前端的,见到优秀的网站就会去查看源代码,这是一种病,更是一种职业素养。腾讯作为中国最财大气粗的互联网公司,自是让前端开发者们趋之若鹜(我也不例外)。腾讯前端团队里高手云集自是不必说了,查看、学习腾讯各大网站源代码也是表达膜拜之意、向大神看齐的一种方式。前两天浏览腾讯视频,顺手看了一下首页的源代码,发现下面几行:
<!--[if (IE 9)|(IE 10) ]> <meta name="application-name" content="腾讯视频" /> <meta name="msapplication-tooltip" content="腾讯视频" /> <meta name="msapplication-task" content="name=首页;action-uri=/;icon-uri=/favicon.ico"/> <meta name="msapplication-task" content="name=电影;action-uri=/movie/;icon-uri=/favicon.ico"/> <meta name="msapplication-task" content="name=电视剧;action-uri=/tv/;icon-uri=/favicon.ico"/> <meta name="msapplication-task" content="name=综艺;action-uri=/variety/;icon-uri=/favicon.ico"/> <meta name="msapplication-task" content="name=动漫;action-uri=/cartoon/;icon-uri=/favicon.ico"/> <meta name="msapplication-starturl" content="/" /> <![endif]-->
做前端的应该都知道条件注释里的元数据是用来实现 IE9+ 的固定网站功能的,不过我们现在要讨论的是条件注释。
<!--[if (IE 9)|(IE 10) ]> 的意思是如果是 IE9 或者 IE10 则渲染注释里面的代码。这在 IE 9 里完全没问题,因为 IE9 支持条件注释,用户将网站固定到任务栏后,在图标上点击右键就能看到几个频道的链接,点击可以直接打开 IE 进入相应链接。那 IE10 呢?
没有类似右图的链接,因为 IE10 已经删除条件注释支持(IE 被埋怨了那么多年,也想拜托前端开发恶梦的称号,做符合 Web 标准的现代浏览器),条件注释被当作普通注释处理,而且指定使用可用的最新模式解析文档(IE10里当然是IE10模式最新):
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
所以在 IE9 中工作正常的固定网站功能,到 IE10 里就失效了。解决的一种方式是指定使用 IE9 模式——捡了芝麻丢了西瓜,所以还是干脆删除条件注释吧。
[caption id="attachment_416" align="alignnone" width="730"] IE10 中,条件注释被当作普通注释处理,忽略注释里的内容[/caption]
[caption id="attachment_417" align="alignnone" width="660"] IE9 模式下,可以正确处理条件注释[/caption]
2. 条件注释详解
只有 IE5 - 9 支持条件注释。考虑到 IE 特别是 IE9 以前的版本在国内巨大的市场份额,详细了解一下条件注释还是很有必要的。使用条件注释的好处
比起脚本探测浏览器,条件注释有以下好处:- 对客户端影响小。不支持条件注释的浏览器会忽略条件注释里内容,节省客户端资源。
- 不需要额外的脚本。可以和其他浏览器探测技术结合。
- 使用探测逻辑分离代码。使用条件注释可以将代码分离成更小、更简单的片段,易于理解和维护;可以根据浏览器版本按需载入代码。
- 跨浏览器。(跨毛?连自家的IE10都不支持了)
条件注释语法
注释类型 | 语法 |
---|---|
标准 HTML 注释 | <!-- Comment content --> |
downlevel-hidden 不支持条件注释的浏览器隐藏, 支持的根据表达式判断 | <!--[if expression]> HTML <![endif]--> |
downlevel-revealed 不支持条件注释的浏览器显示, 支持的根据表达式判断 | <![if expression]> HTML <![endif]> |
条件表达式由以下项目组合而成:
项目 | 示例 | 注释 |
---|---|---|
IE | [if IE] | 如果浏览器为IE则匹配 |
value | [if IE 7] | 浏览器版本,整数或浮点数 |
WindowsEdition | [if WindowsEdition] | Windows 7 上的 IE8 通过 "WindowsEdition" 匹配用户Windows版本 |
value | [if WindowsEdition 1] | 匹配Windows 版本(指专业版、旗舰版、服务器版等信息,而不是Vista、Win7这些信息,具体可参考 GetProductInfo function) |
true | [if true] | true值,支持条件注释的浏览器 |
false | [if false] | false值,不支持条件注释的浏览器 |
条目 | 示例 | 说明 |
---|---|---|
! | [if !IE] | NOT 运算符,放在表达式前取表达式相反的值 |
lt | [if lt IE 5.5] | 小于运算符,如果低于指定参数则返回 ture |
lte | [if lte IE 6] | 小于等于运算符(lte = less-than or equal) |
gt | [if gt IE 5] | 大于运算符 (gt = greater-than) |
gte | [if gte IE 7] | 大于等于运算符 (gte = greater-than or equal) |
( ) | [if !(IE 7)] | 子表达式运算符,和布尔值运算符结合创建更复杂的表达式 |
& | [if (gt IE 5)&(lt IE 7)] | AND 运算符,所有表达式为真时返回真 |
| | [if (IE 6)|(IE 7)] | OR 运算符,任何一个子表达式为真时返回真 |
Downlevel-hidden 条件注释
<!--[if IE 8]> <p>Welcome to Internet Explorer 8.</p> <![endif]-->不支持条件注释的浏览器作普通注释处理忽略,IE5 - 9 根据值来判断是否显示注释内容。
Downlevel-revealed 条件注释
<![if lt IE 8]> <p>Please upgrade to Internet Explorer version 8.</p> <![endif]>不支持条件注释的浏览器及 IE5 - 7 显示注释内容。但是这样不符合 Web 标准,无法通过验证,改进一下:
<!--[if lt IE 8]><!--> <p>Please upgrade to Internet Explorer version 8.</p> <!--<![endif]-->
条件注释示例
<!--[if IE]><p>你在使用IE5 - 9</p><![endif]--> <![if !IE]><p>You are not using Internet Explorer.</p><![endif]><!--[if IE 7]><p>Welcome to Internet Explorer 7!</p><![endif]-->
<!--[if !(IE 7)]><p>You are not using version 7.</p><![endif]--><!--[if gte IE 7]><p>You are using IE 7 or greater.</p><![endif]-->
<!--[if (IE 5)]><p>You are using IE 5 (any version).</p><![endif]-->
<!--[if (gte IE 5.5)&(lt IE 7)]><p>You are using IE 5.5 or IE 6.</p><![endif]-->
<!--[if lt IE 5.5]><p>Please upgrade your version of Internet Explorer.</p><![endif]--><!--[if true]>你的浏览器支持条件注释<![endif]-->
<![if false]>你的浏览器不支持条件注释<![endif]><!--[if true]><![if IE 7]><p>This nested comment is displayed in IE 7.</p><![endif]><![endif]-->
<!--[if WindowsEdition 1]>
<p>你在使用旗舰版的Windows(蛋疼?)</p>
<![endif]-->
via About conditional comments - MSDN
3. 条件注释的一些应用
IE Mobile
<!--[if IEMobile]> Displayed only on Internet Explorer Mobile on Windows Phone 7 <![endif]--><!--[if !IEMobile]>-->
Not IEMobile
<!--<![endif]-->
测试了一下,貌似 Windows Phone 7.8 上的 IE9 已经不支持条件注释了,而市场使用 Windows Phone 7.0 的用户基本可以忽略,所以针对 IEMobile 的条件注释基本没用了(via )。
条件类名
以前条件注释结合 CSS 使用时,一种是以内嵌的方式把特定样式写进条件注释里,这样不太符合表现和内容分离的原则;另一种是使用条件注释引入特定的样式表,这样又会增加 http 请求。近几年,条件类名开始流行。<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->这是 html5-boilerplate 中条件类名,使用时可以根据实际情况修改类名。这样的好处可以把所有样式都写到一个样式表,使用类名为特定浏览器定义样式,无需再使用那些晦涩难辨、无法通过验证的 hack 了。
关于条件类名的发展过程,可以参考 Conditional Stylesheets vs CSS Hacks? Answer: Neither!;对于是不是每个版本的 IE 都应该添加相应的类名,也有争议,可以看一下 Don’t Use Conditional Comments to Create Classes for IE7+。个人觉得还是根据项目需要吧,一堆没用的类名加在上面也蛮恶心的。
条件类名一些其他资源:
- In Thesis (php) sorta, uses UA sniffing. :/
- in Slim (rails) by helloluis
- in Jade (node) by kmiyashiro & monokrome
- in HAML (rails) by gf3
- thematic by scott nix
IE6 背景图缓存
<!--[if lte IE 6]> <script type="text/javascript"> document.execCommand("BackgroundImageCache",false,true); </script> <![endif]-->