语义
HTML没有给我们提供大量的标签去使用。其可选择的数量就像是街边的小商店而不是沃尔玛。
我们有段落,列表和标题,但是我们不具有事件,新闻故事,或者说是配方。HTML提供给我们一个元素用于字符串的缩写标记,但是没有提供我们一个元素用于数字的价格标记。
显然,从各种各样惊人的网站就可以看出,这一限制并没有得到很好的解决。虽然HTML并没有提供我们一个明确的元素用于内容价格的标记,但是他现在也已经变得十分灵活以至于“足够好”。
这里套用Winston Churchill经常说的一句话,HTML是尝试过的标记形式中最糟糕的一种。
可扩展性
其他的标记语言允许你创建你想要的任何元素。在XML之中,如果你想创建一个 event
元素或者一个 price
元素,你可以直接去创建。其缺点在于你必须告诉解析器 event
或者 price
的含义。HTML中有限的元素限制就成为了一个优点,因为用户代理知道每一个元素的含义。浏览器有一个内置的对HTML的理解。所以我们自定义元素名称是不被允许的。
HTML 提供了一个方便的例外条款,它允许网页设计者向元素添加更多的语义值:class
属性。这个属性允许我们向元素添加特殊的实例标签,使其成为一个特殊的类或者元素类型。
关于这一点,你可能会说“等等,是不是CSS中的类?”你只是说对了一半,CSS类选择器只是使用class
属性的一个例子,并不是使用class
的唯一原因。类也可以在脚本中使用。如果类名遵守商定的约定,他们甚至可以在浏览器中使用,如微格式(microformats)。
微格式
微格式是一组由社会商定的公约。这些格式使用class
属性来弥补HTML的一些漏洞:用于详细联系的 hCard,用于事件的 HCalendar,用于新闻故事的 hAtom。因为类名已经被社会商定,所以现在的解析器和浏览器扩展根据这些特定的模式进行工作。
微格式的设计已经被限制。他们不能尝试解决每一个可能的用例。相反,他们的目标是“低果实”,即用20%的努力就可以解决80%的问题。决定果实的质量,如“语义化标签”是十分简单的,仅仅了解已经被标记的内容就可以。换句话说就是,道路已经被平铺了。
是不是听起来很熟悉?HTML5的设计理念和微格式十分类似。事实上,我所描述的由社区商定的微格式的约定可以很容易的被应用到HTML5之中。
沸腾的海洋
开发微格式进程方式的模板应用到HTML5的开发当中可能并不能满足每个人的要求。但是80/20的法则对于class命名足矣,对于世界上最好的标记语言是不是最好的呢?
有些人认为,HTML需要具有无限的扩展性。这就意味着他不能很好地解决大多数的用户问题。语言应该可以解决用户的每一个问题。
也许对于这种可扩展性最有说服力的论据就是John Allsopp在“Semantics in HTML5”中定义:
我们不需要在HTML词汇中添加特定的术语,我们需要添加一种机制,允许需要的语义被添加到文档中。
现有的技术已经可以做到这一点。RDFa 允许作者在HTML文档中嵌入自定义词汇。但是不同于微格式只可以使用已经约定好的类名,RDFa 可以使用多种格式进行命名。所以微格式可能使用这样子的标记<h1 class="summary">
,而RDFa则可以使用<h1 property="myformat:summary">
这种方式。
毫无疑问,RDFa的功能更为强大,但是他的表现是需要代价的。与HTML的简单相比,RDFa的命名空间引入了格外复杂的一层。
对于命名的争论并不稀奇。在几年前的一篇博客中,Mark Nottingham 讲述了潜在的破坏性的副作用:
关于HTML扩展,我发现的有趣点是命名空间是没有必要的;Netscape增加了
blink
,MSFT增加了marquee
,等等。从一开始我就提出在HTML中添加命名空间在不同浏览器之中将具有不合法化和制度化,而这种差异使用同一种方案是不能解决的。
不是无限的可扩展性,这是基于社区共识最有力的论据。
HTML5可能会以某种方式对固有语义进行扩展。class
属性依然存在,所以微格式将继续工作。HTML5也可能与RDFa进行兼容,或者使用自己的“微”词汇。
在这两种情况下,大多数的网页设计者对这种可扩展性可能并不感兴趣。真正重要的由社区商定并由浏览器厂商实现的固有语义。
新元素
HTML5 引入了一些新的内联元素,来完善我们固有的span
, strong
, em
, abbr
等元素。奥~ 现在我们不称之为内联元素了,取而代之,他们现在是“文本级语义”。
mark
在浏览搜索的结果列表中,你会经常看到每一个搜索结果中会突出显示搜索词。你可以使用span
元素对每个实例进行标记,但是span
只是语义的拐杖,你可能会在样式上投入更多的精力。
你可以使用em
或者strong
,但是这并不具有语义化。你不想再搜索词上添加任何标记只是希望其以某种方式突出显示。
添加mark
元素:
<h1>Search results for 'unicorn'</h1>
<ol>
<li><a href="http://clearleft.com/">
Riding the UX <mark>unicorn</mark>
across the rainbow of the web.
</a></li>
</ol>
mark
元素对其内容赋予任何重要性,仅仅是突出显示。规范解释为mark
是指“文字标注或由于关联与另一个上下文,强调引用”
mark
元素也可以在非搜索环境中使用,但是我还没有想到一个很好的使用环境。
time
hCalendar是最流行的微格式之一,因为它触及了一个非常普遍的库:标记了事件,所以用户可以直接将它们添加到日历之中。
hCalendar中最棘手的一个问题就是日期和时间是以机器可读的方式被描述的。人类喜欢的描述方式为5月25或者下一个星期三,但是在IOS中机器解析的格式为:YYYY-MM-DDThh:mm:ss
。
微格式社区想出了一些解决问题的对策,如使用abbr
元素:
<abbr class="dtstart" title="1992-01-12">
January 12th, 1992
</abbr>
如果abbr
元素的使用方式令你感到恶心,使用一些类-值 模式也可以打破机器解析的方式。在HTML5中,time
元素的使用解决了这个问题。
<time class="dtstart" datetime="1992-01-12">
January 12th, 1992
</time>
time
元素可以被用于日期,事件或者是两者的结合:
<time datetime="17:00">5pm</time>
<time datetime="2010-04-07">April 7th</time>
<time datetime="2010-04-07T17:00">5pm on April 7th</time>
meter
meter
元素可用于测量的标记。提供测量的最大值和最小值进行测量值的缩放。
<meter>9 out of 10 cats</meter>
如果你不想暴露最大值,你可以使用max
属性代之。
<meter max="10">9 cats</meter>
相应的还有一个min
属性。同时你也可以使用high
,low
和optimum
属性。如果你愿意,你甚至可以使用value
属性隐藏隐藏其自身的测量值。
<meter low="-273" high="100" min="12" max="30" optimum="21" value="25">
It's quite warm for this time of year.
</meter>
progress
你可以使用meter
元素对已测量值进行很好地解释。你也可以使用progress
元素对正在改变的值进行说明:
Your profile is <progress>60%</progress> complete.
同样的,如果你想使用,这里也具有min
,max
以及value
属性:
<progress min="0" max="100" value="60"></progress>
progress
元素与DOM脚本结合使用是最有用的。你可以使用Javascript动态更新值,在对Ajax文件上传时便于浏览器可以及时向用户传达进度。
结构体
早在2005年,谷歌就做了一些研究,在网页平铺的道路上可以找出什么样的“语义化标签”呢?
解析器浏览了超过十亿的网页和表格中最常见的类名。结果令人十分吃惊。header
, footer
, 以及 nav
的类名最为普遍。这些新兴的语义很好地映射到了HTML5引入的新结构元素之中。
section
section
元素用于组合一些主题相关的内容。这听起来很像用作通用容器的div
元素。不同之处在于div
没有语义,他不能告诉你内容是什么。相对而言,section
元素可以明确地告诉你其内部相关内容。
你可能可以使用section
元素来替代div
元素,但是替换之前记得提醒自己“所有的内容是否相关?”
<section>
<h1>DOM Scripting</h1>
<p>The book is aimed at designers rather than programmers.</p>
<p>By Jeremy Keith</p>
</section>
header
HTML5规范中描述header
元素为“一组解释性或导航型性的条目。”这听起来很合理。一般这部分内容我希望去报头中寻找,同时header
一次常被用来报头的代名词。
HTML5之中的header
元素与普遍接受的header
或者masthead
单词之间存在关键区别。
网页中通常只有一个报头,但是文档中可以有多个header
元素。例如,你可以在section
元素中使用header
元素。事实上,你应该在section
元素内使用一个header
元素。规范中描述:section
元素作为“主题内容的分组,典型的需要一个标题。”
<section>
<header>
<h1>DOM Scripting</h1>
</header>
<p>The book is aimed at designers rather than programmers.</p>
<p>By Jeremy Keith</p>
</section>
header
通常出现在在文档或者section
的头部,但是这并不是必须的。它是由介绍的内容以及是否具有导航作用来决定的,而不是其位置决定的。
footer
类似于header
元素,footer
元素听起来也是由其位置决定的,但是和header
一样,不具有决定性。相反,footer
元素中应该包含类如此类信息:作者、出版权信息以及相关内容信息,等等。
footer
这个词可以很好的在网页设计者心中留下一个映射。但是不同的是,我们在整个文档中只使用一个fooetr
,但是HTML5允许我们在section
中使用footer
元素。
<section>
<header>
<h1>DOM Scripting</h1>
</header>
<p>The book is aimed at designers rather than programmers.</p>
<footer>
<p>By Jeremy Keith</p>
</footer>
</section>
aside
像header
元素匹配报头部分,aside
元素匹配侧边栏部分。但是,这里我所提及的aside
与位置无关。仅仅因为一些内容出现在主内容的左边或者右边不足以使用aside
元素。再次强调,它与内容相关,与位置无关。
aside
元素应该被用于无关内容。如果你有你认为应该与主内容分开的内容,那么aside
元素是你应该正确考虑使用的元素。询问你自己aside
元素中的内容是否可以被独立开来而不会影响文档或者section
中主内容的含义。
Pullquotes是关于无关内容的一个很好例子。这部分内容的存在是很好的,但你也可以删除它们而不会影响对主要内容的理解。
请记住,仅仅因为你的视觉设计需要一些内容在侧边栏出现并不一定意味着aside
元素是正确的包含元素。 例如,侧边栏部分出现一个作者的介绍是很常见的。 类似于这种数据使用footer
元素是最适合的--规范明确提到作者的信息适合于使用footer
元素(FIG 5.01)。
百分之九十的情况下,你可能在内容的头部使用header
元素,在内容的底部使用footer
元素,在侧边栏使用aside
元素。但是不要迷惑,站住头脚,坚持那剩余的百分之十。
nav
nav
元素最贴近你所想象的样子。它通常包含一个用于导航的链接列表。
事实上,我需要向你进行阐清事实。nav
元素适用于主要的导航信息。仅仅因为一组链接列表的组合不足以使用nav
元素。另一方面,仅仅立足于导航内容,那么几乎所有的内容都可以使用nav
元素。
很多时候,nav
元素常出现在header
元素中。当你认为header
元素被用于导航条目时,这是有道理的。
article
想到将header
,footer
,nav
,aside
元素指定为section
的组成部分是十分有帮助的。section
元素被认为是相关内容的通用块,而header
,footer
,nav
,aside
是特定种类的相关内容块。
article
元素是另外一种特殊类型的section
。常被用来自包含内容。最先最棘手的问题是什么是“自包含(self-contained)”。
询问自己是否愿意以RSS或者Atom的提要形式摘要内容。如果这种情况内容依旧有意义,那么article
元素很可能就是正确的使用元素。事实上,article
元素就是专门为摘要设计的。
如果你在article
内使用time
元素,你可以选择使用pubdate
布尔属性表明它包含的出版日期:
<article>
<header>
<h1>DOM Scripting review</h1>
</header>
<p>A small lighthouse for what has been a long and sometimes dark voyage for JavaScript.</p>
<footer>
<p>Published
<time datetime="2005-10-08T15:13" pubdate>
3:13pm on October 8th, 2005
</time>
by Glenn Jones
</p>
</footer>
</article>
如果你在一个article
内使用多个time
元素,你只可以使用一个pubdate
属性。
article
元素适用于博客文章,新闻报道,评论或者论坛帖子等等。它涵盖了hAtom微格式完全相同的用例。
HTML5规范远不止于此。它也声明了article
元素适用于自包含的窗口小部件:股票行情,计算器,钟表,天气窗口小部件等。现在article
元素涵盖微软网页快讯的所有用例。
我的直观理解是article
元素应该被应用到被称为“小部件”的构建之中。话又说回来,无论是article
还是部件都是可包含摘要类型的内容。
重要的问题是article
和section
元素十分相似。唯一的区分点在于是否自包含。如果有一些硬性规定,那么决定使用哪种元素就会变得十分简单。所以这就是问题的突破口。你可以在一个article
中使用多个section
元素,也可以你也可以在一个section
中使用多个article
,你也可以嵌套使用section
或者article
。这取决于给定的情况下使用哪种元素更具有语义化。
取代 div?
HTML5给我们提供的元素屈指可数,如上所述。如果你在构建一个传统的网站,例如博客,使用他们就会变得十分方便。大多数的博客设计由一个头部,紧接着是一系列文章,侧边栏内容以及一个页脚组成。如下所示:
现在你可以使用一些更精准的语义结构元素来替换之前使用的div
元素。但是不要过度使用,如果你现在使用的某些div
,以后也将继续使用。不要仅仅是因为新鲜而去替换你原先的div
元素。要记得去考虑它的内容构造。
这些新元素的创造不仅仅用来取代div
元素,它们的产生是为了浏览器更好地去解析你的内容。
内容模型
以前的标记元素分为两类:行内元素和块元素。HTML5提供了更为精准的分类。
内联元素现在被称为“文本级语义”的内容模型。许多块元素被“内容分组”所取代,如:段落,列表项,div
等等。表单有自己独立的内容模型。图片、音频、视频以及画布被称为“嵌入式内容”。新的结构元素被称为一种全新的内容模型--“区域内容”。
区域内容
它可以使用标题元素h1~h6
创建HTML文档的一个大纲。例如,如下示例的结构标记:
<h1>An Event Apart</h1>
<h2>Cities</h2>
<p>Join us in these cities in 2010.</p>
<h3>Seattle</h3>
<p>Follow the yellow brick road to the emerald city.</p>
<h3>Boston</h3>
<p>That's Beantown to its friends.</p>
<h3>Minneapolis</h3>
<p>It's so <em>nice</em>.</p>
<small>Accommodation not provided.</small>
这个示例提供给我们的大纲如下:
这种方式看起来很好。标题元素下面的任何内容都假定与此标题相关。
让我们看一下最后的small
元素。它应该与整个文档相关。但是浏览器无法解析。这里无法判断small
元素是不是隶属于“Minneapolis.”。
HTML5的区域内容可以让你从头到尾很明确的划分相关的内容。
<h1>An Event Apart</h1>
<section>
<header>
<h2>Cities</h2>
</header>
<p>Join us in these cities in 2010.</p>
<h3>Seattle</h3>
<p>Follow the yellow brick road.</p>
<h3>Boston</h3>
<p>That's Beantown to its friends.</p>
<h3>Minneapolis</h3>
<p>It's so <em>nice</em>.</p>
</section>
<small>Accommodation not provided.</small>
现在可以很明显的看出small
元素隶属于标题“An Event Apart” 而不是
现在可以很明显的看出small
元素隶属于标题“An Event Apart” 而不是“Minneapolis.”。
我甚至可以进一步细化此内容,将每一个城市放置在自己的section
元素之中:
<h1>An Event Apart</h1>
<section>
<header>
<h2>Cities</h2>
</header>
<p>Join us in these cities in 2010.</p>
<section>
<header>
<h3>Seattle</h3>
</header>
<p>Follow the yellow brick road.</p>
</section>
<section>
<header>
<h3>Boston</h3>
</header>
<p>That's Beantown to its friends.</p>
</section>
<section>
<header>
<h3>Minneapolis</h3>
</header>
<p>It's so <em>nice</em>.</p>
</section>
</section>
<small>Accommodation not provided.</small>
最后得到的大纲是一致的:
大纲算法
目前为止,与之前的HTML版本相比,新出现的区域内容并没有给我们提供很多功能。这里有一个小秘密:在HTML5之中,每一个区域内容都有其自己独立的自包含大纲。这就意味着你无需再继续跟踪一开始你使用的标题元素:
<h1>An Event Apart</h1>
<section>
<header>
<h1>Cities</h1>
</header>
<p>Join us in these cities in 2010.</p>
<section>
<header>
<h1>Seattle</h1>
</header>
<p>Follow the yellow brick road.</p>
</section>
<section>
<header>
<h1>Boston</h1>
</header>
<p>That’s Beantown to its friends.</p>
</section>
<section>
<header>
<h1>Minneapolis</h1>
</header>
<p>It's so <em>nice</em>.</p>
</section>
</section>
<small>Accommodation not provided.</small>
在之前的HTML版本中,这会产生错误的大纲,如下所示:
HTML5中产生的大纲是准确的,如下所示:
hgroup
可能存在这种情况,你想要使用多个标题元素,但是你不想要其内容出现在不同的大纲之中。这时hgroup
元素就可以很好的满足你的需求。
<hgroup>
<h1>An Event Apart</h1>
<h2>For people who make websites</h2>
</hgroup>
在这种情况下,二级标题内容“For people who make websites”仅仅是一个口号而已。在hgroup
元素中,只有第一标题才是大纲的组成部分。当然,这里的第一标题不仅限于h1
:
<hgroup>
<h3>DOM Scripting</h3>
<h4>Web Design with JavaScript and the Document Object Model</h4>
</hgroup>
根区域
存在一些元素在大纲中是不可见的,换句话说,不管你是要多少多少此类元素,他们都不会出现在你的大纲之中。
blockquote
、fieldset
以及td
元素对大纲算法都是免疫的。这些元素被称为"区域根"--不要与区域内容相混淆。
可移植性
由于每一个区域内容都可以生成自己的大纲,你现在得到的标题级别就不仅仅局限于h1~h6
。这里你的标题级别就不存在限制了。更重要的是,你可以开始考虑以一种模式化的方式创建内容。
假设这里有一个名为“Cheese sandwich.”的博客。在HTML5之前我需要考虑博客的背景决定如何使用标题元素,如果是该信息位于页眉那么就使用h1
以下的标题对博客进行标注。
<h1>My awesome blog</h1>
<h2><a href="cheese.html">Cheese sandwich</a></h2>
<p>My cat ate a cheese sandwich.</p>
但是如果我在自己的网页中发布了此博客,那么此时的博客标题应该使用一级标题:
<h1>Cheese sandwich</h1>
<p>My cat ate a cheese sandwich.</p>
在HTML5中,我并不需要担心标题的使用。在这个示例中,我仅仅需要使用区域元素--article
:
<article>
<h1>Cheese sandwich</h1>
<p>My cat ate a cheese sandwich.</p>
</article>
现在内容真的更为便携。不管他出现在页眉或者页脚位置都变得无关紧要:
<h1>My awesome blog</h1>
<article>
<h1>Cheese sandwich</h1>
<p>My cat ate a cheese sandwich.</p>
</article>
HTML5的大纲算法产生的大纲如下:
样式域
每一种区域内容都有其自己独立的大纲,这一事实使它可以与Ajax完美结合使用。强调,这句话出于Web应用程序规范。
试图将一个内容由一个文档转移到另一个之中会出现许多问题。父元素中的CSS规则也会被应用到插入的内容之中。这是目前在网络上散播一些小部件的挑战之一。
HTML5提供了scoped
属性来解决此类问题,这可以被应用到样式之中。在此属性中的所有样式仅仅适用于其包含的区域内容:
<h1>My awesome blog</h1>
<article>
<style scoped>
h1 { font-size: 75% }
</style>
<h1>Cheese sandwich</h1>
<p>My cat ate a cheese sandwich.</p>
</article>
在这个示例中,只有第二个h1
元素具有font-size: 75%;
样式。当然这仅仅在理论上讲得通,目前还没有得到任何一种浏览器的支持。
总结
文章介绍了HTML5的一些自带义语义化的标签,对于语义化争议还是非常的大,但如果你的HTML结构写得更具语义化,还是有足多的好处,比如你团队的成员更易读懂你的代码。当然还有很多同学担心这些标签浏览器对他的支持力度如何?其实很多HTML5标签都已运用到实际项目中。
如果你对这方面有更深的理解,欢迎在下面的评论中与我们一起分享你的见解。
本文根据@JEREMY KEITH的《HTML5 For Web Designers:Semantics》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://html5forwebdesigners.com/semantics/。
如需转载,烦请注明出处:http://www.w3cplus.com/html5/semantics-tags.html