关于HTML条件注释你可能不知道的一些事儿
最近经常看到类似这样的HTML代码片段,很多前端开发人员应该都熟悉:
1 <!--[if lt IE 7]> <html class="ie6"> <![endif]-->
2 <!--[if IE 7]> <html class="ie7"> <![endif]-->
3 <!--[if IE 8]> <html class="ie8"> <![endif]-->
4 <!--[if gt IE 8]><!--> <html> <!--<![endif]-->
这段代码包含了一些条件注释,它会根据浏览器的不同选择性地给<html>标记添加(或不添加)一个包含浏览器版本信息的class属性。具体来说,对于IE5-IE8,<html>标记会增加一个class属性,属性值由IE的版本来决定。对于IE9、较IE9更高的IE版本以及非IE浏览器,<html>保持原样。这样,我们就可以针对IE5-IE8这些老式浏览器来编写只对它们生效的CSS代码,比如:
1 .foo { color: red;}
2 .ie6 .foo { color: yellow;}
3 .ie7 .foo { color: blue;}
进一步地,我们就可以避免类似这样的CSS hack:
1 /***** 选择器(Selector) Hacks ******/
2 .foo { color: red;}
3 * html .foo { color: yellow; }
4 *:first-child+html .foo { color: blue; }
5
6 /***** 属性(Attribute) Hacks ******/
7 .foo { color: red; *color: blue; _color: yellow;}
使用“HTML条件注释”来避免CSS hack,这是一种目前比较流行而且比较安全稳定的技术。这种技术的代码有很多版本,再介绍一个比较有意思的,来自于HTML5 Boilerplate:
1 <!--[if lt IE 7]> <html class="lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
2 <!--[if IE 7]> <html class="lt-ie9 lt-ie8"> <![endif]-->
3 <!--[if IE 8]> <html class="lt-ie9"> <![endif]-->
4 <!--[if gt IE 8]><!--> <html> <!--<![endif]-->
文章写到这里,我感觉,写了这么多,全是大家可能都知道的事儿。其实,这篇文章的主题,不是讨论条件注释和CSS hack孰优孰劣,也不是讨论哪种条件注释方案最好,我想讲一些条件注释技术实现代码的细节。
我们聚焦文章的第一段示例代码。看这段代码的第一行:
<!--[if lt IE 7]> <html class="ie6"> <![endif]-->
就算我们没有条件注释的知识,凭字面我们也能大概猜出这行代码的作用:在IE6或更低版本的浏览器中,这行注释会被解析成<html class="ie6">。在其他IE浏览器(IE7-9)中,它会被解析成空。在非IE浏览器中,毫无疑问,它会被当做我们所熟知的一般HTML注释,它会被忽略。事实上,浏览器的确是这样做的。
在IE条件注释的概念体系中,一共有两种条件注释类型。这种条件注释的类型被称作downlevel-hidden。它的语法是这样的:
<!--[if expression]> HTML <![endif]-->
语法的细节说明可以查看文章结尾的参考资源。
在将要讨论语法怪异的第四行代码之前,让我们先思考一个问题。凭借现有的HTML条件注释的特性,我们能够实现“IE9、较IE9更高的IE版本以及非IE浏览器中,<html>保持原样”这一目标吗?
1 <!--[if gt IE 8 | !IE]> <html> <![endif]-->
2 ...
3 </html>
这样可以吗?不可以。IE9浏览器中,注释条件为真,代码会解析为<html>。但是,IE10以及非IE浏览器中,这行代码会被忽略,这会导致HTML文档缺少起始<html>标记。从高亮的HTML上,我们可以明显地看出来。特别强调一下,微软已经宣布,IE10不再支持条件注释。
凭借现有的HTML条件注释的特性,我们没有办法实现我们的目标。怎么办?
在IE条件注释的概念体系中,还有另外一种条件注释类型叫downlevel-revealed,它的语法(具体语法细节请查看文章结尾的参考资源)是这样的:
<![if expression]> HTML <![endif]>
很幸运,我们可以利用downlevel-revealed类型的条件注释来实现之前的目标。
<![if gt IE 8]> <html> <![endif]>
对于这行代码浏览器的解析是这样的:在IE9中,浏览器会识别出这是一段条件注释,并且条件为真,所以这段代码会解析为<html>。在IE8-IE5中,注释的条件为假,故解析为空。在IE10以及非IE浏览器中,<![if gt IE 8]> 以及 <![endif]>会被当做无法识别的标签,整条代码最终被解析为<html>。感谢微软,我们的目标实现了。
但是,这段代码,是无法通过(X)HTML验证的。为了能够通过通过(X)HTML验证,我们可以使用一种改进的语法,代码可以修改为:
<!--[if gt IE 8]--> <html> <!--[endif]-->
我们增加了4个 --,这使得代码看起来非常的怪异,这与downlevel-hidden类型有点差别,但它能被IE5-IE9识别为条件注释别并处理。对于改进过的代码,IE5-IE8的解析方式不变。IE10以及非IE浏览器会把<!--[if gt IE 8]--> <!--[endif]-->当作一般注释来解析,最终结果不变。但是,IE9出问题了:注释条件仍然为真,解析结果却变成了--> <html>。我们再次改进一下语法,代码可以修改为:
<!--[if gt IE 8]<!--> <html> <!--[endif]-->
我们只是增加了一个 <! 。 对于再次改进过的代码,IE5-IE8的解析方式不变。IE10以及非IE浏览器会把<!--[if gt IE 8]<!--> <!--[endif]-->当作一般注释来解析,最终结果不变。IE9的问题被修复了。
至此,我们所得到这行代码,其实就是示例中的第四行代码。
关于HTML条件注释你可能不知道的一些事儿的更多相关文章
- 您可能不知道的CSS元素隐藏“失效”以其妙用——张鑫旭
一.CSS元素隐藏 在CSS中,让元素隐藏(指屏幕范围内肉眼不可见)的方法很多,有的占据空间,有的不占据空间:有的可以响应点击,有的不能响应点击.后宫选秀——一个一个看. { display: non ...
- swift与OC之间不得不知道的21点
swift与OC之间不得不知道的21点 自6月的WWDC大会上由苹果的大神Chris Lattner向我们首次展示swift至今已经大半年时间了,虽然绝大部分软件公司代码里还都见不到一丁点swif ...
- 你所不知道的15个Axure使用技巧
你有用原型开发工具吗?如果有,那你用的是Axure还是别的? 从以前就喜欢使用Axure,主要是觉得它能清楚的表达设计的思路,还有交互的真实再现,能让看的人一目了然,昨天看了这篇博文,便更加确定Axu ...
- Java你可能不知道的事(3)HashMap
概述 HashMap对于做Java的小伙伴来说太熟悉了.估计你们每天都在使用它.它为什么叫做HashMap?它的内部是怎么实现的呢?为什么我们使用的时候很多情况都是用String作为它的key呢?带着 ...
- 你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)
前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程, ...
- 你所不知道的五件事情--java.util.concurrent(第二部分)
这是Ted Neward在IBM developerWorks中5 things系列文章中的一篇,仍然讲述了关于Java并发集合API的一些应用窍门,值得大家学习.(2010.06.17最后更新) 摘 ...
- 不知道的陷阱:C#委托和事件的困惑
转载网址:http://www.cnblogs.com/buptzym/archive/2013/03/15/2962300.html 不知道的陷阱:C#委托和事件的困惑 一. 问题引入 通常,一 ...
- 你所不知道的 CSS 滤镜技巧与细节
承接上一篇你所不知道的 CSS 动画技巧与细节,本文主要介绍 CSS 滤镜的不常用用法,希望能给读者带来一些干货! OK,下面直接进入正文.本文所描述的滤镜,指的是 CSS3 出来后的滤镜,不是 IE ...
- 漫谈程序员(十一)老鸟程序员知道而新手不知道的小技巧之Web 前端篇
老鸟程序员知道而新手不知道的小技巧 Web 前端篇 常充电!程序员只有一种死法:土死的. 函数不要超过50行. 不要一次性写太多来不及测的代码,而是要写一段调试一段. UI和编码要同步做. 多写注释方 ...
随机推荐
- ASP.NET - 视图状态概述
本文转载自dodream 视图状态是 ASP.NET 页框架用于在往返过程之间保留页和控件值的方法.在呈现页的 HTML 标记时,必须在回发过程中保留的页和值的当前状态将被序列化为Base64 编码字 ...
- Ninject学习笔记<一>
本文转载自永远的阿哲 如果给您带来不便请联系博主. Ninject是一款.Net平台下的开源依赖注入框架.按照官方说法,它快如闪电.超级轻量,且充分利用了.Net的最新语法,使用Lambda表达式代替 ...
- Rehashing
The size of the hash table is not determinate at the very beginning. If the total size of keys is to ...
- 查看ecshop广告位对应的广告详细信息
在ecshop的日常应用中,如果添加了很多广告位和广告.然而时间一长又不知道哪些广告是有用的,哪些广告是没用的,广告对应的链接是什么.倘若人工一个个查看又特费时费力不讨好.因而想想办法用sql一次性查 ...
- Android drawable的自动缩放
今天在写程序时发现,一张图片被自动放大了,后来发现,这张图片放在了drawable-zh文件夹下,这个文件夹没有指定屏幕密度!于是将drawable-zh改为drawable-zh-nodpi,问题解 ...
- Java入门的程序汇总
Java入门的基础程序,虽然很简单,也要多练习,下面有重点的总结一下 1.HelloWorld这个不说了 2.常量与变量部分 基本数据类型使用 public class Javashujuleixin ...
- Java for LeetCode 199 Binary Tree Right Side View
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...
- 双系统重装windows后修复UBUNTU的GRUB
1.问题背景 本子是win7和ubuntu10.04双系统,用的还算好,虽然只有在用QQ的时候还会用到win7,但还是保留windows.可是几天 前,win7突然总是蓝屏.死机,更重要是的背景变成黑 ...
- mysql自增字段重排 或 归零
由于删除了某些记录行,所以自增字段不连续了.重排或归零的方法:方法1:truncate table 你的表名//这样不但重新定位自增的字段,而且会将表里的数据全部删除,慎用!方法2:delete fr ...
- 信与信封问题(codevs 1222)
题目描述 Description John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出.但是,第二天John的儿子Small John将这n封信都拿出了信封.不幸的是,Small Joh ...