刚才,我说doctype不是为浏览器写的,这样说大多数情况下没有问题。在有一种情况下,你使用的doctype会影响到浏览器,相信在座诸位也都知道。但在这种情况下,Doctype并非真正用得其所,而只是为了达到某种特殊的目的才使用doctype。当初微软在引入CSS的时候,走在了标准的前头,他们率先在浏览器中支持CSS,也推出了自己的盒模型——后来标准发布了,但标准中使用了不一样的盒模型。他们怎么办?他们想支持标准,但也想向后兼容自己过去推出的编码方式。他们怎么知道网页作者想使用标准,还是想使用他们过去的方式?
于是,他们想出了一个非常巧妙的主意。那就是利用doctype,利用有效的doctype来触发标准模式,而不是兼容模型(quiks mode)。这个主意非常巧妙。我们今天也都是这样在做,在我们向文档中加入doctype时,就相当于声明了“我想使用标准模式”,但这并不是发明doctype的本意。这只是为了达到特殊的目的在利用doctype。
下面我出一道有奖抢答题,听好:“一分钟后开始,如果你手快的话,第一个在文档前面写完doctype html,然后我用Internet Explorer打开你的文档,会触发它的标准模式,还是会触发它的兼容模式?”
答案是,这是在Internet Explorer中触发标准模式的最少字符数目。我认为这也说明了HTML5规范的本质:它不追求理论上的完美。HTML5所体现的不是“噢,给作者一个简短好记的doctype不好吗?”,没错,简短好记是很好,但如果这个好记的doctype无法适应现有的浏览器,还不如把它忘了更好。因此,这个平衡把握得非常好,不仅理论上看是个好主意——简短好记的doctype,而且实践中同样也是个好主意——仍然可以触发标准模式。应该说,Doctype是一个非常典型的例子。
还有一个例子,同样可以说明规范是如何省略不必要的复杂性,避免不必要的复杂性的。如果前面的文档使用的是HTML 4.01,假设我要指定文档的字符编码。理想的方式,是通过服务器在头部信息中发送字符编码,不过也可以在文档这个级别上指定:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
同样,我也不会把这行代码背下来。我还想省下自己的脑细胞去记点别的更有价值的东西呢。不过,如果我想指定文档使用UTF-8编码,只能添加这行代码。这是在HTML 4.01中需要这样做。要是你在XHTML 1.0指定同样的编码,就得多敲一下键盘,因为你还得声明meta元素位于一个开始的XML标签中。
<?xml version="1.0" encoding="UTF-8" ?> |
在HTML5中,你要敲的字符只有:
<meta charset="utf-8"> |
简短好记。我能背下来。
同样,这样写也是有效的。它不仅适用于最新版本的浏览器,只要是今天还有人在用的浏览器都同样有效。为什么?因为在我们把这些meta元素输入浏览器时,浏览器会这样解释它:“元数据(meta)点点点点点,字符集(charset)utf-8。”这就是浏览器在解释那行字符串时真正看到的内容。它必须看到这些内容,根据就是伯斯塔尔法则,对不对?
我多次提到健壮性原理,但总有人不理解。我们换一种说法,浏览器会想“好,我觉得作者是想要指定一个字符集……看,没错,utf-8。”这些都是规范里明文规定的。如今,不仅那个斜杠可以省了,而且总共只要写meta charset=”utf-8″就行了。
关于省略不必要的复杂性,或者说避免不必要的复杂性的例子还有不少。但关键是既能避免不必要的复杂性,还不会妨碍在现有浏览器中使用。比如说,在HTML5中,如果我使用link元素链接到一个样式表,我说了rel=”stylesheet”,然后再说type=”text/css”,那就是重复自己了。对浏览器而言,我就是在重复自己。浏览器用不着同时看到这两个属性。浏览器只要看到rel=”stylesheet”就够了,因为它可以猜出来你要链接的是一个CSS样式表。所以就不用再指定type属性了。你不是已经说了这是一个样式表了嘛;不用再说第二次了。当然,愿意的话,你可以再说;如果你想包含type属性,请便。
同样地,如果你使用了script元素,你说type=”text/javascript”,浏览器差不多就知道是怎么回事了。对Web开发而言,你还使用其他的脚本语言吗?如果你真想用其他脚本语言,没人会阻拦你。但我要奉劝你一句,任何浏览器都不会支持你。
愿意的话,你可以添加一个type属性。不过,也可以什么都不写,浏览器自然会假设你在使用JavaScript。避免-不必要的-复杂性。
支持已有的内容
支持已有的内容。这一点非常重要,因为很多人都认为HTML5很新,很闪亮;它应该代表着未来发展的方向,应该把Web推向一个新的发展阶段。这就是HTML5,对吗?显然,我们都会考虑让Web的未来发展得更好,但他们则必须考虑过去。别忘了W3C这个工作组中有很多人代表的是浏览器厂商,他们肯定是要考虑支持已有内容的。只要你想构建一款浏览器,就必须记住这个原则:必须支持已有的内容。
下面我们就来看一个HTML5支持已有内容的例子。
这个例子展示了编写同样内容的四种不同方式。上面是一个img元素,下面是带一个属性的段落元素。四种写法唯一的不同点就是语法。把其中任何一段代码交给浏览器,浏览器都会生成相同的DOM树,没有任何问题。从浏览器的角度看,这四种写法没有区别。因而在HTML5中,你可以随意使用下列任何语法。
<img src="foo" alt="bar" /> <img src="foo" alt="bar"> <IMG SRC="foo" ALT="bar"> <img src=foo alt=bar> |
好了,看到这几段代码,恐怕有人会说“不对不对不对。其中只有一个是对的,另外三个——说不好。”不对,应该给属性值加引号!拜托,我们可是一直都给属性值加引号的!元素名大写对吗?这种做法10年不是就被抛弃了吗?
看到HTML5同时允许这些写法,我心里忍不住一阵阵想吐。我写了10年的XHTML 1.0,已经非常适应严格的语法了。但你必须明白,站在浏览器的角度上,这些写法实际上都是一样的。确实没有什么问题。
还有谁也感到不舒服了吗?有谁看到这些之后想“噢,这不是乱写嘛,这样做不对”?只有我这样想吗?还有别人吗?
但是,HTML5必须支持已经存在的内容,而已有的内容就是这个样子的。不是吗?根据伯斯塔尔法则,浏览器没有别的选择。
有人可能会说“这样不行。我觉得语言本身应该提供一种开关,让作者能够表明自己想做什么。”比如说,想使用某种特定的语法,像XHTML,而不是使用其他语法。我理解这些人的想法。但我不赞成在语言里设置开关。因为我们讨论的只是编码风格或者写作风格,跟哪种语法正确无关。对于像我们这样的专业人士,我认为可以使用lint工具(一种软件质量保证工具,或者说是一种更加严格的编译器。它不仅可以象普通编译器那样检查出一般的语法错误,还可以检查出那些虽然完全合乎语法要求,但很可能是潜在的、不易发现的错误),对其他技术我们不是也在使用lint工具嘛。
比如说对JavaScript使用lint工具。JavaScript同样也是比较混乱、不严谨的例子,但它非常强大,原因恰恰是它混乱、不严谨,而且有很多不同的编码方式。在JavaScript,你可以在每条语句末尾加上分号,但不是必需的,因为JavaScript会自动插入分号……是不是听起来有点不好接受?
正因为如此,才有了像JSlint这样的工具,在道格拉斯·克劳克福德(Douglas Crockford)的网站jslint.org上面。有个网页上写着“JSlint可能会伤害你的感情。”但这确实是个非常棒的工具,它可以把JavaScript代码变得完美无瑕。如果你通过JSlint运行JavaScript,它会告诉你“好,你的JavaScript代码有效,但写法不妥。你这种编码风格啊,我不喜欢。不赞成你这样写。这样写不好。”特别是对团队,对于要使用统一的编码风格的团队,JSlint是非常方便的工具。
我个人认为,不仅对团队来说,就算是你自己写代码,也要坚持一种语法风格。从浏览器解析的角度讲,不存在哪种语法比另一种更好的问题,但我认为,作为专业人士,我们必须能够自信地讲“这就是我的编码风格。”然而,我不认为语言里应该内置这种开关。你可以使用lint工具来统一编码风格。现在就来说说lint工具。大家可以登录htmllint.com,在其中运行你的HTML5文档,它会帮你检查属性值是否加了引号,元素是否小写,你还可以通过勾选复选框来设置其他检查项。
但这不意味着拒绝粗心大意的标记,做不做清理完全取决于你自己。我说过,因为浏览器必须支持已有的内容,HTML5自然也不能例外。归根结底还是伯斯塔尔法则。我们始终离不开伯斯塔尔法则。
解决现实的问题
HTML5的另一个设计原理是解决现实的问题。显而易见的是,解决各种问题的格式和规范已经比比皆是了,因此在我看来,这个原理其实是要解决理论问题,而非解决现实的问题。这条设计原理是要从理论上承认人们普遍存在的问题,消除敏感问题。
下面我来举个例子。相信这个例子有不少人都遇到过。假设我使用HTML 4或XHTML 1,页面中已经有了一块内容,我想给整块内容加个链接,怎么办?问题是这块内容里包含一个标题,一个段落,也许还有一张图片。如果我想给它们全部都可以点击,必须使用3个链接元素。于是,我得先把光标放在标题(比如说h2元素)中,写一个链接标签,然后再选中所有要包含到链接里面来的文本。接着,再把光标放在段落里,写一个链接标签,然后把段落中的文本放在链接里……
<h2><a href="/path/to/resource">Headline text</a></h2> |
在HTML5中,我只要简单地把所有内容都包装在一个链接元素中就行了。
<a href="/path/to/resource"> |
没错,链接包含的都是块级元素,但现在我可以用一个元素包含它们。这样太好了。因为我碰到过类似的情形,必须给几个块级元素加上相同的链接,所有能这样写就太好了。为此,我就非常欢迎HTML5这个新标准。
它解决了一个现实的问题。我敢说在座不少朋友都曾遇到过这个问题。