精通 HTML5 语义标准和排版(一)
零、简介
除非你度过了一个没有数字的假期,否则你会听到很多关于 HTML5 的讨论。作为一名 web 专业人员,很明显,理解 HTML5 不仅有益,而且非常重要。在过去的几年中,Web 的未来已经从根本上改变了方向,从 XHTML 到 HTML5,这意味着有新的概念要学习,但也有过时的编码实践要忘记。
有时 HTML5 在它所包含的内容上看起来神秘而模糊,为 HTML5 给出一个定义可以把你引向许多方向。这本书将全面涵盖 HTML5 的状态,并为您提供它所涵盖的技术的坚实基础。在深入细节之前,先简要介绍一些基本概念,重点是为 HTML 打下坚实的基础。在 web 表单、多媒体和改进的网站语义等领域,有许多新的元素和属性要介绍。还有一些现在已经过时的元素和属性,作为一名专业的 web 开发人员,你绝对不会再使用它们了(对吗?).当前 HTML 元素的正确用法,新的和旧的,在清晰易懂的摘要中显示出来。CSS 和 JavaScript 是桌面上的下一个主题,两者都通过它们与 HTML 的关系进行了讨论和探索。
此外,为了给你理论和实践知识,使你的网络实践更上一层楼,相关的基础主题,如数字颜色,媒体格式,响应设计,甚至三角学,都将涉及到 HTML5。
虽然 HTML5 将在未来几年内成型,但您会发现它已经为今天要构建的许多下一代 web 应用奠定了基础——这些 web 应用可能就是您自己构建的!
这本书是给谁的?
HTML5 精通面向任何熟悉 HTML、CSS 和 JavaScript 的人,他们有兴趣更深入地理解定义这些语言的规范。HTML5 规范非常庞大。通过这本书的页面来接近它将会很快让你跟上速度,并且作为一个跳板来把你的 HTML 知识带到一个新的高度。
HTML、CSS 和 JavaScript 可能对你来说很熟悉和容易,但是你一定会发现让你惊讶的隐藏的宝石。了解这些微妙之处将对你成为 HTML5 大师大有帮助。你将带着基础知识和必要的手段去寻找更高层次的概念,以便跟随现代网络发展的趋势。
这本书的结构是怎样的?
这本书首先讨论了导致 HTML5 成为当今最热门的 web 开发趋势的令人惊讶的错综复杂的历史。对于那些 HTML 新手来说,在浏览 HTML5 的亮点和自 HTML 4.01 以来的变化之前,先介绍一些基础术语。在这个 HTML5 状态的高级视图之后,后续章节深入到感兴趣的特定领域,提供了 HTML 元素和相关技术的全面概述。
本书的前三分之一将为您提供 HTML5 中可用内容的坚实基础,并帮助您为当今的互联网组织和构建更好的网页。在第二章中,您将了解所有元素上的全局属性,以及 HTML5 的新内容模型类别,这些类别将每个 HTML 元素组织成一组重叠的组。接下来的两章将深入探讨这些元素。特别注意页面的语义结构。在对 HTML 中的所有元素有了广泛的理解之后,本书的后三分之一将深入探讨 web 表单的元素,接下来是将多媒体嵌入 web 页面的元素。
本书的后三分之一深入到与 HTML 紧密相关的概念中,但与用于构建页面的 HTML 元素是分开的。从第六章开始,讨论 HTML 和 CSS3 的关系。还展示了基本的 CSS 概念,并演示了 CSS3 样式的关键新功能的示例。接下来,介绍 HTML5 JavaScript APIs 的概念。构建了一个在 web 浏览器中探索 JavaScript 的小模板,并通过具体的实例进行了演示。这本书以面向移动设备的 web 开发的未来之路作为结尾,并以即将到来的和正在发展的 HTML5 技术的总结作为结尾,最后,涵盖了不属于 HTML5 但通常使用并与之相关联的技术(如地理定位 API)。
这本书可以从头到尾读一遍,也可以放在你的电脑上作为特定元素和概念的参考。为了从本书中获得最大收益,我建议您遵循(WHATWG) HTML 规范的智慧,在讨论如何阅读文档以获得最大收益时,它是这样表述的:
“[它]应该从头到尾,多次阅读。然后,至少要倒着读一遍。那么应该通过从目录中随机选择部分并遵循所有的相互参照来阅读”
最后,这本书在 html5mastery.com 有一个附带的网站,在那里你可以找到相关的信息和链接。
本书中使用的约定
这本书使用了几个毫无价值的约定:
-
除非另有说明, HTML5 和 HTML 指的是 HTML 语言的最新实现。
-
现代浏览器被认为是谷歌 Chrome 11 或更新、Mozilla Firefox 4 或更新、Safari 5 或更新、Opera 11 或更新、微软 Internet Explorer 9 或更新。
-
单个 HTML 元素可以用“元素”或不用“元素”来引用,例如,
pre和pre元素都引用 HTML<pre>。 -
除非显示或暗示,否则假定本书中的所有 HTML 示例都嵌套在有效 HTML5 文档的
body中。 -
除非另有说明,否则任何 CSS 和 JavaScript 代码都被假定分别位于外部样式表和外部脚本文件中。
-
包含在一大段代码中的代码片段可以包括省略号字符
(...),其用于表示在特定代码片段之前和/或之后有未示出的代码。这里有一个例子:`...The head area and the rest of the body aren't shown, but they should be there if you wrote this code yourself.
...` -
Lastly, it should be noted that the JavaScript examples shown have variables and functions that are created in a global scope for the sake of brevity and clarity. This likely will be fine for most uses, but in a truly professional best practice environment, the scope of a particular set of JavaScript variables and functions would likely be placed inside a custom object to prevent naming conflicts between different scripts running on the same page.
随着手续的方式,让我们开始掌握 HTML5 的道路。
一、入门:过渡到 HTML5
HTML5 是十多年来对 HTML 规范的第一次重大更新。十年了!这是多么大的更新啊!令人兴奋的新特性,如多媒体支持、交互性、更智能的表单和更好的语义标记都出现了,但这并不是从零开始的。你所熟悉和喜爱的 HTML 仍然在那里等着你去使用,XHTML 也是如此。使用 HTML5,您可以(几乎)以任何您熟悉的方式对页面进行编码,但是对您的技能的掌握来自于对您所编码的内容的历史、约定和语义(含义)的理解,以及来自于创建驱动您的创作风格的明智决策。
这一章将解开 HTML5 的基础,这样你就能明白它是从哪里来的;接下来是基本 HTML 术语和概念的概述。接下来,总结 HTML5 的主要变化,并说明 XHTML 的状态。最后,总结了目前使用 HTML5 特性的一些工具,并列出其他 web 开发人员工具。
HTML5 = HTML
HTML5
HTML 代表什么?"超文本标记语言."这对你来说可能并不陌生。那么,HTML5 代表什么呢?“超文本标记语言,第 5 版”听起来很合理。这确实是一个合理的假设,但是 HTML5 有一段复杂的历史,这使得这个术语不像第一眼看上去那么清晰。对某些人来说,它可能意味着 HTML 规范的最新草案,对其他人来说,它可能意味着一个更大规范的稳定快照,或者一个标签来描述一整套新的和不太新的技术,这些技术旨在使 Web 成为一个更丰富、更吸引人的交互场所。
在 HTML5 之前
还记得 Web 2.0 吗?这个在 2000 年代中期变得突出的术语成了从对网络的只读心态到允许积极参与其内容的转变的同义词:读/写网络。随着这个词在越来越多的会议和其他地方出现,最终成为主流媒体的流行语,它的确切含义变得模糊不清。YouTube 等公司似乎拥有这种能力,但毫无疑问,全世界的网站开发者都面临着向困惑的客户解释他们网站的陈旧 HTML 无法被 Web 2.0 取代的难题。这个词在很大程度上象征着什么是可能的,什么是时尚的,什么是新的。实际上,它包含了以新方式重新包装的旧技术,比如用 JavaScript 和 XML(后来被称为 Ajax)异步加载内容。事实上,在读/写环境中与网站交互的能力已经存在多年了。
或许最重要的是,这个时期象征着给网络带来新生命的渴望。自 1999 年 HTML 4.01 发布以来,万维网联盟(W3C)一直没有发布 HTML 规范的推荐标准。几年后,W3C 忙于 XHTML 1.0 和 XHTML 2.0 的工作,这是一种重新设计的基于 XML 的 HTML 风格,旨在实现更严格、更一致的编码实践。由于 XHTML 是基于 XML 的,网页作者需要严格遵守规范;否则,页面在无效时不会加载。希望世界上的网站作者会采用这个新标准,清除网络上的畸形标记。但是有一个问题。世界没有改变。
为什么 XHTML 2.0 死亡而 HTML5 兴盛
当 Web 2.0 被创造出来的时候,对使用 XHTML 的批评越来越多。为了适应不支持 XHTML 的浏览器,web 页面作者编写 XHTML 标记,但继续使用 Internet MIME 类型“text/html”而不是正确的“application/xhtml+xml”从他们的 web 服务器提供页面,这将告诉浏览器它正在查看 xml。作者会构建他们认为有效的 XHTML 页面,但不会以 XML 的形式提交页面。他们不会看到任何编码错误在他们构建的浏览器中具体化。这一点变得没有意义了。如果没有被这样检查,XHTML 语法并不重要。2004 年,一个名为 Web 超文本应用工作组(WHATWG)的组织成立了,它的目标是发展优秀的旧 HTML,而不是像 W3C 当时那样专注于 XHTML。WHATWG 开始开发一个名为“Web 应用 1.0”的规范,最终成为 HTML5!
WHATWG 理念
WHATWG 在开发 HTML 规范时采用了不同于 W3C 的方法。WHATWG 的目标不是推动一些人认为的对 web 标准的严厉改革,而是逐步发展 HTML,保持与以前版本 HTML 的向后兼容性。这是有意义的,因为 web 浏览器并不使用版本化的方法来呈现 HTML 他们试图呈现扔给他们的任何 HTML,而不考虑网页作者试图遵循的规范版本(HTML 3.2、HTML 4.01 等等)。WHATWG 开发了一个规范,该规范主要由实际使用的内容驱动——哪些 web 浏览器供应商正在实现,哪些 web 页面作者正在使用。2007 年,三家网络浏览器制造商,Mozilla 基金会、苹果公司和 Opera 软件公司,要求 W3C 采用 WHATWG 的成果作为进一步开发 HTML 的起点。不久之后,W3C 采纳了这个建议,在 HTML 休眠了近十年之后,下一个版本 HTML 5(带空格)正在进行中。2009 年,在八个工作草案和没有发布候选版本之后,W3C 决定结束 XHTML 2,专注于 HTML5(最终简称为 HTML 5)。(参见图 1-1 了解这段复杂历史的图表。)此外,XHTML 以 XHTML5 的形式存在,它遵循 XML 语法规则,而不是 HTML 规则。在 HTML 语法中,XML 语法的一部分是允许的(例如,空元素上的尾随斜线,比如<br />);然而,这些都不是真正的 XHTML 文档,除非它们是使用 MIME 类型“application/xhtml+xml”或“application/xml”从服务器显式传递的(稍后将详细介绍)。
图 1-1。HTML 错综复杂的演变。注意,HTML2 规范出现在 W3C 形成之前。
html 5 的当前状态
“规范永远不会完整,因为它在不断发展。”
WHATWG 常见问题
HTML5 做好了吗?不要。可以用了吗?没错。WHATWG 和 W3C 继续联合开发 HTML5 规范;然而,WHATWG 不再把它的规范称为 HTML5(你只是认为你在用你的脑袋去思考历史!).除了专注于编纂已经在实践中的东西之外,WHATWG 和 W3C HTML 工作组之间的另一个哲学差异是,WHATWG 将不再开发 HTML 的某个版本,该版本将在某个时候关闭以供进一步修订。W3C 将每个版本视为当前开发状态的“快照”,而 WHATWG 的目标是为 HTML 制定一个规范,并根据需要进行更新。这反映了开发依赖于特定 HTML 版本的特性的 web 应用的趋势,而是直接依赖于检查对特性的支持,而不管所使用的 HTML 规范的“版本”。
在 WHATWG 看来,W3C HTML5 规范([w3.org/TR/html5/](http://w3.org/TR/html5/))是 WHATWG 监管的“活规范”中最稳定特性的快照。这个规范简称为 HTML ( http://whatwg.org/html/)。HTML 规范被进一步嵌套为 web 应用 1.0 的子集(图 1-2 ),它包括与 HTML 分离的 Web 开发相关的规范,如 Web Workers(并发 JavaScript 线程)、Web Storage(用于在 Web 应用中存储数据)等。你可以在[www.whatwg.org/specs/web-apps/current-work/complete.html](http://www.whatwg.org/specs/web-apps/current-work/complete.html)查看完整的网络应用规范。
***图 1-2。*HTML/HTML 5 如何融合在一起
这让我回到了 HTML 历史之旅的起点。HTML5 是什么?根据上下文:
- It is the latest version of HTML specification.
- It is a stable snapshot of the earlier version of the HTML specification.
- This is a label used to describe the contemporary state of open web technology.
就本书中提到的 HTML5 的含义而言,这里所涵盖的本质上是当前规范的快照。这意味着它可能领先于 W3C 的 HTML5 规范,但在本书付印时可能落后于 WHATWG 的“活规范”。这就是网络的本质。它在不断进化。对于本书所涵盖的内容,前面提到的第三点可能是最好的。这本书着眼于网络发展的当代状态。HTML5 是网络的新潮流,就像之前的 Web 2.0 一样。在适当的地方,相关的 API 和技术也包括在内,不管它们来自于什么样的规范,但是它们工作的总体框架是 HTML 的下一个版本——HTML 5!(或者你想怎么称呼它都行。)
html 5 文档的剖析
既然您已经充分掌握了通向 HTML5 的道路,那么让我们来看一个简单的文档,这样您就可以看到事情是如何变化的。打开您喜欢的代码编辑器,创建一个新的 HTML 文件,将其另存为index.html,并键入以下内容:
`
HTML5 ApprenticeHello World
`惊喜!你会注意到这个文档不仅熟悉,而且比你以前见过的 HTML 更简单。很干净紧凑,是吧?好的,请随意在您的首选浏览器中打开它,看看文本 Hello World 是否真的会显示在您的页面上。如果你能说出前面代码中的每一个术语,请随意跳过下一节;否则,请继续阅读,复习基本的 HTML 术语和概念。
HTML 术语和概念
为了避免混淆本文中所指的内容以及您可能在其他地方读到或听到的内容,了解一些基本术语和概念非常重要。使用正确的术语很重要,既可以避免混淆,也有助于自己和他人的理解。
HTML 文档由三个基本构件组成:元素、属性和文本(内容)。考虑以下用于创建链接的 HTML 代码片段:
<a href="about.html">About Us</a>
元素是a(代表锚)元素,它生成指向另一个 HTML 页面或其他资源的可点击链接。元素由两个标签组成:开始标签 ( <a>)和结束标签 ( </a>),也称为开始和结束标签或开始和结束标签。属性是作为名称/值对出现在开始标记内的文本。最后,文本内容(在浏览器中查看该代码时出现在网页中)出现在开始和结束标签之间(参见图 1-3 )。
***图 1-3。*显示元素、属性、内容和标签的典型 HTML 片段的基本组件。
元素
元素是 HTML 中的M;它们是指示 web 浏览器如何处理某些内容的标记。每个元素都有一个关键字,比如body、p、a、img等等,这些关键字定义了它是什么(分别是主体元素、段落元素、锚元素和图像元素)。不同的元素定义了不同类型的行为,比如创建链接、嵌入图像等等。您可能听说过元素与标记同义,但是元素和标记的含义略有不同。标签是要素的部分,如图图 1-5 所示。大多数元素由开始标签、一些内容和结束标签组成,但是根据标签的不同,这三个组件中的一个或多个可能会缺失。许多元素可以包含嵌套在其中的任意数量的其他元素,这些元素又由标记和内容组成。下面的例子显示了两个元素:p元素,它是从第一个开始尖括号(<)到最后一个结束尖括号(>)的所有内容,以及em元素,它包含开始<em>标记、结束</em>标记以及它们之间的内容。
<p>Here is some text, some of which is <em>emphasized</em></p>
请注意,<em></em>元素完全包含在<p></p>元素中;以任何其他方式嵌套它们都不是正确的语法,如下所示:
<p>Here is some text, some of which is <em>emphasized</p></em>
内容内部没有明确的层次结构,当 web 浏览器决定如何显示这些文本时,这是一个问题。web 浏览器仍将分析并尝试显示此代码,但它不是符合 HTML 规范的代码。
空元素
并非所有元素都包含文本内容。例如,img、br和hr元素分别将图像、新行和水平线插入页面。除了占用空间之外,他们不会修改页面上的某些内容。这样的元素不是容器元素——也就是说,你不用写<hr>some content</hr>或<br>some content</br>。相反,任何内容或格式都是通过属性值来处理的(将在下一节中解释)。在 HTML 中,空元素(也称为 void 元素)被简单地写成<img>、<br>、<meta>或<hr>,没有结束标记。在 HTML、XHTML 的 XML 形式中,一个空元素需要一个空格和一个尾随斜杠,像<img />、 1 <br />、<meta /> 1 或者<hr />;这些被称为自动关闭标签。由于 HTML5 灵活的语法,这两种形式都可以使用。我倾向于 XHTML 语法,因为斜杠的存在使标记是合并在一起的开始和结束标记变得更清楚。
属性
属性出现在元素的开始标记中。一个特定的元素通常包含该元素特有的属性,以及对许多不同元素都有效的属性。它们用于在某些方面修改元素的行为。它们可以被认为是键/值配对,就像key="value"一样,其中一个特定的元素将有许多已定义的属性(键),这些属性可以被设置为某个值。例如:
实际上,img 和 meta 元素也有属性。
<a href="contact.html">Here is some text that links to a contact page.</p>
属性href出现在开始标记中,并被设置为一个定制值,该值改变 HTML 元素的行为。根据属性的不同,它可能包含多个空格分隔的值。您可能已经遇到过的其他属性可能包括alt、src和title,但是还有更多属性。与元素一样,HTML5 在编写属性时同时支持 HTML 和 XHTML 语法;在 HTML 语法中,它们不需要用引号括起来,所以<a href=contact.html>是可以接受的,但是,和元素一样,我相信 XHTML 语法更清楚,因为引号让你知道这个值是一个自定义值,就像你说过的话的引号。XHTML 语法清晰性的一个例外可能是它处理某些称为布尔属性的属性的方式。布尔属性仅根据它们在元素中的存在与否来提供效果。在 XHTML 中,要求每个属性都有一个值,它们的值要么留空,要么设置为与属性名相同的文本字符串。例如,video元素包含一个名为autoplay的属性;在 XHTML 语法中,这看起来像是<video autoplay="">或<video autoplay="autoplay">。然而,在更宽容的 HTML 语法中,这可以写成<video autoplay>。在这种情况下,HTML 格式更加清晰。既然 HTML5 支持这两种语法,那么用哪种方式写就看你自己了!
家
安全地描述完元素、标签和属性之后,让我们把注意力转向另一个您应该知道的与 HTML 相关的概念:DOM。文档对象模型 (DOM)是一个特别在讨论 JavaScript 与页面的关系时突然出现的术语,作为一名网页设计者/开发者,这是一个需要注意的重要术语。这是什么?这是将文档(在本例中是 HTML 页面)表示为由连接节点组成的树状数据结构的标准方式。节点表示页面中的元素、属性和文本内容。通过其分支的树状结构,DOM 描述了节点是如何相互嵌套的。
DOM 及其包含的节点在 JavaScript 中被表示为对象,这些对象描述了特定节点包含的内容和能够做的事情。使用 JavaScript,可以使用点符号遍历树结构来访问页面上的各个组件。如果您不熟悉点标记法,它只是意味着 DOM 树中嵌套在另一个节点中的一个节点可以通过其包含的节点(在此上下文中称为对象)来访问,方法是提供用句点分隔的节点(对象)名称。例如,HTML 页面在 DOM 中被表示为一个名为document的对象,它包含实际的 HTML 页面内容。由于 HTML 页面包含头部和主体,因此在document对象中有一个head和一个body对象。因此,要访问 HTML 页面的body元素,应该用 JavaScript 编写以下代码:document.body。这实际上不会做任何事情;从 JavaScript 中访问了body元素,但是没有以任何方式对其进行处理。重点是页面的结构由嵌套的对象表示,每个对象都可以用一个点(句点)来访问。
一旦深入到特定的 HTML 元素,命令就会变得更加通用,因为事先不知道特定页面上有哪些元素。JavaScript 包含许多命令,可用于访问 HTML 页面主体内的内容、动态更新内容、响应事件等等。例如,要访问页面上显示的第一个 HTML 元素,可以使用document.body.firstElementChild。要访问该元素的第一个属性,可以使用document.body.firstElementChild.attributes[0]。括号中的零只是指要访问的属性的编号;0 表示 HTML 元素中的第一个属性,1 表示第二个属性,依此类推。最后,要访问这个元素的内容,可以使用下面的代码:document.body.firstElementChild.firstChild。
图 1-4 显示了一个简单网页的结构,只有一个链接在主体区域。看这个图,你会注意到顶部有一个额外的对象,叫做window。虽然可以通过document对象访问 DOM,但是document实际上包含在这个window对象中,它表示包含页面内容的 web 浏览器窗口。从技术上讲,访问 DOM 首先要通过 window对象完成,它是“根”对象,通过它可以从 JavaScript 访问网页的所有其他方面。例如,访问页面的主体可以用window.document.body或document.body来完成(在这种情况下,引用开头的window是隐含的)。
***图 1-4。*通过
HTML5 有什么新功能?
此时,您可能会问自己,“HTML5 到底有什么新功能?”首先,值得注意的是,HTML 最初被认为是一种表示文本文档的标记语言,而不是一个应用开发平台。然而,随着时间的推移,越来越多的功能被挤进了网络浏览器。在过去的十年中,HTML5 首先试图整合、记录和添加到语言中的特性。以下部分描述了一些主要变化。
向后兼容
HTML5 在大多数情况下与以前的 HTML 语法和标记形式兼容。这怎么是新的?多年来,一种“基于标准”的 web 创作方法一直强调从 HTML 语法向 XHTML 语法的过渡。正如在历史部分中所讨论的,HTML5 已经将的重点从语法上“纯粹的”基于 XML 的方法移开,取而代之的是将重点转向已经在使用的实践的更好的文档化。
错误处理
虽然网页作者可以用他们熟悉的任何方式编写文档,但是 HTML5 的一个主要变化是针对用户代理(网页浏览器制造商),而不是作者。Web 浏览器试图呈现 HTML 代码,不管它看起来像什么。由于 HTML 在实践中的灵活性,代码的结构有时会不明确。在过去,web 浏览器制造商以不同的方式处理不明确的代码,并实现不同的算法来处理不明确的 HTML(称为标签汤)。这导致不同浏览器的外观不一致。解决这个问题的一个显而易见的方法是使语言更加严格,这样网页作者就被迫以某种方式组织他们的页面。这是 XHTML1 背后的思想和努力。x;然而,另一种方法是在浏览器实现者端标准化错误的处理方式。这就是 HTML5 寻求做的事情。它试图最终记录语法中的变化应该如何处理。Web 浏览器在处理解析错误时有两种选择:要么实现 HTML5 规范中指定的规则,要么在出现第一个错误时中止处理文档。这个想法是,不同的浏览器将一致地处理相同的错误,那些没有实现错误处理行为的浏览器将停止解析 HTML,从而通知作者他们的语法有问题。
显然,对于 web 开发人员来说,如果页面没有呈现出来,就很明显有问题,但是如果页面呈现得很好,即使浏览器正在处理一个错误,也不那么明显。在这种情况下,页面被处理,但是它被认为不符合 HTML5 规范。这就是为什么 web 开发人员熟悉 HTML 中的变化以及他们不应该使用的元素和属性是非常重要的(参见本章后面的“过时功能”一节)。然而,如果有疑问,可以使用一致性检查服务,比如[html5.validator.nu](http://html5.validator.nu)或[validator.w3.org](http://validator.w3.org),根据 HTML5 规范检查提供的 HTML 代码。
简化的文档类型
HTML 通常以 doctype 声明开始。在过去,这看起来像这样:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
或者
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
doctype 声明提供了一个指示,表明您将根据什么样的文档类型定义(DTD)来编写标记。DTD 基本上是一个详细描述标记的规则和语法的页面。所以,前面列出的两行代码的区别在于,它们为不同版本的(X)HTML 指定了 DTD,一个是 HTML 4.01,另一个是 XHTML 1.0。等一下!这预示着 HTML 的世界观将它分成不同的版本。因为我们讨论的是 HTML5,它与规范的以前版本向后兼容,所有需要做的就是说页面正在显示 HTML。因此,doctype 已简化为以下形式:
<!DOCTYPE html>
这对于文档类型的简化来说怎么样?这真是再简单不过了。嗯,实际上是可能的。它可能不存在,如果它被省略,您的 HTML 页面仍然会加载,但是不要从您的 web 页面中删除这一行!
HTML 中的文档类型有两个重要目的。首先,它们通知用户代理和验证器文档是针对什么 DTD 编写的。这个动作是被动的——也就是说,每次页面加载时,您的浏览器不会去下载 DTD 来检查您的标记是否有效;只有当您手动验证页面时,它才会生效。
第二个也是最重要的实际目的是,文档类型通知浏览器使用哪种解析算法来读取文档。Web 浏览器通常有三种解析 HTML 文档的方法:
- -No quirks (or "standard") mode
- -There are quirky patterns.
- -Limited quirk (or "almost standard") pattern
为了以一种模式呈现文档,浏览器依赖于 doctype 字符串的存在、不存在或值。这就是所谓的文档类型切换,它包含在浏览器中,作为一种决定如何呈现文档的方式。假设一个作者已经包含了一个 doctype,那么这个作者知道他或她在做什么,浏览器试图以一种严格的方式(换句话说,标准模式)解释严格的标记。缺少 doctype 会触发 quirks 模式,以旧的和不正确的方式呈现标记;这里的假设是,如果作者没有包含 doctype,那么他或她可能没有编写标准标记,因此标记将被视为过去为 buggier 浏览器编写的。触发无怪癖模式还是有限怪癖模式比较微妙,取决于所选择的文档类型以及查看文档的浏览器。
提示您想让自己相信浏览器会根据文档类型的存在与否来切换解析模式吗?如果你在 Mozilla Firefox 4 中打开一个页面,并选择 Tools
Page Info,在 General 选项卡下你会看到一个呈现模式列表,显示当前用来查看页面的模式。如果您在 web 页面中添加和删除 doctype 声明,并在每个状态下检查页面信息,您将会看到浏览器正在触发不同的解析模式。或者,如果您熟悉 JavaScript,可以将以下脚本插入 HTML 页面的 head 部分:
`
alert(document.compatMode);
`
加载页面时,会弹出一个“CSS1Compat”或“BackCompat”的窗口前者意味着模式被设置为无怪癖模式;后者意味着它被设置为怪癖模式。
关于 doctype 的最后一个注意事项:为了与生成 HTML 代码并因此要求 doctype 语法看起来更像以前的遗留系统兼容,下面的 HTML5 替代 doctype 声明是可接受的:
<!DOCTYPE html SYSTEM "about:legacy-compat">
这仅提供给产生 HTML 的系统,所以作为网页作者,你不太可能使用这种声明,除非你想给你的手指一个额外的锻炼,或者向你的朋友显示你是 HTML5 的最小细微差别的大师。
简体字编码
你输入的 HTML 是文本,对吗?对你来说是的,但是对计算机来说它是以一系列的位来存储的:1 和 0。因此,一个特定的字符实际上是作为一个特定的二进制数存储的。阅读文本文档的计算机程序(如 web 浏览器)需要从根本上了解两件事:
- It should read text.
- The bits it reads are used to map to the representation of specific characters in the text.
这第二点被称为文档的字符编码。你可以把它想象成老式的电报交流系统,信息以莫尔斯电码的形式发送,然后被翻译成字母和单词。为了成功地使用莫尔斯电码传输文本,发送者和接收者都需要知道发送的点击是如何映射到特定的字母的。字符编码告诉计算机如何将它读取的位和字节翻译成字母,用于显示或其他目的。
HTML5 规范强烈建议所有 HTML 文档都有一个字符编码集。推荐的方法是让服务器在 HTTP Content-Type 头中将其作为响应头的一部分发送,但是如果这是不可能的,那么可以在 HTML 文档的头部分使用meta HTML 元素。网络上使用最广泛的字符编码系统是 UTF-8,它可以编码超过 100 万个字符,涵盖了世界上使用的大多数书面语言文字。
在 HTML 4.01 中,meta元素看起来像这样:
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
为了向后兼容,HTML5 中仍然支持这一点,但是首选的语法更短,并且包括一个新的属性charset:
<meta charset="UTF-8">
啊,这更简洁了!请记住,如果您的服务器将字符编码作为其 HTTP 响应头的一部分发送,您根本不需要这样做。
新增内容模型类别
一个内容模型用于指定特定 HTML 元素预期包含的内容种类。可以包含相同类型内容的不同 HTML 元素可以按类别分组。传统上,HTML 元素分为两类:块和内联。在 HTML5 中,这些已经显著扩展为七个主要类别:
- Metadata content
- Mobile content
- Sectional content
- Title content
- Wording content
- Embedded content
- Interactive content
block 类别大致对应于“流内容”,而 inline 类别对应于“语法内容”,以区分这个类别和 CSS 中使用的display:inline;属性。这些将在下一章进一步探讨。
新元素
HTML5 引入了大量的新元素来帮助赋予网页结构更大的意义(语义)。像header、nav和footer这样的新元素分别描述了页面标题和徽标出现的位置、主导航菜单出现的位置以及版权和法律信息出现的位置。这标准化了使用元素(比如带有id属性的div元素)创建网页区域的常见实践。例如,以前页脚部分可能是这样创建的:
<div id="footer">copyright 2011</div>
使用新的 section 标记,可以重写如下:
<footer>copyright 2011</footer>
使用这些新的结构化标签更加清晰,并且标准化了这个标签的标识符,因为一个id属性可以由不同的作者写成“page-footer”、“thefooter”等等。“语义网”旨在提供机器可读的明确定义的内容,以便更好地进行数据挖掘/搜索。旧的格式使机器无法在几个不同的网页上一致地挑选出页脚,而 HTML5 语法使它完全可以预测——当然,假设作者实际上在他们网页的适当部分使用了页脚标签。
除了新的结构元素之外,web 表单中可用的元素类型也进行了重大升级,引入了用于输入日期、URL、电子邮件地址、电话号码等的新输入类型。还引入了许多用于嵌入式和交互式内容的新元素,比如video、audio和canvas(一个可脚本化的绘图表面)。现有元素也有变化,例如重新定义了b、i和small元素的含义(语义),使它们在本质上不再是表示性的。新元素和对现有元素的更改将在接下来的章节中更详细地探讨。
微数据
这种新的添加基于注释 HTML 元素的思想,目的是将元数据添加到页面内容中,以便外部应用、聚合器和搜索引擎可以更容易地以标准化的方式处理这些内容。这个想法并不新鲜。微格式和 RDFa 是用于注释 HTML 的两种格式,但是 HTML5 引入了第三种格式:微数据(本身基于 RDFa)。微数据使用一组全局属性,这些属性可用于向页面上的内容添加额外的语义结构。
嵌入式 MathML 和 SVG
数学标记语言(MathML)和可缩放矢量图形(SVG)都是基于 XML 的标记语言,其描述规范不同于 HTML。顾名思义,MathML 用于使用正确的数学符号描述和表示数学方程。SVG 用于描述交互式和静态(非交互式)矢量图形。这两种语言都不是新的,但是由于 HTML5 可能包含 XML 样式的语法,所以这两种语言都可以嵌入到常规的 HTML 页面中。这些将在附录 a 中进一步讨论。
API
本着为 web 应用开发创建平台的精神,HTML5 引入了许多脚本应用编程接口(API)。这些包括 JavaScript API 的附加功能,允许通过它们的类来选择元素。例如,使用数组语法,class属性设置为aClass的页面上的第一个元素可以通过 JavaScript 检索,如下所示:
document.getElementsByClassName("aClass")[0]
还添加了与新元素相关的 API,比如在新的video和audio元素中控制视频和音频播放的方法。添加的其他功能包括处理拖放用户交互、访问 web 浏览器历史状态,以及将网页数据存储在缓存中以供以后在脱机状态下检索。还有许多与 HTML5 一起工作的相关 API,但实际上属于不同的规范。这一类别中值得注意的一个是地理位置 API,它提供了一种在 web 上下文中处理位置数据的方法。后面的章节将更详细地探讨这些 API。
不再符合 SGML(再次!)
坦白地说,你根本不可能注意到这种变化。最纯粹的 HTML 最初是从标准通用标记语言(SGML)发展而来的,SGML 是一种更古老的标记语言。然而,web 浏览器实现的 HTML 并不完全符合 SGML 规范,HTML5 只是将这一事实编成了法典。HTML5 的语法元素借鉴了 SGML、HTML 和 XHTML1。使它成为一种混合的语言,有自己独特的权利。
过时的功能
HTML5 中有一个“第 22 条军规”,它必须与 HTML 的旧特性保持兼容,同时不鼓励使用某些不再被认为可以接受的元素。例如,HTML 包含某些本质上是表示性的标记,这意味着它对其内容的影响是以某种方式使其外观风格化(例如,font元素)。表示性标记早已被级联样式表(CSS)所取代,所以这些特性中的大部分已经被弃用。作者不应该再使用这些元素,即使它们仍然出现在 HTML 规范中。这些元素不是简单地从规范中删除,以便用户代理(web 浏览器)在遇到它们时知道如何处理它们(例如在较旧的网页中);然而,这样的页面被认为是不符合要求的。web 浏览器将呈现它们,但是它们不符合当前的 HTML 规范。表 1-1 显示了过时元素及其替代品的清单。
除了不推荐使用的元素之外,许多属性也被归档在 obsolete 下,许多属性本质上是表示性的,很容易使用 CSS 进行模拟。见表 1-2 中 HTML5 中已被标记为过时的属性列表。它们不应该被使用。
XHTML 没了吗?
简单回答:不是。它现在被称为 XHTML5。然而,HTML5 规范规定,XHTML 不能再像 XHTML 1 那样使用 MIME 类型“text/html”。 x 。这成为现实的一个主要原因是 Internet Explorer 不会解析作为 XML 的页面,而是试图将页面下载到磁盘上,而不是显示它。然而,这不是唯一的原因。XML 的语法非常严格,最小的验证错误都会导致网页崩溃,变得不可用,整个世界都可以看到错误。因此,经常使用 XHTML 语法,但作为一种预防措施,还是以 HTML 的形式提供。
关于哑剧类型的所有这些噪音是什么?
多用途互联网邮件扩展(MIME)类型,也称为媒体类型,告诉网页它正在接收哪种数据。显然,web 浏览器想要以非常不同的方式处理图像和文本文档,所以有办法告诉它发送的是什么类型的数据是很重要的。由于 XHTML 和 HTML 看起来非常相似,所以需要告诉 web 浏览器它正在处理哪一个。如果是 XHTML,就需要使用符合 XML 规范的 XML 解析器进行解析;如果是 HTML,它需要使用符合 HTML 规范的 HTML 解析器来解析它。
在我继续之前,让我澄清一下 XHTML 和 HTML 之间的主要区别。尽管 XHTML 和 HTML 有共同的词汇表,但它们在理论上有几个优于 HTML 的地方,包括:
- Ill-formed XHTML will be found immediately, because the browser will refuse to display the page, but will display an error instead.
- XHTML provides a well-formed 2 document.
但是,除非页面使用 MIME 类型为“application/xhtml+xml”或“application/xml”的 XHTML,否则上述两点都不成立。如果您的 web 服务器为您的 web 页面提供 MIME 类型的“text/html”,那么您就不能充分利用 XHTML。
在 HTML 和 XHTML 之间抉择
那么,应该用 HTML5 还是 XHTML5 呢?这取决于您的语法偏好,以及文档中格式良好的保证对您有多重要。XML 风格的语法仍然可以在 HTML 中使用,但是不要期望它有 XHTML 的含义,除非它是这样服务的。最终,这是一个完全取决于你自身情况的判断。只是不要错误地认为,通过将页面作为 XHTML,您已经完成了创建专业的、结构良好的、语义有意义的文档所需的所有工作。
网络浏览器支持
无论你使用哪种语法,让我们来看看你如何看待你的劳动成果。随着 HTML5 的特性变得稳定,在完美的世界中,它们有望出现在您首选的 web 浏览器的最新版本中。但是,您如何知道哪些特性实际上是受支持的,哪些是不受支持的呢?在你开发的浏览器中测试代码是最可靠的选择,但是也有一些网站,比如[caniuse.com](http://caniuse.com)可以让你知道你的首选浏览器支持什么。另一个站点[html5test.com](http://html5test.com),检测用于访问该站点的浏览器中某些功能是否可用(图 1-5 )。使用不同的浏览器,您可能会看到不同的分数和摘要,突出显示并非所有功能都适用于所有主流浏览器。
我应该指出“格式良好”并不意味着“有效”例如,具有属性 mymadeupattribute="true "的标记是格式良好的,但仍然无效。
图 1-5。 [html5test.com](http://html5test.com) 谷歌 Chrome 11 的结果
由于当前的 web 浏览器并不支持 HTML5 的所有特性,所以检测对任何不会正常失败的特性的支持是一个好主意。Modernizr ( [modernizr.com](http://modernizr.com))是一个值得研究的 JavaScript 库。该库检测 HTML5(和 CSS3)特性的可用性,这些特性的存在与否作为布尔值存储在 Modernizr 库创建的 JavaScript 对象中。 3 这些值可以使用有条件的 JavaScript 代码来检查,如果特性存在就添加功能,否则,如果不存在就处理页面。例如,要检测是否支持audio元素,您可以在页面的 JavaScript 代码中编写以下内容:
// Check Modernizr object for audio Boolean value of true if (Modernizr.audio) { // Enable functionality on page for audio controls } else { // Handle lack of audio element support on the page }
如果你想了解更多关于创建检测 HTML5 特性的自定义方法,请查看马克·皮尔格拉姆在 diveintohtml5.org/detect.html…](diveintohtml5.org/detect.html)
注 Paul Irish (
[paulirish.com](http://paulirish.com))是 Modernizr 项目的首席开发人员,同时也是一个名为 HTML5 样板([html5boilerplate.com](http://html5boilerplate.com))的项目的首席开发人员,这个项目也值得一试。样板文件为 HTML5 web 项目提供了一个默认的基本模板。它包括 Modernizr 和 jQuery JavaScript 库,以及一个默认的网页结构和附加的 CSS 样式表。
网络浏览器开发工具
每个网络浏览器都使用被称为布局引擎的软件来解析 HTML 和 CSS,并将其呈现在屏幕上。不出所料,每种浏览器的功能通常都不同(尽管谷歌 Chrome 和苹果的 Safari 都使用 WebKit),这解释了对 HTML5 功能支持的差异,即使是在不同浏览器的最新版本中。因为它们是不同的,所以最好有一个可靠的浏览器内开发工具来探索和操作 HTML/CSS。在这方面,每个浏览器都有一套帮助 web 开发的工具。通常,这些工具在启用时允许右键单击页面上的内容,并且上下文菜单中会出现“检查元素”或类似的选项。检查 HTML 元素将揭示它的结构和 CSS 样式,可以在浏览器中浏览和操作(非永久性的)。这些工具还具有某种“控制台”的特性,JavaScript 代码可以使用代码console.log("message");或类似代码记录命令。主要浏览器各自的布局引擎和开发工具列表见表 1-3 。
访问 getfirebug.com 的 ?? 下载这个火狐扩展。
5 通过“开发”菜单启用,该菜单通过勾选首选项… 高级中的复选框启用。
总结
这是一条曲折的道路——经过多年的酝酿——现在我们迎来了 HTML5。越来越多的新功能正在 web 浏览器中出现,当然今天大部分功能都在这里供我们使用!现在,您已经了解了 HTML5 如何融入更大的画面,并探索了哪些发生了变化,哪些保持不变,是时候深入了解如何最有效地使用新功能的细节了。你只是触及了表面!
二、为正确的工作使用正确的标签
有了 HTML5,web 开发人员就有了更多的 HTML 元素来为他们的页面添加含义。引入了许多新元素来更精确地标记、定义和组织内容。理解何时何地使用 HTML 中的许多元素对于创建逻辑结构化、符合规范、语义丰富的网页是必不可少的。
本章将概述 HTML5 中可用的元素,包括新添加的和从 HTML 4.01 继承的元素。你可能会想,这可能是一项艰巨的任务!毕竟,有一个 800 多页的规范涵盖了所有这些内容(完整 WHATWG HTML 规范的当前长度,截至 2011 年 7 月)。为了更容易地处理这个长长的元素列表,我们将研究集合中的元素,并用单独的章节来进一步研究特别感兴趣的元素组。HTML 中的元素可以松散地分为以下几组:
- Root element:
htmlelement is independent because it is the only element that contains all other elements in the document.- Document metadata and script elements:
headelements contain metadata of documents, CSS styles and JavaScript in many cases.- Document subsection element: body element encapsulates the content of the page, and the new semantic subsection element defines the header, footer, article and other chapters on the page. These will be discussed in detail in Chapter 3.
- Content grouping elements: The content of a specific part of a webpage can be organized into paragraphs, lists, block references, charts, etc.
- Text-level semantic elements: A single text string can be marked with words or sentences to provide fine-grained control over the meaning of content, such as separating time, abbreviation and superscript from adjacent content, or providing emphasis, importance or other differences from ordinary prose. These will be discussed in detail in Chapter 3.
- Table data elements: Data suitable for display in the spreadsheet may be marked with rows and columns of
tableand related elements.- Form elements: These elements include text fields, drop-down menus, check boxes and other elements for collecting user input in web forms. These will be discussed in detail in Chapter 4.
- Embedded content elements: These include external media embedded in web pages, such as video, audio, bitmap drawing surface or third-party plug-ins, such as Adobe Flash content. These will be discussed in detail in of Chapter 5.
- Interactive elements: These include inherent interactive elements that do not require further scripts.
在深入这些组之前,我们将讨论适用于所有元素的两个方面:适用于所有 HTML 元素的全局属性和“内容模型类别”,这是 HTML 规范用来对元素进行相互分类的经常重叠的分组。我们开始吧!
全局属性
熟悉所有 HTML 元素上的属性(表 2-1 )为利用 HTML 中可用的核心功能提供了强大的工具,例如与 CSS 和 JavaScript 的集成,以及新的编辑和拖放 API。
语言代码列表见 www.iana.org/assignments…
注意当使用微数据时,有一组额外的全局属性适用,这允许向页面上的元素添加额外的标记,以使搜索引擎算法等机器更容易解析和使用内容。微数据将在本书后面讨论。
无障碍
accesskey和tabindex属性提供了使用键盘访问页面上的元素,这对于行动不便的用户可能很有帮助。当在一个元素上设置时,accesskey属性允许在键盘上按下一个(或多个)键来激活该元素。例如,它可以用于使用键盘跟踪超链接。不幸的是,这种可访问性的优势也有不利的一面。通常需要键盘组合来激活访问键,例如同时按下 Ctrl 或 Alt 键和 set 访问键。具体使用哪种键盘组合因浏览器和操作系统而异,降低了该功能的实用性。此外,所使用的键盘组合可能会干扰现有的键盘快捷键,最严重的是屏幕阅读器为视力受损的 web 用户使用的快捷键。最后,在一个元素上设置多个访问键(如果从两种类型的设备上查看网站,这可能会有所帮助)并没有得到广泛的浏览器支持。所有这些因素使得使用访问键相当令人沮丧。
在我们继续之前,最后一点需要注意的是——Opera Software 的 Opera 网络浏览器在访问键方面提供了一个很好的特性。通过同时按下 Shift 键和 Esc 键,在 web 浏览器窗口上弹出一个菜单,显示页面上所有可用的访问键以及它们链接到的位置(如果在锚元素上设置了属性;否则显示“空”)。参见图 2-1 的示例。
图 2-1。 Opera 网络浏览器显示访问密钥和公司主页上的相关链接
下一个属性tabindex,可能更有用。在网页上重复按下键盘上的 Tab 键,您会看到不同的页面元素变得突出显示。这是使用键盘访问网页元素的一种常见方式,在填写 web 表单时可能特别熟悉。当在许多不同的元素上设置tabindex属性时(从 1 开始并在每个元素上递增 1),该属性确定按 Tab 键在不同元素间移动的顺序,首先访问较小的数字,例如:
`
`当按下 Tab 键时,列表中的第一项将被激活,接着是最后一项,最后是中间项。显然,在这样的列表中,让它们以与列表相同的顺序激活会更有可用性,但是这演示了如何使用tabindex定制顺序。
元数据
属性为一个元素提供咨询信息。当鼠标悬停在链接、表单输入字段、缩写或首字母缩略词上时,通常会以工具提示的形式出现。这里有一个例子:
<a href="http://w3.org" title="World Wide Web Consortium">W3C</a>
当鼠标悬停在链接文本“W3C”上时,将显示一个显示“万维网联盟”的工具提示(图 2-2 )。
***图 2-2。*链接上设置的title属性的工具提示效果
下一个属性lang指定元素中的文本用什么语言编写。一些元素使用它来根据语言脚本的不同呈现不同的文本,例如使用的引号类型。例如,网页顶部的以下代码片段将指定整个 HTML 页面是用英语编写的:
<html lang="en">
最后,contextmenu属性是在 HTML5 中添加的,但是在撰写本文时还没有在任何发布的主流浏览器中实现。其思想是通过将元素的contextmenu设置为菜单的id属性,可以将menu元素与特定元素相关联并显示。要进一步了解它是如何工作的,您必须等待浏览器跟上规范的步伐!
识别
id属性用于为页面上的特定元素分配一个惟一的标识符,随后可以使用 CSS 或 JavaScript 进行访问,以用于样式或脚本目的。 2 这是一个惟一的名称,可以分配给 HTML 元素之一,然后可以用它来引用该元素。属性的使用方式类似;然而,与id属性不同,同一个类值可以应用于页面上的多个元素,目的是指定它们有一些共同点(比如特定的 CSS 样式)。总而言之,id和class属性之间的主要区别如下:
id 属性也可以作为超链接的目标。在第三章的“超链接”一节中讨论了如何使用 id 属性。
id- 该值可能出现一次,并且每页仅出现一次和,以便标识单个元素。
class- 该值可能每页出现多次。
- 一个特定的
class属性值可能包含多个类名,每个类名之间用空格隔开。
为了说明这些差异,请考虑下面的代码片段:
<p id="about-text" class="homepage popup">
该代码包含about-text的唯一id属性和两个类:homepage和popup。about-text的id属性不能在其他地方使用,而homepage和popup都可以在其他元素上使用。注意,元素不需要同时被分配一个id属性和一个class属性;他们可以有其中之一,或者都没有。此外,为了避免问题,不要以数字开始id或class属性,并且绝对不要在名称中包含空格(使用破折号或下划线代替)。
合理的 ID 和类值
基于您希望元素看起来如何而不是它是什么来赋值可能很有诱惑力,但是最好避免这样做。例如,代替这样的值:
<div id="topBox"> <strong class="redText"> <p class="big">
您应该使用如下值:
<div id="notificationBox"> <strong class="important"> <p class="introduction">
为什么呢?仅仅是因为有一天你可能会发现你需要那个strong元素是蓝色的而不是红色的,或者你可能想把这个内容框从页面的顶部移到底部——当这种情况发生时,你的id或class值将会产生误导。
这两个属性在 web 开发中被广泛使用,所以您必须熟悉它们。我们将在适当的地方使用 CSS 和 JavaScript 来说明 HTML5 的特性,但是简单地说,如果您想从 CSS 中引用这些属性值并设置样式,您可以键入值,然后在 id 前面加上一个散列符号(#)和一个句点(.),就像这样:
#about-text { background: blue; } .homepage { color: white; }
为了从 JavaScript 中引用这些属性值,您通常会在 JavaScript 中使用命令document.getElementById("about-text"),其中about-text被替换为您想要访问的元素的实际 ID。类似的命令可用于检索具有特定类值的所有元素:document.getElementsByClassName("homepage")(其中homepage被替换为您所引用的类值)。
可编辑性
在新的编辑 API 中使用了contenteditable属性,这和 HTML 标准中的一样新。编辑 API 允许对页面内容进行页面内编辑,自从 2000 年 Internet Explorer 引入以来,它就有了属性contenteditable,但直到现在才把该属性纳入 HTML 规范。这个想法是允许编辑 HTML 的元素,以便可以更容易地创建用于 web 表单等的富文本编辑器(例如,使用 web 应用接口为博客条目创建标记文本) 3 。
拼写检查
顾名思义,spellcheck属性用于指定一个元素是否应该进行拼写检查。Web 浏览器通常具有拼写检查功能,例如,当用户在 web 表单的输入字段中键入内容时,该功能会检查拼写和语法错误。有时,最好在页面的某些元素上禁用这种拼写检查功能。例如,您可能不想检查输入到 web 表单中的电子邮件地址的拼写错误,因此可以使用spellcheck属性通知浏览器忽略电子邮件地址表单输入控件。spellcheck属性的值是true或false(或者一个空的文本字符串"",它映射到 true 状态)。自然,这非常适合可以编辑的内容。
隐藏元素
hidden属性,用于隐藏和显示 HTML 元素。这相当于使用 CSS 属性和值display:none。虽然使用 CSS 隐藏元素是一种常见的做法,但实际上 HTML5 规范不鼓励使用hidden属性。hidden属性为受影响的元素添加了额外的语义。它的存在意味着该元素此时不相关。这可以被屏幕阅读器使用,例如,它可以忽略通过 CSS 显示规则应用的任何隐藏。
下面的 HTML 和 JavaScript 代码片段展示了如何使用hidden属性来显示和隐藏内容。HTML 部分显示了一个定义列表,其中包含一只狐狸的通用名和它的拉丁名:
`
- Red Fox
- Vulpes vulpes
JavaScript 部分添加了在滚动或关闭红狐的拉丁名称时显示和隐藏其拉丁名称的功能。因为hidden属性是一个布尔属性,所以可以使用 JavaScript 将其设置为true或false,这将导致显示和隐藏相关元素:
function toggleLatin(){ var entry = document.getElementById("fox"); var latin = document.getElementById("latin"); entry.onmouseover = function(){ latin.hidden = false; }; entry.onmouseout = function(){ latin.hidden = true; }; } window.onload = toggleLatin;
关于使用 contenteditable 的示例,请参考附录 A 中的“网络存储”部分。
拖放
与文档相反,draggable和dropzone属性是真正体现 HTML 向构建应用方向发展的两个属性。这些需要一些设置和 JavaScript 集成(我们将在第七章中讨论),但当功能正常时,这些属性允许 HTML 元素从页面的一部分拖放到另一个元素上(尽管正如你将看到的,你可能只会使用draggable来实现这一点,因为dropzone还没有获得太多的浏览器支持)。接下来发生的事情由 JavaScript 事件控制。
风格
属性提供了一种将 CSS 样式直接应用于元素的方法。以这种方式应用的任何样式都将覆盖元素上其他位置设置的样式。尽管这可以提供一种将样式应用于元素的快速方法,但是最好完全避免该属性,并在外部样式表中为您的页面提供样式。在你的网站中清晰的区分 CSS 和 HTML 代码提供了组织和灵活性的优势,因为当 CSS 规则包含在一个 CSS 文件中时,查找和禁用 CSS 规则要容易得多,而不是分散在 CSS 和 HTML 之间。
文本方向性
dir属性控制文本的流向。文本通常从左向右流动,但是如果使用一种向相反方向流动的语言,例如阿拉伯语,文本也需要向那个方向流动。dir属性提供了这种能力。如果整个块使用从右到左语言,则在容器元素上使用“rtl”值表示从右到左语言,使用“ltr”值表示从左到右语言,这将翻转文本和标点符号的对齐方式:
`
When rendered by a browser, this paragraph will appear aligned to the right.
While this paragraph will not because it lacks a dir attribute.
也可以给定值“auto ”,它试图根据包含的文本自动确定文本方向。
注意CSS
direction属性提供了相同的功能,并接受值inherit、ltr和rtl。然而,这个 CSS 应该而不是被使用,因为这个信息应该被嵌入到页面本身,这样即使相关的样式表被禁用,文本内容的方向性仍然可以被确定。
自定义数据
data-*属性有点奇怪。它是属性的总称,允许添加任何属性名称,以便在 HTML 元素中存储自定义数据,供 JavaScript 应用等使用。属性名中的*不是实际完成的属性;可以用任何文本替换它来创建自定义属性。例如,可以添加city来创建属性data-city。或者可以添加score来创建data-score,它可能被用在一个网页上列出一个游戏的高分。以下面的 HTML 代码片段为例:
`Show Scores
- Top Blaster Tom
- Middle Range Merv
- Last Pop Louis
然后可以编写一个 JavaScript 函数,在单击按钮时用获胜分数替换用户名:
function showScore(){ document.getElementById("show-score-button").onclick = function(){ var entries = document.getElementsByTagName("li"); entries[0].innerHTML = entries[0].dataset["score"]; entries[1].innerHTML = entries[1].dataset["score"]; entries[2].innerHTML = entries[2].dataset["score"]; } } window.onload = showScore;
注意前面代码中的
dataset属性允许以键/值对的形式访问data-*属性。但是,只需要属性的自定义部分,所以在数据集中查找属性score,而不是data-score。
这允许在单个元素中存储的内容有很大的灵活性,但同时又受到特定规范的支持。多么矛盾!这样做的目的是,这些属性只在特定的站点内使用,而不会被网站域外的软件所利用。在这种情况下,请谨慎使用这些方法,并且只有在绝对没有其他解决方案可行的情况下才使用!
内容模型类别
如第一章所述,最初,HTML 中的元素大致可以分为两类:块内和行内。一个类别或另一个类别的内容模型定义了什么样的内容可以放在特定的元素中。例如,行内元素不能包含块元素。随着 HTML5 的发展,这两种类型的内容不足以描述可用 HTML 元素的行为。WHATWG 取代了 block 和 inline,加入了一个更大的类别集, 4 ,这些类别根据相似的特征对元素进行分组。每个类别中的元素都有相似的内容模型,并且必须遵守定义内容类型的规则。现在有七个主要类别,列于表 2-2 。
即使这七个类别也不能完全涵盖所有情况下的所有要素。例如,一个元素可能不属于这些类别中的任何一个(例如html元素),或者可能被称为透明的,这意味着它继承了其父元素的类别。许多元素属于不止一个类别,在这种情况下,它们被称为具有混合内容模型。
参见 blog.whatwg.org/content-mod… 了解这一变化背后的动力。
注意实际上还有另外七个小类别,它们将特定上下文场景中的元素进行分组,比如当它们是表单的一部分时。要查看其他类别,请在
[dev.w3.org/html5/spec-author-view/index.html#element-content-categories](http://dev.w3.org/html5/spec-author-view/index.html#element-content-categories)或[whatwg.org/specs/web-apps/current-work/#element-content-categories](http://whatwg.org/specs/web-apps/current-work/#element-content-categories)浏览 HTML 规范中的类别参考。
根元素
要开始研究 HTML 中的元素,从开始看是有意义的——嗯,差不多是从开始看。我们在前一章讨论了 doctype 声明,它是 HTML 文档中出现的第一个元素。然而,跟在 doctype 声明后面的是html元素,它作为包含文档中所有其他 HTML 元素的元素,也称为根元素。
根元素是标签可选的少数元素之一(见表 2-3 中包含可选标签的其他元素列表)。虽然标签可能是可选的,但元素不会被省略。如果省略了可选元素,它们将被隐含(元素body是一个例外,如果没有提供页面内容,它将被省略)。例如,下面是一个完全有效的 HTML5 文档:
<!DOCTYPE html><title>Tiny HTML5</title><p>This is a valid HTML5 page!
在这种情况下,解析文档时会添加缺少的html、head、body和p元素的标签。如果不包含 doctype 声明,它甚至可以更短,但这将在 web 浏览器中触发 quirks 模式(关于 quirks 模式的讨论,请参考第一章中的 doctype 部分)。
注意要根据当前的 HTML5 规范检查文档的有效性,请访问
[html5.validator.nu](http://html5.validator.nu)或[validator.w3.org](http://validator.w3.org),这两个网站都提供基于网络的服务,可以验证提供的网站 URL、上传的 HTML 文件或直接输入 HTML。对于 W3C 中的验证器,请确保将验证器下拉菜单中的文档类型设置为“HTML5(实验)”以确保根据最新的规范进行检查。
尽管前面的代码片段很容易激怒那些热衷于 XHTML 的朋友,但是为了清楚起见,包含可选的标记仍然是一个好主意。虽然 HTML5 可能看起来像是从 20 世纪带回了编码实践,但重要的是要记住,它记录的是实践中使用的内容,而不一定是最佳实践。
html 元素的属性
除了全局属性之外,html元素还有一个新属性,manifest,用于创建离线应用的新 API 中。当您利用这个属性时,web 应用的基本功能组件(例如 JavaScript)可以缓存在浏览器中,这样当用户离线并重新加载页面时,页面仍然可以运行。
注意
html元素还有一个属性xmlns,用于声明 XML 名称空间,它描述了正在使用的标记语言。这个属性应该出现在有效的 XHTML 文档中。它只有一个支持的值,文本[www.w3.org/1999/xhtml](http://www.w3.org/1999/xhtml)。它只适用于 XHTML,在 HTML 中没有任何意义,除了在可能跨越 HTML 和 XHTML 的文档中使两者之间的转换更容易。
记录元数据和脚本元素
在开始根标签html之后,出现head元素的开始标签,它包含文档元数据元素,这些元数据元素指定诸如文档在浏览器窗口中出现时的标题、页面上元素的默认 URL 地址、字符编码信息以及链接和嵌入的 CSS 样式表(如果使用的话)之类的页面属性。表 2-4 列出了相关元素及其内容模型类别。
5 仅当 itemprop 属性存在时才适合流内容类别,这是 HTML5 中可用的微数据规范的一部分。
6 像meta元素一样,只有当itemprop属性存在时,link 元素才适合流和短语内容类别。
网页信息:标题和元数据
如前面展示的最小 HTML5 示例所示,title是 head 部分中唯一的强制元素。开始和结束title标签之间的文本将显示在浏览器窗口标题栏中。文档标题是文档中一个经常被忽视的区域;你肯定见过标题为“无标题文档”的页面。这是不幸的,因为如果给予适当的关注,文档标题可以为您和您的用户提供许多好处:
- Better search engine ranking. Search engines will consider the page title when determining the relevance of your webpage to a specific topic and when determining the content displayed on the search results page.
更好的方便。如果你的用户给页面添加书签,默认情况下,页面标题将被用作书签名称。 Better usability. Identifying websites and pages in the same location helps to identify the association between specific pages and specific websites. For example, "Semantic Web W3C" is the title of the main semantic web page on the website of the World Wide Web Consortium, which clearly identifies the theme of the web page and the website to which it belongs.*
** 注意以网页中有意义的标题的重要性为例,试着打开几个“无标题文档”窗口,然后在最小化它们后在它们之间切换——在切换之前你能分辨出哪个是哪个吗?或者尝试在单个 web 浏览器窗口中打开与选项卡相同的页面。你能一眼看出哪一页是哪一页吗?
还要注意,如果网站名称包含在标题中,网站名称应该出现在页面主题标题之后。当公司或网站名称放在实际页面标题之前时,也会出现类似的问题,因为如果标题太长而无法在最小化时或在选项卡中显示,则可能会从右向左裁剪,导致实际页面主题标题从视图中被裁剪。
只有当scoped属性存在时, 7 才符合流内容类别。
元元素
前一章介绍了常用于设置页面字符编码的meta元素,但它也常用于设置一系列元数据信息和指令的键/值对。例如,它可以用于定义网页的概要描述,或者用于为页面上的内容定义一组关键字。在键/值配对中创建“键”时,meta元素使用两个属性之一,http-equiv或name,而“值”部分使用content属性来设置。这里有一个例子:
`
`
注历史上,搜索引擎使用关键词,但今天许多人不使用它们,因为它很容易误导依赖于这一特征的搜索引擎,以发送垃圾搜索结果。但是,如果使用得当,包含它们并没有什么害处,尽管更新关键字以反映频繁编辑的文档中的内容变化是很重要的,这可能会产生额外的维护步骤,而没有实质性的好处。选择权在你!
http-equiv属性的一些用途(称为 pragma 指令)提供了设置 cookies、指定字符编码等任务,这些任务对于现有的更好的方法来说是多余的。因此,HTML5 规范中不推荐几个值。具体来说,content-language和set-cookie指令是不符合标准的,不应该使用(lang属性应该用于设置内容的语言,真正的 HTTP 头应该用于设置 cookies)。HTML5 规范中的其他官方 pragma 指令是content-type,它是charset属性的另一种形式;default-style,用于设置页面的默认 CSS 样式表(在第六章中解释);和refresh,它在几秒钟后刷新或重定向页面,如前面的代码示例所示。
注意为了在暂停后重定向页面,在使用
refresh pragma 指令时,URL 被添加到content属性中。经过指定的秒数后,页面被重定向到 URL。重定向看起来像这样:
<meta http-equiv="refresh" content="3; URL=homepage.html">.
为http-equiv和name属性建议的值的完整列表很大,所以您最好参考一些资源,比如分别位于[wiki.whatwg.org/wiki/PragmaExtensions](http://wiki.whatwg.org/wiki/PragmaExtensions)和[wiki.whatwg.org/wiki/MetaExtensions](http://wiki.whatwg.org/wiki/MetaExtensions)的 WHATWG PragmaExtensions 和 MetaExtensions wikis。除了这些网址上列出的值之外,HTML5 规范还包含了application-name作为name属性的值。该值允许为 web 应用(不是标准的 web 页面,而是添加了脚本功能的实际 web 应用)指定一个标题,该标题可以被视为独立于页面标题或对页面标题的补充(使用title元素设置)。这是因为在使用应用来反映正在发生的操作(如加载附加内容等)时,页面标题可能会发生变化。
注意可能更有用的是元名关键字
robots,它指导网络爬虫(谷歌和其他公司用来索引网页的自动程序)如何索引页面。关于这个名称值和其他值的信息可以在前面提到的 WHATWG 元扩展 wiki 的[wiki.whatwg.org/wiki/MetaExtensions](http://wiki.whatwg.org/wiki/MetaExtensions)上找到。
链接、样式和资源:基础、链接和样式
每个文档只能使用一个base元素。它应该出现在任何其他属性中包含 URL 的元素之前。这个想法是,base元素可以防止在整个页面中添加链接时重复输入相同的根 URL。它的两个属性,href和target,指定了要使用的 URL 和默认目标(如果适用)。target告诉,例如,一个链接是在一个新窗口还是在同一个窗口打开。例如,如果这出现在 head 部分中:
<base href="http://example.com/portfolio/" target="_blank" />
这出现在正文部分:
<a href="photographs.html">Photography</a>
然后单击该链接将打开一个新的浏览器窗口,并将用户连接到 URL [example.com/portfolio/photographs.html](http://example.com/portfolio/photographs.html)。
链接元素
link元素具有属性href、rel、media、hreflang、type和sizes,以及全局属性。其中,至少href和rel是共同设定的。href指定链接资源的地址(URL ),而rel指定资源的类型。以下代码是您最有可能使用该元素的方式,因为它通常用于将样式表链接到您的页面:
<link rel="stylesheet" href="main.css" type="text/css" />
然而,rel属性可以用来提供关于页面的附加相关信息。这个属性的本质可能有点难以理解,所以让我们考虑一个例子。除了样式表之外,当使用link元素引用网页头部的 RSS 提要时,您可能已经遇到过rel,就像这样:
<link rel="alternate" href="http://example.com/feed/" type="application/rss+xml" />
前面的代码意味着“这个文档的另一个版本存在于[example.com/feed/](http://example.com/feed/)”,用户代理可以发现并找到 RSS 提要——大多数现代浏览器都会在浏览器地址栏中显示一个提要图标,允许用户选择、查看和订阅提要。
如果替代版本是翻译版本,那么alternate值也可以与hreflang属性一起使用。如果替代版本是为不同的媒体设计的,它也可以和media属性一起使用。 8 它也可以和type属性一起使用,表示链接的文档是不同文件格式的页面版本,比如页面的 PDF 版本。例如,一个链接引用了一个可打印的 PDF 版本的文档,该文档也是法语的,可能如下所示:
<link rel="alternate" href="alt-fr.pdf" type="application/pdf"?hreflang="fr" media="print" title="French version PDF for printing" />
HTML 规范为rel属性列出了十几个预定义的类型(表 2-5 )。
8 媒体属性有screen, tty, tv, projection, handheld, print, braille, aural,和all等多个有效值,分别针对电脑屏幕、终端、电视、投影仪、手持设备、打印页面、盲文触觉反馈设备、语音合成器以及以上所有设备。其中,您最有可能使用屏幕和打印,也可能使用手持设备。Opera 在全屏模式下使用投影,所以如果您已经为主样式表指定了一种屏幕类型,您可能需要考虑包含投影:<link media="screen, projection" ... />。
属性指定了被链接资源的 MIME 类型。它纯粹是对浏览器的建议(例如,用户代理不会仅仅依赖这里指定的值来确定资源类型),并且可以在样式表中省略,因为它们是在link元素中最常见的文件类型。
样式元素
style元素允许将 CSS 样式规则直接嵌入到 HTML 文档中,这可能是在创建页面时添加样式规则的一种快捷方便的方式,但是与全局style属性一样,文档的 CSS 样式最好通过使用link元素将外部样式表链接到页面来提供。一个新的属性是scoped属性,它(理论上)允许将一个通用的 CSS 应用于一个特定的 HTML 块。然而,在撰写本文时,主流 web 浏览器的当前版本不支持该属性。
添加行为和回退:脚本和 noscript
script元素类似于style和link元素的组合,因为它支持直接在 HTML 文档中编写嵌入式客户端 JavaScript 代码或允许将脚本作为外部文件加载。与 CSS 一样,除非不可避免地要在 HTML 中嵌入代码,否则最好将 JavaScript 放在加载的外部文件中,如下所示:
<script type="text/javascript" src="js/menu.js"></script>
前面的代码片段显示了链接到外部 JavaScript 文件时script元素的一般外观(在本例中,该文件名为menu.js,位于名为js的目录中)。请注意,在外部脚本中链接时,元素的开始和结束标记之间不应包含任何内容。
HTML5 定义了一个名为async的新属性,它与另一个属性defer结合使用,可以用来控制何时解析外部加载的脚本。这两个属性都是布尔属性,因此它们的存在和缺失会以各种方式影响外部脚本的加载(表 2-6 )。
脚本:在顶部还是在底部?
需要注意的是,script和style元素不需要出现在 HTML 文档的头部;事实上,雅虎!Developer Network 公布了 35 个提高性能的最佳实践,指出script元素应该放在网页的底部(见[developer.yahoo.com/performance/rules.html](http://developer.yahoo.com/performance/rules.html))。(相反,style元素应该出现在顶部的头部区域。)此外,第一章中提到的 HTML5 样板文件([html5boilerplate.com](http://html5boilerplate.com))将所有脚本(除了 Modernizr,因为它更早就需要)放在页面底部,在结束的</body>标签之前。可以说,这种做法虽然提高了性能,但存在语义问题,因为它将关于页面的元数据移到了正文区域,而不是它所属的头部。理想情况下,随着async和defer属性获得更广泛的支持,script元素在页面中的位置将成为一个争论点。
最后,noscript元素用于显示周围的内容,只有在浏览器禁用或不支持脚本时才会显示。如果noscript元素放在文档的头部,那么它只能包含link、style和meta元素;否则,如果它在主体中,它可以包含所有会出现在body元素中的正常元素,除了另一个noscript元素。还值得注意的是,noscript元素的语法只适用于 HTML 文档,对 XHTML 文档没有影响。noscript是 W3C 推动 XHTML 时前途未卜的元素之一,它保留了一点处理禁用脚本的粗糙和肮脏的名声。更好的方法是编写一个脚本,将页面内容从静态动态转换,因为即使启用了脚本,脚本也可能失败,在这种情况下,noscript中的内容不会显示出来。例如,考虑下面的代码(为了简洁起见,它嵌入在 HTML 中):
<div> <p id="fall-back">Script disabled</p> <script type="text/javascript"> var fallBack = document.getElementById('fall-back'); var fallBackParent = fallBack.parentNode; fallBackParent.removeChild(fallBack); fallBackParent.innerHTML = "<button id='alert-button'>Show Alert!</button>" var showAlert = document.getElementById('alert-button');
` showAlert.onclick = function(){alert( "script worked!" );}
一个段落(其id被设置为fall-back)具有一些默认的静态内容。接下来是一个script元素,它删除了默认的 HTML,并用一个按钮来代替,这个按钮具有点击时显示警告框的功能。这样做的好处是,不仅为将静态页面转换成动态页面提供了更细粒度的控制,而且这也适用于 XHTML。
记录切片元素
在结束的head标签之后是开始的body标签,它可以包含任何非头部特定的标记,通常是预期出现在 web 浏览器窗口内容区域的内容:段落、列表、图像等等。body标签传统上有几个表示属性:background、text、link、vlink和alink,分别用于设置文档的背景颜色、文本颜色、链接颜色、已访问链接颜色和活动链接颜色。所有这些属性在 HTML 4.01 中都被贬低了,在 HTML5 中已经被标记为过时。它们的效果应该用 CSS 来创建。CSS background-color、color、a:link、a:visited和a:active属性和伪类(在第六章中讨论)是适当的。
结束body标签后面紧跟着结束html标签。这是一个完整的 HTML 文档,尽管没有任何内容。我们将在本章和后续章节中看到的其余元素将主要是内容元素——出现在正文中以各种方式标记和组织内容的元素。
语义分段元素
可能出现在主体中的第一组元素是那些涉及到将内容组织到不同逻辑部分的元素。这些显示在表 2-7 中,其中还列出了每个内容模型的类别。你会注意到几乎所有的 HTML5 都是新的。您还会注意到,它们的名称暗示了网页的常见组件,如页眉、页脚、导航栏等。这些元素的语义细微差别值得他们自己密切关注,所以暂时只需注意 HTML5 中有新的元素来赋予内容比传统的div和span元素更细粒度的含义。我们将在第三章的中深入探讨这些新的切片元素。
内容分组元素
在页面上内容的特定部分内,该部分的各种组件被分成段落、列表、图表等。段落等元素将内容分组为比节更小的单元。除了 HTML5 中新增的figure和figcaption之外,这个组中的元素对您来说可能都非常熟悉。这些元素的内容模型类别和描述见表 2-8 。
必然段:p
也许你在编写网页时最常用的标记是p。关于p没有太多要说的:它只是用来标记一个段落。然而,这个不起眼的元素经常被 WYSIWYG(所见即所得)web 创作软件滥用,作为在内容之间添加填充的快速而肮脏的间隔。您可能见过如下所示的标记,其中作者在他们的编辑器中按了几次 Enter 键:
`
`
这是(X)HTML 被吸收到表现方式中的一个典型例子。我们在这里发现多个无意义的段落,里面有一个不间断的空格实体(因为有些浏览器不显示空元素),但这种效果确实应该用 CSS 来实现。在内容下方添加一些空间的快速方法是向相关内容添加一个类:
<p class="section">Your content here.</p>
然后使用 CSS 样式化该类,在顶部或底部添加填充:
.section { padding-bottom: 3em; }
注意EMS 的使用传统上是专业 web 开发人员的首选度量单位,因为它是一个相对的长度单位,如果用户(或开发人员)放大或缩小页面,它将按比例调整大小。然而,近年来,随着 web 浏览器在处理绝对单位(如像素)的大小调整方面变得更好,对 ems 的偏好变得不那么明显了。关于尺寸是用 ems 还是像素有相当大的争论。em 使用起来可能不太直观,而像素则不能适应层叠式的大小变化。选择一个或另一个通常不会是一场灾难,所以选择你觉得更舒服的。总之,在一天结束时,你应该在各种场景下测试你的页面,所以问题应该会很快显露出来。
打破思维:hr
hr元素,或者说水平标尺,在历史上一直是一个表示元素,但是它被重新定义为代表一个内容和另一个内容之间的主题分隔。hr元素有几个属性——size、width、noshade和align——但是在 HTML5 中所有的属性都被声明为过时,所以 CSS 必须用于水平标尺的样式,这是应该的。
保留格式:前
那么,pre呢?由pre元素引起的视觉效果是保留标记中的空白(即制表符、空格和换行符),所以如果空白对于理解内容很重要,比如在计算机代码示例中,那么就使用pre。或者,可以用 CSS white-space:pre属性和值复制的效果,在可以使用另一个元素更好地描述相关内容的情况下,这可能是一个更可行的选择。例如,在标记计算机代码的情况下,code元素和white-space CSS 属性可以用来保存格式,并在格式可能丢失的情况下传达内容的含义(例如,如果它被屏幕阅读软件读取)。
报价文本:批量报价
blockquote是一个元素,历史上一直用于其呈现效果,而不是其语义或结构相关性,但它应被视为包含从另一个来源引用的内容,无论它将如何呈现。blockquote元素有一个cite属性,允许作者引用引用的来源(通常以 URL 的形式,但也可以是任何形式的引用,比如另一个作者的名字或电影的名称)。
注意例如,对于段落中出现的行内引用,还存在
q元素,它在第三章的文本级语义部分列出。
列表
在当前的 HTML 规范中有三种列表类型:无序列表(ul)、有序列表(ol)和描述列表(dl)。
列表类型之间的差异非常小且简单明了:
- When your content (as you expected) does not have any particular order, you should use a unordered list .
- When your content is arranged in a certain order, you should use a ordered list : alphabetically, numerically and so on.
- Description list is used to associate names or terms with values or other data-any items directly related to each other, such as glossary.
无序列表和有序列表:ul、ol 和 li
无序列表和有序列表分别由开始的ul或ol标记组成,后面是任意数量的列表项—li—元素,最后是结束的</ul>或</ol>标记。开始和结束标记只能包含列表项,但是列表项可以包含任何流元素,包括段落、div s、标题以及更多列表。只要它们都包含在一个列表项中,它就是完全有效且格式良好的标记。至于 HTML/XHTML 之间的区别,在 HTML 中你不必用</li>关闭列表项,但是在 XHTML 中你必须这样做。
除了全局属性之外,无序列表没有任何属性。另一方面,有序列表有三个附加属性:reversed、start和type。第一个是reversed,决定了列表的排序方向。它是一个布尔属性,意味着它的存在与否决定了它的行为。如果这个属性存在,列表将是降序的(9,8,7,6,5…);否则,将是升序(1,2,3,4,5…)。不幸的是,在撰写本文时,浏览器对该属性的支持很差。
在这种情况下,您可能会发现 HTML 语法更清晰。例如,以下两种方法都可行:
`
- item 1
- item 2
- item 1
- item 2
接下来,start属性允许作者从一个非 1 的数字开始对有序列表进行编号,这在您需要中断有序列表时非常有用,比如在搜索结果列表被分成几页的情况下。有趣的是,这个属性在 HTML 4.01 中被弃用了,但在 HTML5 中又恢复了良好的地位。
最后,type属性可用于将列表开头的标记从十进制数字(默认)更改为字母列表或罗马数字。然而,强烈建议使用 CSS list-style-type属性,它提供了更多的选项,并且将这种表示上的改变转移到 CSS 而不是 HTML 中。
当li元素是无序列表的一部分时,它只有全局属性,但是当它在有序列表中时,它又多了一个属性:value。此属性允许作者为特定列表项指定一个无序编号。
属性的问题已经解决了,让我们来看一个实现列表的例子。令人欣慰的是,虽然标记可能并不令人兴奋,但它至少是灵活的,使用 CSS 可以以多种方式显示列表:水平、垂直、扩展/折叠等等。例如,采用以下导航菜单:
`
`我们可以使用下面的 CSS 规则很容易地将它变成一个水平菜单:
li { float: left; }
简单!但是在这个阶段,它显然很难看,而且有点不可用,所以让我们稍微整理一下:
li { border: 1px solid; float: left; list-style-type: none; padding: 0.2em 1em; }
通过添加边框,删除列表项目符号,并添加少量填充,我们得到了如图 2-3 所示的列表。
***图 2-3。*一个无序列表,列表项向左浮动,加边框,填充
如你所见,我们已经有了一个非常实用的水平菜单。我们可以用一些锚标签的样式使它更有趣,给它们一个background-color,用display:block让它们填充整个列表项区域,用伪类:hover改变它们的背景,等等。
为了帮助减轻创建链接列表的痛苦,也值得尝试一下 Accessify 的 List-O-Matic (
[accessify.com/tools-and-wizards/developer-tools/list-o-matic](http://accessify.com/tools-and-wizards/developer-tools/list-o-matic)),这是一个在线列表生成器,可以让你从各种预建的样式中进行选择。
因此,您已经可以看到一个简单的列表可以用不同于默认样式的方式显示。使用 CSS 来创建列表的动态行为是可能的。例如,正如 Eric Meyer ( [meyerweb.com/eric/css/edge/menus/demo.html](http://meyerweb.com/eric/css/edge/menus/demo.html))所述,:hover伪类可用于将嵌套列表显示为弹出菜单。实现这一点的 CSS 非常简单:
li ul {display: none;} li:hover > ul {display: block;}
这意味着任何作为li的派生元素的ul——即嵌套列表——都不应该显示。第二行表示任何被悬停的li的子元素ul都应该正常显示。在兼容的浏览器中,最终结果(加上一些更多的表示风格)看起来像图 2-4 。
***图 2-4。*一个纯 CSS 嵌套菜单
一切都很整洁。Patrick Griffiths 的 Suckerfish Dropdowns 脚本([www.htmldog.com/articles/suckerfish/dropdowns](http://www.htmldog.com/articles/suckerfish/dropdowns))提供了一个 CSS 解决方案和一个 JavaScript 解决方案,这两个解决方案都非常健壮(满足了多个嵌套菜单的需要)并且非常容易实现,只需要包含一个小脚本和向 CSS 文件添加一个类选择器。
描述列表:dl、dt 和 dd
描述列表由一个开始的dl,接着是一个术语(dt,然后是任意数量的描述(dd)。典型的描述列表如下所示:
`
- Bottle
- A receptacle having a narrow neck, usually no handles, and a mouth that can be plugged, corked, or capped.
- To hold in; restrain: "bottled up my emotions."
- Rocket
- A vehicle or device propelled by one or more rocket engines, especially such a vehicle designed to travel through space.
大多数浏览器会以类似于图 2-5 所示的方式显示前面的代码。
***图 2-5。*一个描述列表,左边是术语,描述缩进
如上所述,描述列表相当灵活。只要术语和描述之间有直接关系,就可以使用这个列表来表示许多结构。例如,作为术语的照片可以具有包括关于摄影师和照相机的信息的描述。此外,描述列表可用于显示会议上一系列演示的时间表,演示的标题为术语,描述包括演示作者的详细信息以及日期和时间。在线购物应用中也可以使用描述列表来描述产品细节等。
尽管描述列表使用起来很灵活,但你应该记住以下警告:定义术语只能包含短语内容,不能包含流内容,因此不能包含段落、标题或列表——这意味着术语不能像标题那样被赋予不同的重要性级别(h1、h2等等)。然而,列表中的描述元素(dd)可以包含任何流元素或一系列元素,只要它们格式良好。
图表、照片、插图:数字和图片说明
元素背后的思想是提供图表、图像、代码等等,可选地带有标题或图例(figcaption元素),作为与文档主要内容相关的独立单元。该图形应该能够在不破坏文档整体布局的情况下移动或删除。
例如,下图显示了两幅并排的图像,标题如下(见图 2-6 ):
`
图 2-6*。**示例从figure和figcaption元件*输出
创建分部:div
一个div(“division”的缩写)用于标出一个内容块。它没有给它所围绕的内容添加任何特殊的含义,只是用来添加额外的 CSS 样式或 JavaScript。传统上,div是帮助页面布局的常用元素,但在许多情况下已经被语义更具体的元素所取代(在第三章中有更深入的讨论)。
文本级语义元素
我们现在开始进行最细粒度的控制:文本级的元素吸收了有意义的单个单词和句子。这些元素的正确语义用法有细微差别,最好在下一章中与文档分段元素一起讨论,所以现在先熟悉一下表 2-9 中的大量这些元素,我们将在第三章中进一步讨论它们。大多数已经存在了一段时间,但是有几个如i和b在 HTML5 中有了新的含义。
仅当它包含专有措辞内容时。
表格数据元素
几年前,使用表格来生成像素级精确的网站布局是非常普遍的做法。在当时,对于外行人来说,表格的这种使用提供了网页设计的一个飞跃,因为设计可以在 Adobe Photoshop 中创建,切割成一个网格,然后在表格中重新组合,以创建网页中的原始设计。然而,这种设计方法的不灵活性和可访问性很快就被 CSS 所取代,当吹捧的“无表格布局”成为一个流行语,意思是没有表格的像素完美布局。哎哟。桌子哪里出问题了?在标准世界中,当它们被用于一个它们原本不打算用于的目的——表示——时,它们就出错了。表格是用来显示数据的。洛杉矶电子表格,仅此而已。
如表 2-10 所示,表元素是适合流内容模型类别的单个单元。所有其他与表格相关的元素都在一个table元素中工作,以定义其结构,因此它们不适合任何主要类别。与body元素一样,大量本质上是表示性的属性被扔进了过时的垃圾箱;例如,在tr中,除了全局属性之外的所有属性都被去掉了。
10 可以放在语法内容中,如果它只包含语法内容。
表格基础知识
手工编码标记时,创建一个简单的表相当简单。单个表格的基本要素包括一个开始的table标记,后面至少有一个表格行(一个tr),后面至少有一个表格单元格(一个td,意思是“表格数据”)。这里有一个例子:
`
| Some data |
对于创建表来说,这已经是最简单的了,但是创建一个只有一项数据的表是不太可能的,所以让我们把事情变得更有趣一些。下面的标记是针对一个包含两行数据的两列表格(嵌入样式是提供一个border作为视觉辅助,以更好地区分表格的布局;理想情况下,它的效果应该放在生产环境中的外部 CSS 文件中):
<style type="text/css"> ` td { border: 1px solid #ff0000; }
| Name | Place of residence |
| Anselm Bradford | Auckland |
| Paul Haine | Oxford |
这将创建一个基本的表格,但是让我们进一步使用表格标题。
添加表头
您可以通过在表格顶部标记标题来指示列,从而使该表格更加清晰易读。虽然您可以通过向每个表格单元格添加一个类名,然后用 CSS 对其进行样式化来做到这一点,但是更好的方法是将最上面的表格单元格变成真正的表头,用th元素代替td。
`
...
| Name | Place of residence |
|---|
前面的标记呈现如图图 2-7 所示。
***图 2-7。*标题单元格使用th的基本表格
这种方法有几个好处。首先,它对可访问性有很大的帮助。虽然屏幕阅读设备在有能力的用户手中可能会将第一个表示例读取为“姓名,居住地,安瑟姆·布拉德福德,奥克兰,保罗·海雷,牛津”,并且有可用的表头,但它可以理解表头如何与数据相关,并将其读取为“姓名,安瑟姆·布拉德福德,居住地,奥克兰,姓名,保罗·海雷,居住地,牛津……”11当然,在这个简单的示例中,推断表的结构非常容易。不难看出“姓名,居住地,安瑟姆·布拉德福德,奥克兰,保罗·海雷,牛津”是一个人的名字后面跟着一个地名,但是当表格变得更复杂时(因为有更多的行和列),这就成了一个大问题。
注意你也可以使用
speak-header CSS 属性来控制在听觉样式表中是读出once还是always。
除了让屏幕阅读器的用户更容易访问表格之外,使用适当的表格标题还为视力正常的用户提供了关于表格结构的有用的视觉提示,并使 web 作者的生活稍微轻松一些,他们不必为每个标题都包含一个额外的类名。此外,这给了设计者一个额外的 CSS 和脚本钩子。
添加图例:标题
现在您已经打开了表格,您可以通过以caption元素的形式包含表格标题来使事情变得更好。这个元素需要直接放在开始的table标签之后:
`
…| Name | Place of residence |
|---|
大多数用户代理会呈现标题,如图 2-8 所示。
***图 2-8。*一个基本表使用一个caption
11W3C 在[www.w3.org/WAI/References/Tablin](http://www.w3.org/WAI/References/Tablin)提供了一个工具来帮助理解你的表格如何被辅助设备读取。
添加结构:thead、tfoot、tbody
如果你的表格看起来有点长,有点笨拙,你可以用thead、tfoot和tbody添加一些进一步的结构来帮助你的浏览器理解事情。这些元素允许您将行分组为标题部分、脚注部分和正文部分。很像th元素,如果需要的话,这三个元素给你 CSS 和脚本的另一个钩子,而不必添加额外的类或 id。像caption一样,这些元素必须按照特定的顺序和位置放在表格标记中。第一,如果包含三者中的任何一个,就必须包含thead。这个元素可以放在任何你想放的地方,但是最好直接放在开始的table标签下面——除非你已经包含了一个caption,在这种情况下thead元素必须直接放在它的下面。如果你愿意,你可以把它放在你的tfoot和tbody下面,它仍然是有效的标记,但是只有当你几个月后回到你的标记上,想知道你到底在想什么的时候,你才需要这样做。
然而,tfoot元素、必须在tbody元素之前出现。为什么页脚在正文之前?这样,用户代理就可以在从中间开始绘制之前先绘制表格的顶部和底部,如果您计划让表格主体滚动并且有许多行,这就很有用。
最后,添加tbody元素。不管怎样,这个标签实际上隐含在你的表中。例如,尝试将tbody {font-style: italic}添加到您的 CSS 中,并将其应用到一个基本的表格中,您会看到它将表格中的文本设置为斜体。即使它的存在是隐含的,如果你使用thead和tfoot,你必须明确包含tbody标签。因此,一旦添加了这些元素,您的标记应该看起来有点像这样:
`
| Name | Place of residence |
|---|---|
| Name | Place of residence |
| Anselm Bradford | Auckland |
| Paul Haine | Oxford |
除了现在在表的底部重复出现的标题之外,具有这些元素的表和没有这些元素的表在视觉上没有区别,但是包含它们是好的,因为它们提供了关于表的结构的额外的、有用的信息,在打印或在屏幕上查看时可以利用这些信息。
使用tfoot元素时要小心。因为该元素可能会在几页中重复出现,所以最好将其用作thead元素内容的副本(如前面的示例所示),而不是长表的字面结论,例如价格列下的最终总计(如果它出现在表完成之前,则没有什么意义)。
添加更多的结构:colgroup 和 col
如果您需要一个表格单元格跨越多行或多列,您可以使用rowspan和colspan属性来实现这种效果,这两个属性都采用一个数值来表示一个特定的单元格应该跨越多少个单元格。这一切都很简单。举个例子,让我们想象一下,除了居住在新西兰的奥克兰,我在佛蒙特州还有第二处住所。将这些数据添加到表中需要一个额外的行,但是我不会在新的居住地旁边留下一个空的表格单元格,我将插入一个rowspan属性,这样包含我的名字的单元格就可以与两个居住地配对:
`…
Anselm Bradford Auckland Vermont Paul Haine …`该表现在呈现如图图 2-9 所示。
**图 2-9。**使用rowspan属性的基本表格
如果需要,表格单元格可以跨越行和列。你只需要确保你的细胞和跨度相加。例如,如果您的表格有两行,一行包含五个td元素,那么第二行最多只能跨越五个单元格——超过这一行,表格将无效,并且会不可预测地呈现,少于这一行,剩余的单元格将占用剩余的空间。
我听说过去有人建议rowspan和colspan是表象性的,应该避免,但这是不正确的;您正在使用属性来定义结构,而不是表示,因此您应该将该信息保存在标记中。
到目前为止,您可能已经注意到,大多数表格标记只与行和这些行中的单个单元格相关——没有tc元素。相反,我们有两个元素可以定义列和列组,并且都是可选的:col和colgroup。
colgroup元素允许您使用一个span属性和一个数值来指定表中将存在多少组列(因此每组列有一个colgroup,一个组只能包含一列)以及每组中包含多少列。这个元素直接放在开始的table标签之后,除了可选的col标签之外,它不包含任何标记,稍后会介绍。
例如,考虑图 2-10 中所示的表格。
***图 2-10。*多列表:这里有三个列组,分别是“姓名”、“居住地”、“出生日期”
沿着最上面的标题阅读,您可以看到这个表格有三组列,最后一列横跨三个单元格的宽度。使用colgroup,您可以在表的开始定义该结构,如下所示:
<table> <colgroup></colgroup> <colgroup></colgroup> <colgroup span="3"></colgroup> <tr> …
有了这个标记,您就说这个表包含三组列,前两组包含一个列(暗示一个列;这种情况下不需要添加span="1"属性),第三组包含三列。
如表 2-10 所示,有一个col元素,这是一个自结束元素,也有一个span属性,用于指定colgroup中是否存在列。在功能和语义上,它实际上与colgroup相同,但不幸的是 HTML 规范不允许嵌套colgroup元素,所以您必须使用col来代替。使用前面的示例,您可以用两种不同的方式指定最终的三列集合,或者每列一个col,如下所示:
<table> <colgroup></colgroup> <colgroup></colgroup> <colgroup> <col /> <col /> <col /> </colgroup> <tr> …
或者使用单个col和一个span属性,如下所示:
<table> <colgroup></colgroup> <colgroup></colgroup> <colgroup><col span="3"></colgroup> <tr> …
这开始看起来像是大量的工作——为什么有人会为此费心呢?的确,乍一看,您似乎提供了多余的信息,但是这种标记确实有它的用途。有一些附带的好处,但是colgroup和col存在的主要原因是允许浏览器呈现表格,即使所有的表格行数据还没有到达。如果没有这两个标签提供的信息,浏览器必须首先解析整个表格,找到包含最大数量的单元格的行。接下来,浏览器必须计算该行的宽度,只有这样它才能知道表格的宽度,并允许它被呈现。当您让浏览器预先知道表的列结构时,浏览器可以在数据到达时呈现数据。
表格元素
就其本质而言,web 表单是一个很大的主题——在 HTML5 中,随着许多新元素的加入,这个主题变得更大。表单元素通常需要对属性进行仔细的编码,以使元素组能够正确地协同工作,并使表单成功地将其数据提交给服务器。表单将在第四章中深入讨论,但作为尝试,我们将在这里看一个基本示例:
`
Please provide feedback on our form!`
当在网络浏览器中渲染时,这将看起来像图 2-11 。
***图 2-11。*一个简单 web 表单的出现
这只是一个显示表单结构的简单示例。表单通常遵循以下格式:
- Include the form component in a
formelement, which defines the file for processing the form data when submitting the form data.- Some controls for collecting input are defined, such as text fields, drop-down lists, radio buttons and so on.
- Provide a button to submit the form to retrieve and process the input data.
如果您对表单非常熟悉,您可能会注意到上一个示例中的一个不熟悉的属性— placeholder,它在textarea元素中添加了灰色文本,提供了应该输入什么的提示。placeholder属性是 HTML5 中的一个新属性,但这仅仅是冰山一角!在最新的规范中,web 表单发生了巨大的变化。除了在表 2-11 中列出的新的和更新的元素之外,还可以使用input元素创建大量新的输入类型,例如急需的电子邮件地址、电话号码、日期和时间等表单输入!你将不得不等到第四章更深入的讨论。同时,让自己熟悉与表单相关的基本元素,然后让我们暂时了解一下嵌入式内容元素的概况。
如果类型属性未设置为隐藏,则 12 符合交互类别。
嵌入内容元素
多年来,除了格式化文档之外,HTML 不擅长做任何事情。静态图像是可以嵌入页面的复杂内容的缩影,而动态 gif 则是动画中的精华。这些缺点有助于 Adobe Flash Player 等技术的传播,这些技术解决了网页上动画、交互性、视频和音频解决方案的缺乏。随着 HTML5 的出现,这种语言已经发生了重大转变,成为开发 web 应用的平台,而不仅仅是格式化 web 文档。新的video元素也许比其他任何元素都更能体现 HTML5 希望表现的东西——使用 HTML/CSS/JavaScript 开放标准的丰富多媒体体验。在video元素被引入之前,没有 Adobe Flash 的视频似乎是不可能的。当然,其他解决方案也存在,比如苹果的 QuickTime 插件,但多年来,Flash 视频一直在 YouTube.com 等流行的视频分享网站上占据主导地位。
2010 年春天,苹果公司(Apple Inc .)的史蒂夫·乔布斯(Steve Jobs)发布了一封公开信,抨击 Adobe Flash 是一项有缺陷的过时技术,随着 HTML5 视频的传播,这项技术将被搁置一旁。HTML5 作为网络的未来被推向公众意识。就目前而言,未来还在前方;Flash 视频仍然得到广泛使用,HTML5 视频在应该使用哪种视频格式上存在分歧。但慢慢地,HTML5 技术家族正在朝着标准化功能取得健康的进展,以前只有 Adobe Flash 和其他第三方插件才有可能实现这一点——不仅仅是在视频方面。新的canvas元素提供了一个位图绘制表面,可以使用 JavaScript 来创建复杂的渲染和体验 13 类似于以前使用 Adobe Flash 制作的丰富的多媒体体验。
嵌入式内容元素是如此丰富多样的一组元素,我们将在第五章中深入探讨它们。与本章中涉及的其他元素集一样,表 2-12 显示了新的和更新的元素以及它们所属的内容模型类别。熟悉这些,我们将在几章后回到它们。现在,前进!
13 请访问 ro.me 上的罗马项目,了解嵌入式元素的功能。
14 如果设置了 usemap 属性,则可以放在交互类别中。
与 img 元素一样,如果设置了 usemap 属性,则可以将其放在交互类别中。
16 可以放在语法内容中,如果它只包含语法内容。
互动元素
最后一组元素是一个很小的集合,它包含了通常通过点击进行交互的元素,而不需要额外的脚本或其他创建交互性的机制。这组四个元素中的三个,details、summary和command是新的,而menu在 HTML 4.01 中被贬低后,在 HTML5 中被重新定义。这些要素的通常汇总见表 2-13 。
显示更多信息:摘要和详细信息
summary和details元素一起提供了一个“小部件”,可以显示和隐藏额外的文本,而不需要使用 JavaScript 或 CSS。summary元素作为一个标题(或摘要,如元素名所示),提供了一个切换按钮,单击该按钮可以显示和隐藏details标签之间的文本。默认情况下,details内的文本将被隐藏,直到该开关被点击;然而,布尔属性open可以被添加到details元素,以便默认显示文本。
不幸的是,在撰写本文时,details和summary元素还没有得到很好的支持,只有谷歌的 Chrome 浏览器支持这一功能。 18 如果你使用的浏览器不支持这些元素,那么细节区内的所有内容都会显示出来,不会有任何形式的切换。
一个基本示例可能是这样的:
`
Legal Notice
All content copyright 2011 Anselm Bradford这将显示一个开关和文本“法律声明”,单击它可以显示和隐藏版权声明。details元素可以包含任何流元素,这意味着细节可能相当复杂。例如,下一个例子展示了一些可能出现在剧院网站上的 HTML。这个例子使用了summary和details元素来显示和隐藏剧院当前正在上演的戏剧的附加信息:
`
A Midsummer Night's Dream
Duration: 1hr 42m
Showtimes:
- Tuesday, 8pm
- Wednesday, 8pm
- Thursday, 8pm
- Friday, 6pm and 8pm
如果类型属性设置为工具栏,则 17 适合交互类别。
18 访问 caniuse.com[网站](caniuse.com),在搜索栏中输入*详情*,查看浏览器支持的当前状态。
与上一个只切换一行文本的例子不同,这个例子显示和隐藏了两个段落和一个无序列表。
与元素的交互将看起来像图 2-12 。
**图 2-12。**点击摘要开关后显示隐藏和显示状态的细节元素
注意
summary元素是可选的;如果省略,浏览器将为details元素创建自己的标签,比如文本“Details”
例如,使用 JavaScript,details元素可以用来在 web 应用中设置用户首选项面板。在本例中,summary 是用户的昵称,用户可以打开并更改它。保存他们的更改会更新summary元素中的值,这将改变细节标签的外观。
`
Mac
Nickname:
Save...
图 2-13 显示了打开详细信息、更改名称并点击保存…的过程,然后(使用 JavaScript)更新摘要文本。显然,这将需要永久保存真正有用的更改,要么在后端数据库中,要么可能在客户端存储中(所谓的 web 存储在相关的 API 中可用,在附录 A 中讨论)。
***图 2-13。*一个使用 JavaScript 动态更新细节摘要的细节元素
提供工具栏:菜单和命令
放置在menu元素中的单个command元素可以用来创建一个类似桌面应用中的菜单栏。不仅如此,它还可以用来创建上下文菜单或其他交互式菜单选项列表。还记得使用了这两个元素的contextmenu全局属性吗?不幸的是,像contextmenu属性一样,command属性还没有在任何主流浏览器中实现,所以这些菜单仍然停留在 HTML5 规范的理论空间中。
总结
恭喜你!这是一个非常密集的章节,充满了大量的信息,但是我希望您已经了解了 HTML5 中存在哪些新元素,并且可能复习了其他一直存在的元素。现在是时候转向我们在本章中忽略的细节,看看如何实际使用这些丰富的新 HTML 元素了。**
三、识别语义
好了,好了,我们已经研究了可用的元素,这很好,但是你可能想知道如何从了解 HTML 元素到掌握 HTML 元素。好了,在知道存在什么元素之后,下一步就是知道什么时候使用一个而不是另一个。本章将引导你走上这条道路,重点放在定义网页结构和语义的元素上。我们将编写一个简单的 web 页面大纲来学习结构语义,然后深入一个案例研究来探索文本级语义元素的细微差别。
什么是语义,我为什么要关心语义?
“HTML 中的元素、属性和属性值(由该规范)定义为具有特定的含义(语义)。例如,ol 元素表示有序列表,lang 属性表示内容的语言。
作者不得将元素、属性或属性值用于其适当的预期语义目的之外的目的。”
WHATWG HTML 规范
单词 semantic 在 web 开发社区中经常可以在诸如语义网、好语义网、语义丰富的 HTML 等短语中听到,但它感觉有点像是一个被抛来抛去的流行语,让演讲者看起来对当代 Web 开发很时髦。到底是什么意思?这个问题正是语义学想要回答的。语义是某事物的意义,尤其是关于语言的组成部分。语义 HTML 是关于描述它们所包含的内容类型的 HTML 元素。它关注的是将内容封装在一个 HTML 元素和另一个元素中的含义。它也是关于按照 HTML 规范中的指导方针,为特定的内容使用适当的元素。
有时候一个元素将包含什么样的内容是非常清楚的。例如,看到time可能会让你快速找到这个元素的内容。另一方面,看到s可能需要仔细查看 HTML 规范中的相关段落。但是让我们再来看看time元素。它将包含的内容是否像最初看起来的那样清楚?例如,我可以这样写吗:
<p>Innovations of the <time>21st century</time>.</p>
或以下内容:
<p>The machine ran <time>infinitely</time>.</p>
嗯,没有;每个元素都有约束条件,虽然这两部分内容都与时间相关(一个时间段和一个时间属性),但它们不是time元素想要描述的与时间相关的内容类型。稍后我们将更多地讨论time,但简而言之,规范告诉我们它是公历中精确的日期,可选地带有一个时间。所以,并没有我们最初想的那么清楚!为什么这个元素不叫date而叫datetime?好吧,撇开元素名称不谈,关键是每一个都有微妙的差别,不管这个名称使它的目的看起来有多清晰。掌握这些细微差别将有助于创建结构合理、易于维护、对数据挖掘服务(例如,搜索引擎)更友好的页面。所以,把你的假设留在门口,让我们深入 HTML 元素的细微差别!我们将从结构元素开始。
勾勒思维
看看你是否能理解这个场景。你有一个新的网站项目要做。在仔细考虑了网站的总体概念后,你启动你最喜欢的图形编辑器,开始移动颜色块,摆弄纹理和线条。你扔进一个标题和标志,并把标题拖来拖去,直到它看起来合适。这引起共鸣了吗?当着手一个新的网站项目时,立即投入进去并开始设计网站的外观是很诱人的,但是如果你发现自己也在这样做,那就值得停下来看看大图。最终,一个设计良好的网站是一个提供有效的交付和访问其内容的网站。你的设计应该旨在创建一个信息层次结构——页面的各个部分应该首先吸引浏览者的注意力,然后是第二,以此类推。如果你事先没有把所有的内容组织成一个层次结构,你可能会发现自己一次又一次地放弃你的设计,因为你发现这个或那个部分需要在页面上或多或少地突出。
所以,暂停一下,把设计放一会儿,拿起纸和笔,写下你网站的主要内容。为每一部分考虑一个标签,以及它相对于页面内容的位置。暂时忘记细节,而是专注于创建可以位于主要内容部分之上的标签。例如,对于一个简单的主页,你可能会想出类似于图 3-1 的东西。
***图 3-1。*一个简单的主页轮廓
把这个列表想象成你的网站内容的目录或站点地图,什么在什么之前,什么是一个更大部分的一个子部分。在这个例子中,网站的标题(可能是一个公司名称)是所有其他内容所属的信息。下面是到其他页面的主导航(记住这是大图,所以在这个例子中没有显示单独的链接),接下来是主页上的特色内容,包括一篇特色文章,其中有对文章内容的简要总结。最后,主页上的其他文章被放在“其他新闻”部分。
开发一个这样的列表可以帮助你组织和可视化你网站上的信息层次,但这不仅仅是一个崇高的练习,在开发你的网站时可能有帮助,也可能没有帮助 HTML5 规范实际上提供了一个具体的算法来建立一个基于大纲的网站结构,例如图 3-1 中的大纲。不仅如此,该算法是学习如何正确组织网页的一个很好的指南。
HTML5 轮廓算法
HTML5 规范的这一部分被称为 HTML5 大纲算法,它提供了将内容分成嵌套列表的规则,每个列表都有一个标题。提供理解和解析网页结构的标准算法意味着每个适当构造的网页自动获得一个“目录”,该目录可以被例如屏幕阅读器(对于视力受损的用户)使用,或者在内容的联合部分中使用。
注意一个部分 1 只是一组内容——把它想象成页面上某个内容周围的一个盒子——而一个标题就像是打在盒子上的标签,说明它包含的内容。
简单来说,outline 算法使用以下规则解析文档:
- Specify the
bodyelement as the root section under which all other page sections are grouped.- Specify the first title content element as the title of
body.- For each subsequent slice content element found, define new slices and sub-slices and add them to the outline.
- Specify the first title content element found in each subsequent chapter as the title of that chapter.
在前面的步骤中,请注意提到的两个内容模型类别,标题内容和小节内容。这两个类别中的元素位于第二章中的“语义分段元素”一节。两者都包含一小组元素;标题内容包括h1、h2、h3、h4、h5、h6和hgroup元素,而article、aside、nav和section元素属于小节内容。 2
1HTML 中有一个 section 元素,但在此上下文中,“section”是一个通用术语,涵盖了 sectioning 内容模型类别中的 HTML 元素。
2 请注意(可能令人惊讶的是)div 不包括在分段内容中。
使用标题内容隐式创建大纲
之前的网站轮廓(图 3-1 )可以使用h1、h2、h3和h4元素来建立顺序和层次,如下所示:
`
HTML5 Outline AlgorithmSite Title
Main Navigation
Featured Content
An Article
Article Synopsis
Other News
Another Article
`坚持住。如果您仔细阅读大纲算法解析规则,您可能会注意到这里的一个问题。从h1到h4元素是标题内容元素,而不是小节内容元素,那么除了由主体创建的根节之外,这个页面还会有其他节吗?答案是肯定的。如果算法遇到预期的情况,可以隐式地创建部分。
从h1到h6标题元素据说有一个等级,这是它们名字中给出的数字(例如,h1的等级为 1,h2的等级为 2,依此类推)。较低等级的标题元素,当被放置在较高等级的元素之下时,将被嵌套在较高等级的标题元素的部分内。然而,如果标题元素与它的前身具有相同或更高的等级,它将隐式地创建一个新的部分,如果还没有定义的话(图 3-2 )。请注意,这里没有添加任何元素;这就是 HTML5 outline 算法如何解释页面上的内容是如何分组在一起的。
***图 3-2。*相邻标题元素的隐式部分创建。具有相同等级的相邻标题元素将隐式创建新节,而等级较低的标题元素将隐式创建嵌套节。
在早期,使用div元素中的h1到h6元素来构建页面的各个部分是一种常见的做法。这样做的问题是div元素不是元素的分段内容组的一部分,所以它不会根据 HTML5 outline 算法将页面分成几个部分。隐式创建节提供了与这种旧编码风格的向后兼容性,因为节可以基于在div元素中使用的标题元素自动创建。然而,这并不是构建页面各部分的首选方式。相反,在查看源代码时,显式包含内容元素将使嵌套结构更加明显,这是我们接下来要做的。
使用切片内容创建轮廓
在四个分区内容元素中,section元素 3 是最通用的,提供了(理想情况下)主题相关的内容分组。通过将section元素添加到代码中,我们可以明确地显示这些部分将出现在哪里,这可能会更容易地看到页面是如何组织的(如果以下示例中的元素嵌套没有意义,请参考图 3-2 ):
`…
Site Title
Main Navigation
Featured Content
An Article
Article Synopsis
` `Other News
Another Article
…`其他的是文章、旁白和导航。
注意第一个
h1不需要节,因为body元素就是服务于这个角色的。然而,您可能已经注意到了,body元素不包含在 sectioning content 类别中。主体属于称为截面根的特殊元素类别,这些元素内部可能定义了轮廓,但是如果它们包含在另一个轮廓中,它将被隐藏。例如,blockquote元素是 sectioning 根类别的成员,并且可以包含形成轮廓的 sectioning 元素,但是这在页面的轮廓中是不可见的,因为它被封装在 blockquote 中。这个类别的其他成员是details、fieldset、figure和td元素。
通过包含分节元素,实际上不再需要标题元素的不同排序。在这个问题上,规范陈述如下:
“…强烈建议作者要么只使用 h1 元素,要么对节的嵌套级别使用适当级别的元素。”
所以,将代码中的所有标题元素转换成h1元素可能是明智的;否则,页面对结构变化的适应性会降低。例如,如果嵌套结构发生了变化,那么标题等级需要更新以反映嵌套深度的变化(不这样做不会破坏任何东西,但在语义上是不允许的)。
注意也就是说,目前搜索引擎优化(SEO)只关注标题的
h1元素。例如,微软的必应搜索引擎发布了一个网站管理员常见问题([www.bing.com/toolbox/webmaster/](http://www.bing.com/toolbox/webmaster/)),指出一个页面每页不应该有一个以上的h1元素。这一指示预示着早期的网络,所以理想情况下,这最终会被删除,但与此同时,如果搜索引擎优化对你的网络项目至关重要,执行尽职调查,你的目标搜索引擎是否会有多个h1元素的问题,或严格使用标题排名适合他们的嵌套层次。
请注意,将所有标题元素转换为h1意味着页面上的标题在默认情况下可能具有相同的大小,而不管这些部分是如何嵌套的。例如,截至本文撰写之时,最新版本的 Google Chrome 和 Firefox 足够智能,可以减少嵌套在其他部分中的标题元素的大小,而 Safari 和 Opera 则不行。然而,后两个是否实现这个行为是一个争论点,因为页面的所有表现质量(包括标题大小)都应该使用 CSS 而不是 HTML 来处理。
改善大纲语义
区段是一个很好的通用分组元素,但是使用更具体的区段元素可以更好地定义此页面上的许多内容。让我们看看 sectioning 内容组中剩余的三个元素,看看哪一个比section元素更合适。使用图 3-3 中的流程图,我们将逐步完成内容。
***图 3-3。*选择特定切片内容元素的流程图
首先,导航可以包装在nav中,因为这个部分将定义网页的主要导航链接(在这个简化的例子中,链接被省略了,但通常不会被省略)。接下来是“特色内容”区域。嗯,这是一个有趣的问题,因为它包含的内容(一篇文章)如果从网站的其他部分分离出来,就可以自己理解。因此,它可以被包装在一个article中。但是等一下;那真的是最合适的选择吗?为了使你的标记在语义上正确,你必须关注页面上一段内容的目的;内容的特定部分包含什么,以及它在将来会包含什么?例如,article元素是为完全自包含的内容设计的,可以在 RSS 提要中整合。在这个例子中,特色内容区域用于为了在站点上突出显示而从其余内容中分离出来的内容。因此,可以说它不是自包含的,因为它包含的内容是在站点的一个更大的内容集中强调的。因此,如果没有周边内容,指定“特色内容”是没有意义的。此外,特色内容区域可能包含一篇以上的文章或其他内容,它们可能根本不相关。该区域用于特色内容,不一定是相关内容。如果这个领域有更多的内容,那么将所有的内容(相关的和不相关的)捆绑在一起并联合起来还有意义吗?我不这么认为。所以,这给我们留下了一组内容,这些内容在主题上是一致的(因为它们都是有特色的),但又不够独立,不能被认为是一篇文章。因此,该内容最好保留在section中。
注意html 5 规范旨在尽可能清晰地表达元素的语义用法,但仍然有大量内容具有不同的含义和解释。虽然像图 3-3 这样的流程图有助于缩小一个元素比另一个元素更合适的范围,但是你很可能会遇到使用哪个元素的问题的答案变得模糊不清的情况。在这些情况下,最好是选择一个更通用的元素,这个元素肯定适合给定的内容,而不是应用一个更具体的元素,这个元素可能合适,也可能不合适。
接下来,“其他新闻”部分可以被视为“特色内容”它按主题将内容分组在一起(所有未被精选的内容),但它不够独立,不足以保证使用article,所以它也有一个section。所示的两篇文章是独立的,它们本身是有意义的,所以它们被包装在article元素中。
接下来,“文章简介”本身没有意义,它与嵌套在里面的文章相关,所以最好放在aside中。最后,尽管担心使用多个h1标签,我们还是会将所有标题转换成h1,这样你就可以看到是什么样子了。
最终结果如下所示:
`…
Site Title
Main Navigation
Featured Content
An Article
Article Synopsis
` `Other News
Another Article
…`好多了!这种标记现在不那么通用了。导航很容易识别;我们看到页面上有一篇特色文章,边上有一个简短的提要,页面的另一部分有另一篇文章。目前,除了单独部分中的标题之外,没有其他内容(段落、图表等等),但是很容易就有了!这只是建立文件的大纲。
注意在这个例子中,
aside已经嵌套在一个article中,而后者又进一步嵌套在一个section中。如果旁白直接出现在body元素中,它应该与整个页面的内容相关,而不仅仅是一部分。对于一个内容很少的网页来说,这可能是可以的,但是对于一个内容丰富的网页来说,分组和/或嵌套aside以及它们的相关内容很可能是必要的。
页眉和页脚
每个部分可以选择性地有一个header和一个footer元素。一个header 4 用于将一节的介绍性内容或导航帮助 5 组合在一起,因此它可能包含该节的标题元素以及其他介绍性内容(目录、相关徽标等)。一个footer包含与部分或页面整体相关的内容,例如作者是谁、版权信息、联系地址和其他(一般)小片段信息。有时页面主导航菜单的相关链接或重复链接可能会出现在页脚,但一般来说,如果它们是无关的或多余的链接,并且对网站的主导航不重要,就不需要放入nav元素中。
注意需要注意的是,整个页面可以有页眉和页脚,也可以有页面上的节,所以一个页面可以很容易地有多个页眉和页脚。
我们是否应该在现有代码中添加一个header?当然,但是实际上现在没有必要。一个header用于将介绍性内容分组在一起。目前,我们每个部分都有一个标题元素,所以没有什么可以组合在一起。还是有?主导航是一个导航辅助工具,所以它可以放在页面的标题下。另外,让我们在“站点标题”下添加一个副标题,名为“站点口号!”—现在我们有三个介绍性元素要分组!将这些包裹在header中会给我们带来以下结果:
4 不要与“标题”混淆,后者指的是 h1 至 h6 元素。header 元素甚至不是标题内容类别的一部分!
例如,导航工具可以是主菜单或搜索栏,这在许多网站的右上角都可以找到。
`…
Site Title
Site Slogan!
Main Navigation
Featured Content
…`注意“网站口号”在段落元素中。如果使用了标题元素,标题和口号就会被隐含地分成两个部分,这似乎是不对的。但是,有一段好像也不太对。标题用一个h1和口号用一个h2似乎更合适,因为这两者之间有明显的重要性等级,然而它们是同一个介绍性文本的一部分。这就是标题内容类别中最后一个元素派上用场的地方:输入hgroup!
使用 hgroup
hgroup元素允许将一组标题元素放在一起,并且只将其中排名最高的一个元素暴露给 HTML5 outline 算法,这对于您可能希望在一个部分中有两个标题的情况非常有用,例如一篇文章有一个标题和副标题。通过将标题包装在一个h1中,将副标题包装在一个h2 a中,然后用一个hgroup将它们组合在一起,h2不会创建新的部分,因为它不会被轮廓算法看到。这样做的另一个优点是标题元素出现的顺序可以改变,因为出于结构目的,较低等级的标题被有效地忽略了。对于我们一直在使用的示例代码,我们可以将标语移动到标题上方,而不会产生结构上的影响,从而得到如下代码外观:
`…
Site Slogan!
Site Title
Main Navigation
Featured Content
…`用地址格式化页脚
在footer中包含的一个常见元素是联系文章作者或网站所有者的方式。为此,在页脚中可以找到的一个典型元素是address元素。此元素不用于邮政信箱或类似地址,因为这不是联系作者的最直接方式(尽管这些信息也可能出现在页脚)。而是为最近的文章或整个页面提供直接的联系信息(电子邮件地址、电话号码等等)。
注意除了
article或文档正文之外,不适合在分节元素中使用address元素。因此,section元素可能有一个页脚,但它不会包含address元素。如果在这种情况下包含了一个address元素,那么该地址将在语义上应用于遇到的包含该部分的第一个冠词,或者应用于主体,无论哪个先遇到。
让我们在现有代码中添加一个页脚,为整个页面提供一个电子邮件地址联系人:
`…
Site Slogan!
Site Title
Main Navigation
Featured Content
An Article
Article Synopsis
Other News
Another Article
Contact: Webmaster …`确定页眉和页脚内容
参见图 3-4 的流程图,该流程图总结了确定页眉和页脚内容的过程。
***图 3-4。*确定页眉和页脚元素的流程图
查看 HTML5 轮廓
现在我们已经有了一个简单站点的框架,让我们来看看它的轮廓吧!Geoffrey Sneddon ( [gsnedders.com](http://gsnedders.com))开发了一个很棒的工具来解析 HTML5 标记并返回一个大纲。前往[gsnedders.html5.org/outliner/](http://gsnedders.html5.org/outliner/),在那里你可以上传 HTML,输入一个 URL 进行解析,或者将 HTML 直接输入到一个 web 表单中。打完“大纲这个!”按钮,您将看到您提供的 HTML 文档中各部分的概要。尝试输入我们一直在构建的代码。你应该会看到类似图 3-5 的轮廓。试用此工具是学习切片内容嵌套结构的好方法。
如果你喜欢在浏览器中内置一个工具,Chrome 网上商店有一个谷歌 Chrome 扩展。前往[chrome.google.com/extensions/](https://chrome.google.com/extensions/)并搜索 HTML5 大纲视图。扩展安装在地址栏中。当访问一个 HTML5 网页时,可以点击扩展来显示页面的轮廓(图 3-6 )。不幸的是,这不适用于您在本地查看的网页。
Opera 在[addons.opera.com/addons/extensions/details/html5-outliner/](https://addons.opera.com/addons/extensions/details/html5-outliner/)有一个等价的扩展。
此外,如果你在[code.google.com/p/h5o/](http://code.google.com/p/h5o/)访问 HTML5 Outliner 项目,你会发现一个 Firefox 的实验性插件和一个已经在 Firefox 和 Opera 中测试过的 bookmarklet(那里也有一个 Chrome 扩展的链接,因为这是开发该扩展的项目)。
***图 3-5。*Geoffrey Sneddon 的 HTML5 Outliner 输出示例
***图 3-6。*Chrome html 5 Outliner 扩展出现在地址栏右侧。该图像显示了[w3.org](http://w3.org)地点的部分轮廓。
div(和跨度)过时了吗?
所有这些关于在页面上划分内容的讨论几乎没有提到div s!时代变了。在 HTML5 之前,div遍布网页;它们是不可避免的脚手架,用于创建页眉、页脚、列和页面的所有其他部分。有了这些新的切片元素,div会重蹈blink的覆辙吗?不,div s 仍然非常存在;在某些情况下,它们已经被更多语义定义的元素所扩充和取代,但是它们仍然是有效的元素,并且有它们的位置。因为div元素本身没有任何语义,所以它们可以适当地用于分组相关内容、无关内容、整个页面或一个句子。 6 从语义的角度来看,这些都是相等的,div并没有给这些分组增加更多的含义。它们的多功能性在于它们没有额外的语义包袱。因此,它们对于应用 CSS 规则或从 JavaScript 访问一段内容仍然很有用。当没有其他元素适合时,一个div是一个伟大的包罗万象的元素!
同样,span在 HTML5 中仍然存在。它与div有相似之处;当div用于流内容时,span可以用于短语内容。
如果您有一段内容似乎不适合放在另一个元素下,下面是两个很好的经验法则来确定您是否应该使用div(或者span,如果您正在处理文本级的语法内容):
您是纯粹将标记作为挂钩来应用 CSS 样式还是从 JavaScript 访问内容?* Can only one
classoridattribute be used to describe the meaning of the content? Thedivandspanelements do not introduce any semantics of their own, but if there are no other suitable elements, you can add meanings through theclassandidattributes.
案例研究:城市出版社
既然您已经习惯了使用 HTML5 sectioning 元素来组织 web 页面的结构,我们将把注意力转向细节,页面的文本级语义。这些是包含语法内容的元素——段落中的文本等等。我们将以虚拟报纸城市出版社 ( 图 3-7 )的主页为例,探讨这些元素。出于演示目的,城市新闻页面使用了大量不同的元素进行编码。
6 但是,需要注意的是 div 不在分节内容类别中,用于代替节的 div 不会向文档大纲添加新的节。
***图 3-7。*虚构的报纸主页被用作使用语义丰富的 HTML 元素的案例研究
在我们深入研究文本级语义之前,让我们先来看看这个页面的轮廓,看看它是如何构成的(图 3-8 )。
***图 3-8。*城市新闻网页的轮廓
查看大纲,您可以看到文本“The City Press”是主体的标题,它包含两个嵌套的部分,“Main Menu”(nav元素)和“Today:2011 年 10 月 10 日,星期一” ( section元素)。在“Today”部分,有一个article元素(“更多阳光预报……”)和两个aside元素,一个是天气预报,一个是“城市之声”,其中包含文章故事的一段引文。
添加文本级语义
大量的元素可用于标记段落和其他内容组中的文本。这些元素用于定义哪些单词是超链接,哪些应该被强调,哪些应该被标记为重要,哪些应该与文本的其他部分区分开来,等等。我们将逐一探究这些元素。
超链接:a
链接最有可能出现在段落旁边,作为你学习的 HTML 的第一部分,但是我们仍然可以探测到模糊的深度,并发现一些潜在有用的行为。严格来说,a元素不是链接;这是一个超文本锚,它可以链接到一个新文件,通过它的id属性指向任何元素,或者,如果它缺少href属性,就充当一个占位符,否则链接可能会被放置在那里。
与以前的 HTML 版本相比,a元素中一个令人兴奋的新变化是,在链接中可以放置更多的灵活内容。任何流内容都可以嵌套在其中,只要它不是来自交互式内容类别(按钮、链接等),因此在过去,链接可能是这样的:
<a href="newpage.html">link text that appears on web page</a>
它现在看起来像这样:
<a href="newpage.html"> <section> <h1>Wow an entire section in a link!</h1> </section> </a>
作为快速复习,href属性决定了链接的位置,而标签之间的文本是在网页中查看时变得可交互的内容。当文本被点击时,它将连接到在href属性中指定的任何东西,通常是一个文件(最常见的是一个网页)。然而,它可能连接到所谓的片段标识符,这是链接文档中元素的id属性中的值。如果href属性包含一个片段标识符,用户不仅会被引导到链接的文档,还会被带到与片段标识符具有相同 ID 的任何元素。
为了链接到片段标识符,在 URL 的末尾添加一个散列符号和值,如下所示:
<a href="newpage.html#parttwo">link</a>
如果您想要链接到同一页面上的片段标识符元素,则不需要包括文档文件名:
<a href="#parttwo">link</a>
这将链接到带有“parttwo”的id的元素,可能如下所示:
<h3 id="parttwo">Part Two</h3>
链接到同一页面上的某个已标识元素可以有多种用途,例如用于一篇长文档的目录,有时还可以用作“返回页面顶部”链接:
<a href="#top">back to top</a><sup>7</sup>
注意另一个常见的用途是创建跳过链接,这些链接允许人们跳过很长的导航链接以获取内容。对于使用键盘、移动设备或屏幕阅读设备导航的用户来说,通常会包含跳转链接,但有时它们也会以可视方式呈现给那些放大图片但可能不喜欢滚动的用户。总结跳转链接的一篇有用的文章是 Jim Thatcher 的“跳转导航”(
[www.jimthatcher.com/skipnav.htm](http://www.jimthatcher.com/skipnav.htm))。
拥有一个不包含href属性的锚元素是完全可以接受的。例如, City Press 网页上的菜单包括一个围绕“主页”的链接,该链接不链接到任何地方:
`
Main Menu
`让超链接链接到用户当前所在的页面是没有意义的,但同时,出于语义或样式的目的,从所讨论的菜单项中删除锚元素也是没有意义的。在城市新闻网页的情况下,href属性被移除,而class="current"被动态地添加到服务器端,这提供了一个 CSS“钩子”,可以很容易地将主页链接的样式与菜单的其他部分不同(图 3-9 )。
显式包含一个 ID 为“top”的锚或标识元素是一个好主意——一些浏览器会推断出这样的位置。
***图 3-9。*城市新闻菜单,残疾人主页链接显示通过一个类应用的单独样式
HTML5 在a元素中增加了三个新的属性,media、type和download,分别指定链接是否为在特定媒体/设备上显示而优化;链接资源的 MIME 类型(image/jpeg、text/html等等);以及最后,该链接是否指定了要下载的资源。如果资源是要下载的,那么download属性中的值就是给下载文件的默认文件名。在撰写本文时,这个属性才刚刚出现在 Google Chrome 的最新版本中。
锚元素上剩下的属性是target、hreflang,和rel。定义链接打开位置的target属性将在第四章和第五章中进一步讨论,但它通常具有下列值之一:_blank、_self、_parent或_top,这些值决定链接是在新窗口、当前窗口、包含窗口(例如,如果使用了内嵌框架)还是最顶层的包含窗口(如果多个框架嵌套在一起)中打开。属性定义了链接资源的语言;然而,它纯粹是建议性的,实际上没有任何权力设置链接页面的语言(无论如何,它可能在其html元素上设置了一个lang属性)。最后,rel属性定义了链接的类型。它有许多可能的值,如表 3-1 所示。
注意
area元素(在第五章的中讨论)使用了与表 3-1 中所示相同的值作为其rel属性。此外,这些值中的许多也在link元素中使用(参见第二章中与表 2-5 的重叠部分)。
注意WHATWG HTML 规范为链接定义了一个
ping属性(a元素和area元素——在第五章中有介绍),用于定义链接被访问时应该通知的 URL。然而,对它的包含存在争议(担心它可能被滥用),并且 HTML5 规范的 W3C 版本不包含该属性。在这个问题解决之前,你最好暂时不要去管这个属性。
重点和重要性:em 和 strong
虽然 web 浏览器通常会显示分别带有斜体和粗体文本的em和strong,但是这些元素不应该被视为粗体或斜体文本的手段,因为表示功能应该留给 CSS 样式表;更确切地说,em元素应该用来表示的强调,而strong元素应该用来表示重要性。嵌套这些元素中的任何一个都传达了对所包含内容的越来越多的强调和/或重要性,例如:
`CAUTION WARNING DANGER
I am worried!
I am very worried!
`你可能不希望你的重点以这种方式显示出来。请记住,您可以随时重新设计em和strong元素的样式,以您喜欢的方式显示,同时仍然保留它们的含义。例如,如果你的文档是日文表意文本,那么你就不太可能需要斜体来强调。改变背景颜色可能更合适。
注在 Molly E. Holzschlag 的文章“世界变小:全球网络的开放标准”(
[www.alistapart.com/articles/worldgrowssmall](http://www.alistapart.com/articles/worldgrowssmall))中更详细地讨论了国际化的上述问题。
对于城市新闻网页,strong在天气预报中被用于给出预报值相对于周围标签的重要性(例如,“高”和“低”):
`
Weather
Sunny
- High: 82?F
- Low: 70?F
从语义的角度来看,实际的天气内容是这一部分中最重要的,因此strong元素被恰当地应用于天气值,而不是周围的标签。
注图 3-7 中城市压力截图显示的划掉的温度将在后面的“不准确文本”部分添加。
正文分开设置:I 和 b
i和b元素在历史上用于呈现粗体和斜体文本,在实践中,如果没有额外的样式,在 web 浏览器中看起来与em和strong元素在视觉上无法区分。那么,为什么在 HTML5 中它们没有被扔进过时的垃圾箱呢?每一个实际上都有细微的、语义(意思)上的不同,这些都被编入了 HTML5。虽然em元素是为了强调,但是i元素是为了将文本与其他文本进行偏移,以便在阅读时,它可以以不同的声音或语气出现。这是什么意思?好吧,就拿下面这段文字摘录来说:
西蒙傻笑道:“是的,我很乐意把垃圾拿出去。”“唉,我真的不想!”他一边拿起垃圾袋一边想。
第二段讲话是西蒙的内部对话,所以它会以不同的声音读出来,而不是实际所说的。该文本的 HTML 可能如下所示:
<p>Simon smirked, “Yes, I'm happy to take the garbage out.” “<i>Ugh, I <em>really</em> don't want to!</i>,” he thought as he picked up the garbage bag.</p>
注意这里已经抛出了一个em,这样您就可以看到这两个元素在含义上的不同。
当内容是一个技术术语或分类名称或者是一个外语短语时,也可以使用i元素。城市出版社的网页包含法语短语“Oh là là”,这是i元素的一个很好的候选词!HTML 看起来像这样:
<i lang="fr">Oh là là!</i>
注意使用了lang属性来指定这个文本是法语。使用lang属性对浏览器如何处理文本有影响,因为不同的语言可以对引用的文本使用不同的字形。
b元素用于分隔文本,而不传达任何额外的重要性(与strong元素相反)或可选的声音或语气(与i元素相反)。例如,可以使用b将产品评论中的产品名称与附带的文本分开。或者它可以用于食谱中的配料:
<p>After bringing <b>water</b> to a boil, add <b>potatoes</b> and <b>carrots</b></p>
另一种用法是在文章或故事的开头。这是吸引读者的第一段。它并不比文本的其余部分更重要,但它应该突出,以便抓住注意力。城市新闻网页包括以下内容:
<p><b class="lede">Meteorologists predict more sunshine and scorching temperatures for the upcoming week, prompting area farmers to install irrigation systems.</b></p>
在这种情况下,b元素的用途是使用一个class属性专门定义的。
旁注:小
与i和b一样,small传统上被用作一种表现元素。它让文本——你猜对了——变小了!这是一个更适合 CSS font-size属性的任务。在 HTML5 中,small获得了真正的语义。它现在意味着小字、小字、旁注、所有可能包含法律免责声明、许可协议、版权等的地方。它也可用于指示一件作品的属性,如文本或图像。城市新闻中的记者姓名放在小元素中。例如,在主照片标题的末尾,HTML 显示如下:
<small>Chris Elhorn | The City Press</small>
不准确的文本
另一个在 HTML5 中改变了含义的元素,s元素在历史上意味着删除线文本,本质上是表示性的,被指定为过时的 bin。然而,在 HTML5 中,s被重新定义为不再准确或相关的文本。例如,城市新闻网页在天气侧边栏显示温度。这些值最近已经被更新,所以旧值使用s元素被标记为不准确,而新值使用strong元素被赋予重要性(如前面的“强调和重要性”一节所示):
`
- High:
82°F96°F - Low:
70°F79°F
注意在某些情况下,可能有必要将文本标记为已删除,例如在维基(维基百科等用户编辑网站的更通用术语)中查看页面变化时。虽然对标记为 deleted 的文本使用
s元素可能很诱人,但是有一个del元素可以做到这一点。
突出显示文本:标记
mark是一个新元素,可用于突出显示某些文本以供参考。你可以把它想象成一个荧光笔,用来标记书中的一些文字。它也可以用来强调原报价中没有强调的部分。在城市出版社网页中,右下角的blockquote中使用了mark元素来为开始的文本添加粗体(默认情况下,大多数浏览器会将mark中的内容呈现为黄色背景,但是您可以使用 CSS 来改变这一点):
`
`We're all hoping it rains soon, some farmers have installed irrigation systems, at considerable expense
注意注意在
blockquote的cite属性中使用了一个片段标识符。这将它链接回页面上的原始源文章,其属性为id="article1"。
内联报价:问
元素的作用是给文本块添加行内引号。它对于组织内容就像blockquote对于流动内容一样。这个元素已经存在一段时间了,但是在过去遭受了不一致的浏览器支持,所以不推荐使用它。然而,情况已经有所好转,?? 元素在现代网络浏览器中获得了更广泛的支持。浏览器应该在引用的开头和结尾自动包含印刷正确的引号,这意味着你,作者,应该而不是包含它们。此外,通过明智地使用lang属性,这些引号应该以适合于指定语言的样式显示(例如,一些欧洲语言将使用 v 形符号或 guillemets : and,而不是“and”)。如果由于浏览器支持不佳而无法实现这一点,可以使用 CSS 通过 ASCII 代码和quotes属性添加适当的引号。例如,要将正确的引号添加到一个<q lang="fr">元素中,请使用:
q:lang(fr){ quotes: "\AB" "\BB" "\2018" "\2019"; }
但是,Safari 不支持这种功能。
此外,浏览器应该显示嵌套引号的意识(在英语中,如果引号以双引号字符开始,那么引号中的引号应该使用单引号字符,反之亦然)。例如,下面这段 HTML:
<p><q>This is a quote that has a <q>nested quote</q> as part of it.</q></p>
应该显示如下:
This is a quote that has a 'nested quote' as part of it.
虽然这听起来非常令人兴奋,但现实却更加平淡无奇。例如,Safari 也不支持这一点,但大多数其他浏览器都支持。虽然支持变得更好,但您可能仍然会发现最好暂时不要使用q,即使它确实提供了一点独特的语义。
处理条款:dfn 和 abbr
dfn (definition)元素在标记将在整个文档中重复使用的术语的定义实例时非常有用。它通常与abbr(缩写)元素结合使用,以定义第一次出现的缩写或首字母缩略词,供以后参考。在使用了dfn元素之后,术语的定义需要出现在与dfn元素相同的段落、描述列表(dl元素)或部分中。通常,这相当于让结尾的dfn标签后面的文本定义所讨论的术语。在 City Press 网页中,一个虚构的组织——国家农场协会(NFA)被包装在一个abbr元素中,并且在文本中第一次出现一个dfn元素:
<dfn id="nfa"><abbr title="National Farm Association">NFA</abbr></dfn> (National Farm Association)
强烈建议您将title属性与abbr元素一起使用,以便在悬停在元素上时提供缩写的全文扩展。此外,dfn元素被赋予了一个id属性,该属性可用于将未来出现的缩写链接回其定义实例:
<a href="#nfa"><abbr title="National Farm Association">NFA</abbr></a>
该链接使用片段标识符指向前面的dfn元素,因此用户可以跳回到文本中定义“NFA”含义的地方(在dfn后面的括号中)(图 3-10 )。
***图 3-10。*缩写可以链接回第一个使用dfn元素定义它们的地方。
下标和上标:sub 和 sup
科学界有一个笑话,两个人在餐馆里,女服务员问他们想喝点什么。第一个人回答说“H 2 O。”女服务员看着第二个顾客,后者想了一会儿说,“我也要 H 2 O!”
过了一会儿,女服务员端着饮料回来了。第一个人喝了一大口。第二个人喝了一口,倒在地板上,口吐白沫。“白痴,”第一个喊道。
有趣的是,第二个人并没有像第一个人那样显得聪明,而是无意间点了“H 2 O 2 ”(过氧化氢)而不是 H 2 O(水)。
虽然sup和sub(上标和下标)本质上看起来是表象性的,但正如这个笑话所展示的,它们传达了它们周围文本的重要意义。
考虑以下两个等式:
- e = MC 2
虽然它们看起来很像,但前面的方程中只有一个是爱因斯坦的;拼写出来,前一个等式是“e 等于 m 乘以 c 的平方”,而后一个是“e 等于 m 乘以 c 乘以 2。”
注意对于比这更复杂的方程,你应该使用数学标记语言(MathML),它在一个独立于描述 HTML 的规范中定义,但可以嵌入在 HTML 文档中。
或者这个怎么样:
2
第一个是水的化学方程式——两个氢原子和一个氧原子——第二个只是字母 H 后跟数字 2,然后是字母 O ,没有意义。因此,2 的放置和样式很重要,如果你把它的样式和位置去掉,放在一个样式表中,一些浏览器可能会失去意义。
W3C 还指出,一些语言(除了英语)要求使用下标和上标文本。这里有一个法语例子:M lle Dupont。
在文体上,上标和下标也出现在英语中。您最有可能在日期中看到它们,或者指出脚注/尾注的存在:
九月十四日日日日* The report of the committee stated that the minister's actions were sincere.
在 City Press 的例子中,一个上标出现在页面顶部的日期中,在time元素内,这将在下面讨论:
<time datetime="2011-10-10">Monday, October 10<sup>th</sup>, 2011</time>
具体日期:时间
元素是对 HTML 调色板的一个很好的补充,特别是对于联合内容。正如本章开头提到的,它定义了公历中的一个特定日期。它可能包括一个时间和一个时区偏移量,但它不需要这样做。最好使用datetime属性精确地指定日期/时间,因为实际内容可能相当松散,例如:
<time datetime="2011-05-08">Mother's Day</time>
datetime属性遵循格式 YYYY-MM-DDThh:mm:ssTZD (即 2011-10-23T10:23:44+05:00)。时间和时区部分是可选的。
唯一的另一个属性是布尔属性pubdate,它指示日期/时间是最近的文章元素的发布日期,或者如果没有找到文章,则是整个文档的发布日期。城市出版社的网页在主要文章的页脚使用了这个(通常可以找到出版日期):
<small>Posted <time datetime="2011-10-10T12:16:20Z" pubdate>October 10, 2011</time></small>
注时区偏移量中的 Z 代表世界协调时(UTC),与+00:00 相同。
换行:br 和 wbr
换行符元素br(呈现为<br>或<br />,因为它是自结束的)通常用在新行是内容格式的预期部分的内容中,比如邮政地址或诗歌。城市出版社在邮政地址的页脚部分使用这个:
`
The City Press
123 General Street
Springfield, OH 45501
另一个换行元素,wbr(或<wbr />),是 HTML5 中新增的。它定义了如果空间不允许整个单词,在单词的什么地方可以换行。在城市出版社的网页中,提到了一家名为irrigination direct的公司。这是wbr元素的完美候选,因为如果需要的话,HTML 可以指示浏览器在中间断开名称,并且名称仍然有意义。代码如下:
<i>Irrigation<wbr />Direct</i>
其他文本级元素
这一部分涵盖了一些没有在城市出版社网页中使用的落伍者——无论如何,让我们简要地浏览一下他们!
作品名称:引用
cite元素表示作品的标题,如书籍、歌曲、电影、电视节目、绘画等等。我们已经遇到了在blockquote元素中使用的cite属性,用于将来源归属于引用,但是还有一个cite元素,用于包含与任何特定元素或其他材料的引用无关的独立引用。大多数用户代理会用斜体显示引文,这是印刷世界中常见的印刷惯例。
格式化计算机 I/O:代码、变量、样本、kbd
code、var、samp和kbd元素与之前的 HTML 规范没有任何变化。它们分别定义了计算机代码片段、变量、计算系统的样本输出和用户输入。既然这里没有什么新情况要报告,我们就继续吧。
标记文本编辑:ins 和 del
有时,能够指示文档中发生的编辑是有用的,例如,指示添加了什么内容以及删除了什么内容。例如,博客上的管理区将有一个创建和编辑帖子的区域。标记和查看博客帖子的修订版,指出与原始版本相比有什么变化,这可能很有用。HTML5 正好有这个用途的元素!元素用于标记一段文本的插入,而元素用于标记一段文本的删除。这里重要的一点是,它将内容标记为已编辑,但内容应该仍然存在(对于用del标记为已删除的内容)。
JavaScript 大师 John Resig 有一个示例脚本,它使用ins和del来显示对一段编辑过的文本的更改。你可以在[ejohn.org/projects/javascript-diff-algorithm/](http://ejohn.org/projects/javascript-diff-algorithm/)查看例子。
注意在没有进一步样式化的情况下,
ins文本的默认外观通常带有下划线,而del则带有删除线。这意味着默认情况下del看起来会像s;然而,它们肯定是不可互换的。s用于标记不准确的内容,而del用于标记被删除的内容,不管它是否准确。
ins和del有两个属性,cite和datetime。cite属性用于指定解释编辑的文档的网址,而datetime属性用于指示编辑发生的日期和可选时间。有关该值的格式,请参考本章前面的 time 元素,但它看起来类似于:
<p> <ins datetime="2011-10-26T12:00Z" cite="edit10262011.html">new text</ins> is added, while `old text is removed.
处理外国剧本
有几个元素用于显示来自世界各地的书写脚本的不同格式要求和语义。虽然拉丁字母(英语中使用的)已经在 Web 上占据主导地位很多年了,但是作为一种全球现象,Web 需要能够正确地处理不同的字母。下面的元素将帮助格式化 ruby 符号和双向文本。
Ruby 符号:ruby、rt 和 rp
拼音指的是与另一个文本片段有关联的一个文本片段,称为基础文本—它最常用于提供基础文本的简短注释或发音指南,并在东亚排版中使用。通常情况下,它会在基本文本上方显示红宝石文本,但浏览器支持会有所不同,如图 3-11 中的所示。
***图 3-11。*在(从左到右)、Safari、Chrome、Firefox 中呈现的红宝石文本
图 3-11 中的文本有以下 HTML 来源:
<ruby> This is ruby base <rp>(</rp><rt>This is ruby text</rt><rp>)</rp> </ruby>
如您所见,顶部文本是在rt元素中指定的。元素用于为不支持 ruby 的浏览器定义备份内容。在这种情况下,它们用于设置在 Firefox 上显示的括号(图 3-11 )。
注关于 ruby 符号的更多信息,请参考位于
[www.w3.org/TR/ruby/](http://www.w3.org/TR/ruby/)的 W3C Ruby 符号规范。
文本方向:bdo 和 bdi
如果您用外语标记文本,那么您可能会发现使用了bdo元素(即“双向覆盖”)和dir属性(这是该元素所必需的)。bdo分别控制文本片段和文本块的方向,最适合用于标记从右向左而不是从左向右书写的阿拉伯语和其他语言。当单词或短语的方向性不同于包含元素中设置的方向性时,使用bdo。默认情况下,包含元素的方向是从左到右。让我们来看一个使用英语的例子(尽管这是一种从左到右的语言,您将能够看到bdo元素的效果):
<p>When rendered by a browser, <bdo dir="rtl">these words</bdo> will appear as 'sdrow eseht'</p>
该标记呈现如图图 3-12 所示。
***图 3-12。*单词“这些单词”已被bdo元素反转。
有关如何创建使用从右向左脚本的页面的详细概述,请参考下面的 W3C 国际化教程:[www.w3.org/International/tutorials/bidi-xhtml/](http://www.w3.org/International/tutorials/bidi-xhtml/)。
注意有一个叫做
bdi的新元素,它是用来隔离一段文本的,这样它就可以被格式化为向左或向右流动,完全不受周围环境的方向性影响。这个元素还没有在任何主流浏览器中实现,所以您必须等待使用它,但是这个想法是,当一段特定文本的方向性未知时,可以使用它。例如,博客访问者留下的多语言评论可能包括用从左到右和从右到左语言写的文本,但你事先不知道文本的方向。通常,一个文本块将从其父元素继承从左到右或从右到左的方向,但出现在bdi中的文本将忽略任何继承的方向设置,并将默认将其dir属性设置为auto,这将根据其字符集自动检测文本的方向。
总结
结构化标记的目标是尽可能恰当地使用可用元素。有时选择的元素会比其他时候更接近地描述它们的内容。有时,使用什么样的元素是不明确的——在这种情况下,需要仔细研究规范并做出谨慎的判断——但是 HTML5 提供了比该语言以前的版本更多的选择和更好的规则。关键是停止视觉上的思考*。如果您正在使用 Adobe Photoshop 或 Fireworks 进行设计,那么在构建网站时,您可能会发现这有助于忘记样式,直接在文档中键入所有内容(或者占位符文本,如果您当时没有所有内容([lipsum.com](http://lipsum.com)是填充文本的好来源)。所谓“内容”,我指的是一切——不仅仅是正文,还包括任何导航、页眉、页脚等等。如果某个东西最后可能会以一个形象结束(比如一个企业 logo),那么在这个阶段就不要担心它。只是在它的位置包含一些文本;如果需要,您可以随时用内嵌图像替换它。*
当你这样做的时候,想想你正在键入的内容,想想你将如何向其他人描述它,想想有哪些元素符合你的描述。忘记现在会是什么样子——不要认为h1是“大、丑、粗”的,因为那只是默认情况下的样子。把它想象成网页内容轮廓中的标题——一个要点。就外观而言,一切都可以用 CSS 重新设计。
四、掌握表单
在第二章中,我们看了一下 web 表单的新特性。现在是时候更深入地关注它们了。好吧,说实话,如果在许多圈子里,甚至是与 web 相关的圈子里,人们兴奋地这么说,很可能会对 web 表单兴奋的荒谬性嗤之以鼻。在过去,表单一直被归入 web 开发中令人不快的角落,是那些对单选按钮组、文本输入宽度和充满选项的下拉菜单的挑剔感兴趣的人的领域。性感的设计和丰富的互动性哪里去了?但也许更重要的是,应该有的表单输入类型都在哪里,而不是需要用 JavaScript 拼凑起来?表单标记已经伴随我们很多年了,至少早在 HTML 2 规范中就出现了,从那以后没有任何显著的变化。如果知道 HTML5 照亮了它们,它们已经成长为一套有能力处理输入的 HTML,那将是一种解脱。添加了一组新的表单输入类型、表单元素和属性,以及与 JavaScript 和 CSS 接口的新方法。有了 HTML5,许多以前必须通过其他方式构建的功能现在都免费提供了。这太令人兴奋了!
本章开始时,我研究了可用的表单标记,分析了 HTML5 中添加到表单的新特性(有很多),如何最好地使用不同类型的表单控件,以及如何用简单的结构化标记增强可用性和可访问性。我们将剖析一个完整的表单,然后以关于 web 表单可用性和相关问题的一些大的想法结束。
表单标记刷新程序
本质上,表单非常简单——它们允许用户在一端输入一些数据,然后将数据发送到另一端,由表单处理程序处理。一个表单处理程序通常意味着一个处理输入表单数据的脚本,它是用服务器端编程语言或框架如 PHP、Python 或 ASP.NET 编写的。可以把表单想象成 HTML 中的数据中介,位于您和网页服务器之间。
表单由一个form元素组成,该元素围绕任意数量的“表单控件”(用于收集输入的表单 HTML 元素)以及任何其他正文标记(如段落和其他流内容)建立一个容器(但是,不允许将一个表单嵌套在另一个表单中)。在所有输入表单控件的下面,都有一个按钮,用于提交表单,将输入的数据发送到服务器。表单可以使用两种不同的方法发送数据:GET 和 POST。这些方法之间最明显的区别是,当使用 GET 方法时,来自表单提交的数据出现在网站的地址 URL 中。例如,使用 GET 方法提交的表单的 URL 可能如下所示:
handle_form.php?name=Anselm+Bradford&age=31.
这可能是提交图 4-1 中的表格的结果。
***图 4-1。*收集用户输入的简单网络表单
对于此表单,HTML 可能如下所示:
`
Name:
Age:
Submit
`这个例子使用 PHP 脚本来处理表单,但是也可以使用很多其他的服务器端语言,比如 ASP.NET、Python 等等。对于 PHP,有三个“超全局”变量允许它访问表单中提交的数据。变量$_GET和$_POST分别访问通过 get 和 POST 方法提交的表单数据,而$_REQUEST充当所有提交数据的容器,不管提交的方法是什么。例如,为了回显(在 web 浏览器中显示)在前面的表单中提交的值,可以使用下面的 PHP 代码:
`
"; echo "Age: " . $_REQUEST["age"]; } ?> ` 注这只是一个简单的例子,用来显示提交的内容;在生产环境中,需要对表单输入进行筛选,以确保没有恶意代码作为表单字段数据的一部分提交。例如,对于更新数据库的表单,SQL 命令可以输入到表单中,如果没有编写服务器端脚本来过滤掉这类命令,恶意用户可能会删除数据库中的数据,甚至更糟!
剖析表单元素
暂时忽略其他元素,form元素非常简单,只作为一个具有少量属性的容器存在。除了前面显示的method和action属性之外,form元素还有以下属性(以及第二章中列出的全局属性):accept-charset、autocomplete、enctype、name、novalidate和target。在 HTML5 中,一个属性accept被扔进了废弃的垃圾箱,而两个属性autocomplete和novalidate是新的。下面是一个完整构造的form元素的例子:
<form action="handle_form.php" method="post" target="_blank" accept-charset="UTF-8" enctype="multipart/form-data" autocomplete="off" novalidate>
虽然这会使用所有属性(不包括全局属性),但没有必要输入所有或任何属性,因为它们都是可选的。通常,至少会指定action和method(如前面的例子)属性。在下一节中,我们将讨论这些属性的作用,这样您就可以自己决定需要哪些属性。
表格元素属性
以下部分详细描述了每个表单属性。
动作属性
action属性告诉用户代理(web 浏览器)在提交表单时应该对表单内容做什么(使用 submit 按钮,这是一个表单控件元素,我们将在后面讨论)。和前面的例子一样,可以指定一个服务器端脚本来处理提交的表单数据。如果省略,表单将重定向到提交表单的同一个 URL。
方法属性
method属性是表单被设置为使用 GET(默认)或 POST 的地方。一般的经验法则是,如果表单提交正在主动修改数据(比如以某种方式更新服务器端数据库)或者包含敏感信息(比如密码),您的表单应该使用 POST 。另一方面,如果表单提交是被动的,比如搜索引擎的数据库查询,那么使用 GET 。为什么?让数据在页面的 URL 中可见(使用 GET)将允许页面被书签标记,这对于搜索查询很有用,而不在 URL 中(使用 POST)则为敏感数据提供了更好的安全性。此外,GET 更适合于少量数据,因为它有大小限制,因为 URL 只能有这么长(实际长度因 web 浏览器而异)。
接受字符集属性
accept-charset属性允许您指定服务器可以在提交的表单数据中处理哪些字符编码。如果没有指定(通常的情况),则使用页面的字符集(应该在 head 部分使用meta元素设置和/或在服务器的 HTTP 响应头中发送)。如果可以接受多个字符集,则该属性可以是以空格分隔的值列表;但是,为了避免字符显示不正确的问题,在处理编码时,请始终使用 UTF-8。UTF 8 支持世界上所有的主要语言。
enctype 属性
enctype属性用于指定发送表单数据时如何编码。它有三个可能的值:application/x-www-form-urlencoded、multipart/form-data和text/plain。在大多数情况下,可以省略它,因为它将默认为提到的第一个值,这将以 URL 安全的方式对数据进行编码。这通常是区分不明确的表单数据和其他信息所必需的。例如,如果某些表单数据中有一个正斜杠(实线),那么如果它以未编码状态放在网页的 URL 中,就会出现问题,因为正斜杠意味着移动到 web 服务器上的新目录。相反,正斜杠将被作为%2F发送,这是在 UTF-8 字符集中分配给正斜杠的十六进制值。即使使用 POST 方法发送数据,这种格式也有助于从发送到 web 服务器的其他信息中挑选出表单数据。
更改该属性的时机是在使用文件输入元素(用于上传文件,这将在后面描述)时,在这种情况下,该属性应该包含一个值multipart/form-data,它允许表单处理二进制数据。最后一个值text/plain,发送未编码的表单数据。通常不应该使用这个值,因为它很难挑选出表单数据。它主要是由于历史原因而可用的。
目标属性
target属性的工作方式类似于链接上的target属性(a元素),它告诉浏览器在哪里打开在action属性中指定的 URL。值_blank将在新窗口中打开表单提交结果,_self将在同一窗口中打开表单提交结果,_parent将在父浏览上下文中打开表单提交结果。例如,iframe元素可以用来将一个带有表单的 HTML 页面嵌入到另一个 HTML 页面中,该页面被认为是嵌套的 HTML 页面的父浏览上下文。最后,如果表单嵌套了几页深(例如,使用多个iframe),那么_top的值将加载最顶层的页面。
姓名属性
下一个属性name,用于向脚本标识表单。它本质上是赋予表单的唯一 ID,用于在页面上使用的所有表单中识别它。在 JavaScript 中,可以通过document.forms属性访问表单,该属性包含对页面上所有表单的引用。例如,对于具有属性name="contactform"的表单,可以使用 JavaScript document.forms.contactform来访问它。如果您不太熟悉 JavaScript,只需知道您也可以使用id(甚至class)属性来访问表单,这可能是从 JavaScript 与表单交互的更好途径。
自动完成和更新属性
最后,最后两个属性autocomplete和novalidate将在后面详细讨论,但简单地说,它们分别告诉浏览器是否自动填充表单中记住的值以及是否验证表单的输入。
收集输入
form元素只是数据收集元素的容器,称为表单控件,它们是input、select和textarea元素。这些工作的细节将在适当的时候进行说明,但是首先要注意它们都使用的一个属性:?? 属性。与出现在form元素上的name属性不同,这个属性在这个上下文中具有更重要的作用。所有向表单处理程序传递数据的表单控件都必须有一个name属性;否则,当提交表单时,它们不会传递它们的值。除了表单控件被组合在一起的情况,例如单选按钮的情况,name属性值应该是唯一的,这样就可以从其余的表单输入值中挑选出一个特定的值。例如,下面的表单片段显示了两个输入字段:
… <input name="firstname" type="text" value="Anselm" /> <input name="lastname" type="text" value="Bradford" /> …
这里的名称/值对是名字/安瑟伦和姓氏/布拉德福德(这些值是使用value属性的默认设置,但是可以通过用户输入的数据进行更改)。如前所述,如果表单是使用 GET 方法提交的(并且 web 页面文件名是handle_form.php),那么页面的 URL 应该是这样的:
handle_form.php?firstname=Anselm&lastname=Bradford
这显示了 URL 中的name属性及其相关值。
一般来说,一个表单的真正核心是变形元素input。我称之为变形,因为input元素在 HTML 元素中相当独特,它可以呈现许多不同的外观和行为,这取决于它的type属性中的值。type属性将一组关键字中的一个作为它的值。例如,前面的示例将带有type="text"的两个表单控件的输入类型都设置为文本输入。HTML5 中的可用类型列表大幅增加,如表 4-1 所示。每种输入类型的外观将由 web 浏览器决定(可能会因浏览器而异),但可以用 CSS 进行样式化。
注意如果在
input元素上没有指定type属性,或者如果使用了您的首选 web 浏览器尚不支持的类型,输入类型将变成单行文本输入字段。
原始输入类型
传统上,input有一小组可能的类型:text、password、file、checkbox、radio、hidden、button、reset、submit和image。为了让您熟悉不同的类型,我们将简要地浏览一下最初的类型,然后更深入地介绍新的类型。
注意当我在接下来的章节中介绍输入类型时,我提供了许多表单输入字段的截屏。如果您在这里看到的与您自己首选的 web 浏览器中显示的不完全匹配,请不要感到惊讶。有些字段可能看起来不同,有些功能可能略有不同,或者有些可能根本不支持。浏览器对 HTML5 规范中新的表单元素和其他特性的支持正在迅速改善。然而,这里的目标并不是向您展示使用哪种浏览器来查找特定的表单输入字段;更确切地说,它是向你展示最新的网络浏览器有什么可能,以及我们希望在仍在追赶的浏览器的未来迭代中有什么可期待的。这是未来的路,无论是通过 Safari、Chrome、Opera、Firefox 还是 Internet Explorer 来展示。
文本输入
不出所料,使用了一个text输入来收集输入的文本。这是input使用的默认类型,也可能是您遇到的最常见的输入。这是一个单行控件,通常以带有内嵌边框的矩形框的形式出现,如图图 4-2 所示。
***图 4-2。*显示输入到输入中的一些内容的文本输入
输入字符串的允许长度可以通过添加一个maxlength属性来指定,该属性采用一个等于允许的最大字符数的数值。当用户试图插入超过允许数量的字符时,没有提供直接的反馈机制——表单控件只是停止接受额外的字符,并且如果这样的字符串被粘贴到控件中,将截断过长的字符串。如果您想提醒用户空间已经用完,您需要使用 JavaScript。
注意
maxlength属性不是万无一失的;例如,可以通过 JavaScript 将更长的文本添加到文本输入中,这些文本将被提交给服务器而不会被截断。为了限制完全确定提交的文本长度,也需要在服务器上检查长度。
您还可以包含一个value属性来预设文本控件的内容:
<input type="text" name="data" value="Default text" />
页面加载时,value属性中输入的文本会出现在文本字段中,如图 4-2 中的所示。
注意使用
value属性是一种包含默认数据的方法,如果用户在提交表单之前没有更新输入的值,就会提交默认数据。value属性传统上也是提示用户在文本字段中输入内容的方式。这是一个非常普遍的需求,事实上 HTML5 已经为这种“占位符”文本添加了一个属性。但是现在不要担心这个特性,因为它将在本章的后面介绍!
密码输入
一个password输入几乎等同于一个文本输入;功能上唯一的区别是字符输入在输入时被屏蔽,通常是被一系列的点屏蔽,如图图 4-3 所示。它与文本输入共享相同的可能属性;唯一的区别是type属性被设置为type="password"。
***图 4-3。*显示正在输入文本的密码输入
这种类型的输入不是很安全——如果您的表单使用了GET方法,表单数据仍然会以纯文本的形式传输,并且会在 URL 中可见。这种视觉屏蔽实际上只是为了防止任何人越过你的肩膀看到输入内容(例如,当你在公共场所登录银行网站时)。
文件输入
一个file输入通常采用某种浏览按钮的形式,以及一个显示已选择文件信息的区域。浏览器之间的外观差别很大,比其他常见的输入类型更大,如图 4-4 所示。
***图 4-4。*两种不同网络浏览器中文件输入控件的外观,谷歌 Chrome(上)和 Opera(下)
文件输入控件允许您在本地网络上浏览文件,以便将其上传到网站。一旦你选择了文件,文件就会以某种方式显示,这取决于网络浏览器,如图图 4-5 所示。
***图 4-5。*文件输入控件在两种不同网络浏览器中的外观:Google Chrome(上)显示文件名,Opera(下)显示文件路径。
如前所述,为了让表单成功发送二进制数据,比如上传文件时,将相关表单上的enctype属性设置为enctype="multipart/form-data"。这将正确格式化表单数据,以便服务器端脚本可以处理该文件。
注意在 PHP 中,有一个名为
$_FILES的全局变量,可以用来访问上传的文件。你可以在[php.net/manual/en/features.file-upload.php](http://php.net/manual/en/features.file-upload.php)找到用 PHP 处理上传文件的信息。
默认情况下,一次只能上传一个文件;然而,通过向文件输入控件添加布尔multiple属性,可以选择多个文件进行上传:
<input type="file" name="filedata" multiple />
如果没有该属性,在操作系统的文件浏览器中一次只能选择一个文件;但是,包含此属性后,可以按住 Command 键(Mac)或 Control 键(Windows)来选择多个文件。同样,文件输入控件的外观会因浏览器而异,但它可能看起来像图 4-6 。
***图 4-6。*选择多个文件后 Safari 中文件输入控件的外观
注意不幸的是,当代的 HTML 特性通常都是这种情况,在可预见的将来,不要指望 Internet Explorer 会支持
multiple属性。但是,如果使用另一个主要的 web 浏览器,它在 Windows 上也可以工作。
file输入包含一个accept属性,理论上可以用来限制上传文件的类型;然而,在实践中,它纯粹是咨询性的,可能会被忽略。它接受一个逗号分隔的 MIME 类型列表,该列表与可接受的文件类型有关,例如看起来像accept="image/gif,image/jpeg,image/jpg"。这将通知浏览器服务器只接受 GIF 和 JPEG 图像。即使浏览器注意到了这个属性,在生产环境中,您也需要使用服务器端过滤器来检查提交的文件实际上是正确的类型,因为这种客户端检查很容易被绕过。
检查框
这是一个我们熟悉的老复选框,我们喜欢用来收集或真或假的输入。除了文本输入,这是您可能遇到的最常见的输入类型之一。一个checkbox输入通常采用一个方形框的形式,可以被选中或取消选中,但是使用 JavaScript,可以设置第三种“不确定”状态,看起来既不在真也不在假的条件下,如图 4-7 所示。
***图 4-7。*三个复选框:一个未选中,一个未选中,一个处于不确定状态
不确定状态是通过checkbox元素上的布尔indeterminate属性设置的,如下所示:
function init() { document.getElementById("option3").indeterminate = true; } window.onload = init;
这段代码将被放在一个脚本中(或者放在页面上的一个script元素中,或者最好放在一个外部文件中),并将影响下面的 HTML 片段:
<input type="checkbox" name="option3" id="option3" />
要将复选框设置为选中状态,需要添加一个布尔属性checked。只有被选中的复选框的数据才会与表单一起提交。value属性可以用来设置提交表单时发送的值,但也可以省略,在这种情况下,默认值将是文本“on”图 4-7 中的复选框可能如下所示:
<input type="checkbox" name="option1" id="option1" /> <input type="checkbox" name="option2" id="option2" checked /> <input type="checkbox" name="option3" id="option3" />
当这些作为表单的一部分提交时,web 页面的 URL 将被附加上 querystring ?option2=on(如果使用 GET 方法)。
单选按钮
像复选框一样,单选按钮可能你以前也遇到过。它们可能不太常见,但仍然在网络上广泛流行。一个radio输入有两种状态,选择或不选择,如图图 4-8 所示。
***图 4-8。*两个单选按钮,一个选中,一个未选中
您使用单选按钮来指示只能从几个选项中选择一个选项,即一个单选按钮组。
为了向用户代理表明一个单选按钮是组的一部分,您为每个单选输入元素的name属性赋予一个相同的值。当呈现表单时,如果输入与另一个输入共享一个名称值,用户代理将不允许选择多个单选输入。以下是前面示例的标记:
<input type="radio" name="example" value="first" /> <input type="radio" name="example" value="second" checked />
正如您在前面的代码中看到的,单选按钮的状态可以像复选框一样,用checked属性进行预设。
注意现实世界中的表单也会包含表单标签,但是我们将在“用字段集和标签添加结构”一节中讨论这些
添加隐藏输入
hidden输入类型用于将用户看不到的额外数据包含在表单中,但与表单数据的其余部分一起提交。这里有一个例子:
<input type="hidden" name="hiddenValue" value="42" />
当包含该输入的表单被提交时,值hiddenValue=42将出现在 URL 中(如果使用GET方法),并将与表单中的其他数据一起被传递到服务器端。
注意
hidden输入有时与file输入类型一起使用,告诉服务器可接受上传的最大文件大小。例如,一个表单可能包含以下输入,告诉服务器脚本文件上传应该限制在最大 20 千字节(大约)的文件大小:
<input type="hidden" name="MAX_FILE_SIZE" value="20000" />.
按钮、提交、重置和图像输入
button输入类型与button元素有很多重叠(将在本章后面讨论),在这两者之间,button元素可能是更好的选择。两者都创建了一个带有文本标签的可点击按钮,但是本质的区别在于button元素可以在它的标签中使用 HTML 元素,而button输入类型只能使用纯文本(参见本章后面的“使用按钮和图像提交表单”一节中的例子),这使得它不够灵活。submit和reset类型也创建按钮,具有提交表单(将数据发送到服务器)的额外能力,并在单击时将表单值重置为默认值。与button输入一样,button也可用于这些任务。简而言之,如果它看起来像一个按钮,请使用button元素!
最后一种类型image,用于使用图像代替提交按钮;这将在后面的“使用按钮和图像提交表单”一节中讨论。
新的输入类型
正如你在表 4-1 中看到的,input元素有很多种新类型。有些是比较通用的,比如数字的输入,而有些是非常具体的,比如创建一个颜色选择器。
注意许多表单元素还没有在现代 web 浏览器中实现。Opera 和 Google Chrome 似乎领先一步,但对于那些不支持新类型的应用,输入字段将会退回到默认状态——基本的文本输入。与其他 HTML5 特性一样,您可以使用 Modernizr (
[www.modernizr.com](http://www.modernizr.com))来检测对新输入类型的支持。要添加对旧 web 浏览器中缺少的功能的支持,可以使用 html5Widgets 之类的脚本,这是一个 JavaScript poly fill——这意味着它在不支持表单功能的浏览器中使用 JavaScript 来填充缺少的表单功能。下载 html5Widgets 脚本并在[github.com/zoltan-dulac/html5Widgets](https://github.com/zoltan-dulac/html5Widgets)找到实现细节。
颜色选择器
color输入类型创建了一个颜色选择器(也称为颜色井),可用于选择颜色,如图图 4-9 所示。提交表单时,颜色值作为 URL 编码的十六进制值 1 发送。例如,黑色(默认)将作为%23000000发送,其中“%23是散列符号(#)的 URL 编码,这意味着%23000000是颜色值#000000(这是在例如 CSS 代码中遇到颜色的更常见方式)。
**图 4-9。**用颜色输入类型创建的弹出颜色选择器,如 Opera web 浏览器所示
这个特定的输入可能看起来相当深奥,您甚至可能会问自己什么时候真正需要它。这里有一个例子可以让你了解如何使用它:一个包含“按颜色搜索”功能的搜索引擎,可能是汽车经销商搜索表单的一部分,允许用户在搜索新车时包含首选颜色:
<p><label>Preferred color: <input type="color" name="carcolor" /></label></p><sup>2</sup>
虽然您可能不会经常使用这种输入,但是当您需要它时,拥有它无疑是非常宝贵的。在一天结束的时候,能够给一个表单添加一些颜色是多么酷啊,实际上,表单经常是一个平淡无奇的文本输入域的海洋。
日期和时间输入
日期/时间控件是需要收集特定日期和时间的输入的网站的常见要求,例如机票预订网站或酒店住宿预订系统。为了满足这一需求,HTML5 增加了相当多的与选择特定日期和时间值及范围相关的输入。date、time、datetime、datetime-local、month和week输入类型创建了更细粒度或更粗粒度的收集时间和日期信息的方法。这些表单控件通常具有一个数字步进器和/或看起来像标准下拉列表的东西(图 4-10 )。目前最复杂的实现是在 Opera 中,当点击选择想要的日期时会产生一个弹出日历控件(图 4-11 )。
1 URL 编码是指将特殊字符转换成代码,通过网站 URL 地址安全传输。
正如在前面的例子中提到的,我们将在后面讨论标签元素。
***图 4-10。*Opera 网络浏览器中显示的所有不同的日期和时间相关输入。从上到下:date、time、datetime、datetime-local、month、week。
***图 4-11。*弹出一个日期/时间控件,显示 Opera 中自带的日历控件
这些输入类型可能比任何其他控件都更能显示 web 表单的新增功能有多少可能是免费的。图 4-11 中的日历控件由 web 浏览器提供,只有一行 HTML,这通常需要大量的 JavaScript、CSS 和 HTML 来创建。在撰写本文时,Opera 是唯一一个本地提供日历控件的浏览器,所以 JavaScript/CSS/HTML 解决方案仍然是大多数当代 web 浏览器需要的途径。不幸的是,如果可能的话,利用浏览器本身提供的功能,一旦这些输入类型获得了更广泛的支持,您的页面就可以过渡到本身提供的界面。我们只能希望其他 web 浏览器能很快跟上,但与此同时,jQueryUI ( [jqueryui.com](http://jqueryui.com))这样的项目可以与 Modernizr ( [modernizr.com](http://modernizr.com))结合使用,以便在不支持日期/时间输入时提供后备。jQueryUI 包含了一个名为 datepicker ( [jqueryui.com/demos/datepicker/](http://jqueryui.com/demos/datepicker/))的日历控件,它产生的日历控件与图 4-11 中的非常相似,但是由于它不是一个本地控件,如果控件是表单输入的一个关键部分,那么需要处理 JavaScript 被禁用的情况。
为了用日期/时间预设输入,可以为value属性提供一个设置初始值的文本字符串。表 4-2 显示了每个日期/时间输入类型的文本字符串的格式。
注意表 4-2 中datetime和datetime-local的区别。datetime中的 Z 表示输入的日期和时间被发送到服务器,并期望它们处于 UTC 时区(例如,在英国)。这为时间提供了一个公共时区,这可能更容易使用,但这意味着服务器、客户端或用户需要偏移这个时区才能到达他们自己的时区。另一种类型datetime-local不包含时区值,所以数据应该是访问者提交表单时所在时区的数据。
表 4-2 中的相同文本字符串格式也可用于min和max属性,这些属性可用于创建具有最小和/或最大允许日期/时间值的日期范围。此外,可以添加属性step来设置日期/时间字段可以移动的量。例如,对于涉及时间的输入类型(time、datetime和datetime-local),有一个 60 秒的默认步长,这意味着每单击一次控件以增加值,将向前(或向后)移动 1 分钟。对于包含时间的输入类型,step属性以秒表示,因此通过添加step="120",,默认值将变为 2 分钟(60 秒乘以 2)而不是 1 分钟。date、week和month输入类型具有更大的测量单位,默认步长值分别为 1 天、1 周和 1 个月。例如,下面的代码片段将提供一个控件,该控件允许选择每隔一周(通过将步长设置为 2 周),并且将限于(北半球)夏季的日期:
<input type="week" name="event" step="2" min="2011-W25" max="2011-W38" />
数字输入:数字和范围
number输入类型做了您所期望的事情——它处理数字输入。在支持的浏览器中,外观是类似于time输入类型的步进控件(图 4-12 )。与日期/时间控件一样,min和max属性可用于将可能的数字范围限制在一个范围内。此外,step属性可以用来增加或减少一定数量的值(默认为 1)。如果min和/或step属性设置为十进制值,则可以使用小数值。
***图 4-12。*正在输入数值的数字输入类型
在显示数字的实际值不是最重要的情况下,有range输入类型(图 4-13 ),它显示一个在最小值和最大值之间的可拖动滑块(默认为 0 和 100)。也可以在该类型上设置min、max和step属性。
***图 4-13。*默认情况下,范围不显示当前值。
搜索输入
search输入类型是 HTML5 中新增的最简单的类型。根据浏览器的不同,它可能与常规的文本输入类型控件没有区别。那么,它为什么会在那里?这是主要出于语义原因而添加的。将表单输入类型设置为search会将该字段与页面上的其他文本字段分开。在将来,这可以用于应用搜索字段所期望的功能或行为。例如,Safari 目前在搜索栏的右侧添加了一个 x 按钮,可以清除在栏中键入的任何文本(图 4-14 )。这与工具栏中内置的 web 搜索栏的行为是一致的。
图 4-14。 Safari 在搜索输入类型上默认提供了一个清除搜索的按钮。
个人详细信息:电子邮件、电话和网站 URL 输入
像search输入类型一样,最后三种输入类型——email、tel和url——只是附加了额外语义的文本字段。它们甚至看起来像普通的文本输入框(图 4-2 ),但是在表面之下,它们有一种特殊的品质,可以节省你在页面上摆弄脚本的大量时间。它们是展示 HTML5 中一个新特性——内置表单验证——的很好的例子!让我们来看下一个。
验证和提交表单
我在讨论form元素时顺便提到,有一个名为novalidate的属性可以添加到form中,以绕过许多验证规则,否则这些规则将在输入中被检查。这就像把表格拨回到过去一样。如果你想这么做的话,我只是提到它的存在,但是让我们看看这些验证规则是关于什么的。
取email输入类型;它提供了语义上的含义,即无论输入什么文本,都将采用有效的电子邮件地址的形式。这是提交表单时 web 浏览器可以检查的内容。如果输入的值不是一个格式正确的电子邮件地址,浏览器会抛出一个错误信息,告诉用户输入一个正确的值(图 4-15 )。
***图 4-15。*提交表单时,在email输入类型字段中输入的无效文本会产生验证错误。
对于不支持新的 HTML5 客户端验证的浏览器,可以包含一个由 Weston Ruter 编写的名为webforms2.js的 JavaScript 来提供支持。这个脚本可以在[github.com/westonruter/webforms2](https://github.com/westonruter/webforms2)下载。
注意在服务器端仔细检查从表单接收的输入也是一个很好的经验法则。这里显示的客户端验证行为主要是为了提高表单的可用性。它们为用户提供了一些即时反馈,告诉他们输入了错误的信息类型,而不需要您使用 JavaScript 或其他方式自己创建该功能。当在服务器端处理数据时,您会希望再次检查以确保提交了正确类型的信息。谁知道呢,也许用户从某个不支持客户端验证的不知名的 web 浏览器访问了您的表单,躲过了所有的浏览器嗅探检查,并在将电子邮件地址输入表单时设法破坏了它。这些事情会发生,所以在服务器上仔细检查提交的数据。
默认情况下,email输入类型只支持输入一个电子邮件地址,如果在该字段中添加了多个电子邮件地址,验证将会失败。然而,如果布尔属性multiple被添加到输入字段,这是可以改变的。然后,它将允许在单个字段中输入逗号分隔的电子邮件地址列表。
如果在字段中输入了错误的信息,输入类型url也会抱怨。输入的任何格式错误的 URL 地址都会引发类似于图 4-15 的验证错误。此外,它会在需要时添加http://来完成一个完整的 URL 地址。
tel输入类型稍微宽松一些,因为它不寻找特定的格式,但是如果输入了非数字字符,它会报错。由于电话的号码格式在世界各地都不相同,所以对号码的格式不可能有严格的要求。为了细化这种输入类型,使能够验证特定的电话号码格式,有一个属性就是为了这个目的。这个属性称为pattern属性,它将一个正则表达式(regex) 3 作为值,并根据它是否匹配 regex 来验证字段中的输入。正则表达式这一主题超出了本书的范围,但作为一个简单的例子,下面的代码片段将电话字段的输入限制为 NNN-NNN-NNNN 格式,其中第一个数字是 2 到 9 之间的数字,其余数字是 0 到 9 之间的数字 4 :
<input type="tel" name="usphone" pattern="^[2-9]\d{2}-\d{3}-\d{4}$" />
肯定是神秘的寻找!如果你想知道正则表达式是如何工作的,在网上快速搜索一下正则表达式,你会找到大量的资源。对于一些方便的、预构建的正则表达式模式来匹配从信用卡号到纬度和经度的一切,请查看[html5pattern.com](http://html5pattern.com),它还包括一个测试平台,您可以在其中开发和测试自己的模式。
注意
pattern属性不只是在电话输入类型上找到的;它存在于所有基于文本的输入类型中。那些是text、search、url、tel、email和password。
制作所需输入
一种更简单的验证形式(双关语)是要求在提交表单之前,至少给某些字段和表单控件赋予某种值。这就是布尔属性required可以被利用的地方。通过将此属性添加到表单控件:
<p><input type="text" name="example" required /></p>
如果在该字段中没有输入任何内容,将出现一个错误弹出窗口(图 4-16 )。
***图 4-16。*显示必填字段未填写的验证错误
使用按钮和图像提交表单
提交按钮用于将所有的表单数据提交到表单的action属性中指定的文件(如果没有指定action属性,则提交到表单本身)。正如本章前面提到的,button元素是一个比input元素更灵活的创建按钮的选项。例如,比较下面的 HTML 代码片段中的两行代码,它产生了图 4-17 中的按钮:
正则表达式是一种非常简洁的语法,用于匹配符合特定模式的文本。
理想情况下,正则表达式在构建时应该考虑到某些方面的灵活性,但在需要的地方要严格。这个简单的例子并不完全理想,因为它需要数字之间的破折号。最好是一个正则表达式,只要有适当的数字序列,它就可以处理任何破折号或没有破折号的组合。
`
Submit!
图 4-17*。*两个提交按钮,一个用input元素创建(顶部),另一个用button元素创建(底部)
由于button元素不是一个自结束元素,它允许 HTML 被包含在创建它的标签的文本中,这提供了更好的标签样式的可能性。
如果type属性被设置为type="reset",则创建一个重置按钮。重置按钮输入将同一表单中的所有表单控件重置为其初始值。包含重置按钮曾经是一种常见的做法,但后来变得不流行了,因为用户意外重置表单而不是提交表单的风险很高。如果没有任何撤消功能,重置按钮几乎没有什么用处,即使有也应该谨慎使用。
注意拜托,我们都做过这样的事情:到达一个表单的末尾,切换到我们认为是提交的按钮,按下回车键,绝望地看着所有的表单数据迅速消失。如果你曾经想过在一个表单上包含一个重置按钮,试着回忆一下过去你有多少次填写了一个表单,到达了末尾,然后想,“实际上,我想我会把它们都删除掉,不用麻烦了。”没错。
button元素的提交类型不与input元素重叠的一个用例是,如果您想使用一个图像作为提交按钮,在这种情况下,需要使用一个具有image的type属性和一个附加的src属性的input。虽然可以在按钮内部使用图像(如图 4-17 中的,但是使用图像输入控件会使整个图像成为按钮,而不需要浏览器添加任何额外的 UI 元素。src属性指向镜像文件在服务器上的位置,就像img一样。同样像img一样,出于可访问性的原因,记得包含一个描述图像用途的alt属性。
使用图像作为提交按钮也会将 x 和 y 坐标作为值发送(图像中您所单击位置的 x 和 y 坐标);这适用于图像提交与服务器端图像映射结合使用的情况。如果你的图像有一个name属性,那么它也会和坐标一起被发送。例如,如果您的表单使用了GET方法,图像提交按钮如下所示:
<input type="image" name="imagesubmit"/>
将像这样传递值:
handle_form.php?imagesubmit.x=10&imagesubmit.y=20
如果你没有用这些值做任何事情,不要担心它们。当它们与表单数据的其余部分一起提交时,它们不会造成任何损害。如果您真的想阻止它们在 URL 中出现,那么您可以将表单的属性从GET更改为POST,这将对用户隐藏所有的值。
其他常用输入元素属性
虽然不是表单控件功能的核心,但有几个属性值得注意。首先,有许多属性可以用来覆盖特定元素上的表单行为。表 4-3 列出了这些属性,从它们的名称可以看出,它们将覆盖父表单元素的属性中设置的特定值(如有必要,请参考表单元素属性的讨论)。
每个表单控件元素(button、input等等)还有一个名为form的属性,它可以用来将一个表单控件元素与一个不同于它在 HTML 结构中所包含的表单关联起来。如果通过一些示例代码来查看,这一点可能会更清楚:
`
Submit!
Submit!
`在这种情况下,名为example的input元素的form属性被设置为值form1 form2,这意味着它被视为包含 form1 和 form2。当提交任一表单时,example输入控件也将被提交。这样,form属性可以用来模拟一个嵌套的表单,即使 HTML 中不允许这种结构。还可以在提交按钮上设置form属性,这样一个提交按钮可以提交另一个表单。例如,如果您在页面的页眉和页脚中有一个搜索字段,并且希望两个搜索输入都提交到同一个表单,那么可以使用这个特性。页眉和页脚提交控件可以与同一个表单相关联,而不是将整个页面内容放在表单中(这将阻止在页面上创建其他表单)。
注同其他当代形式特征一样,歌剧在这一点上是领先群雄的。一定要在你的首选浏览器中测试这个特性,但是如果它还没有实现也不要惊讶!
提供占位符文本
可以对一个表单做一些小事情,使它变得更加完美和可用。这是一件这样的事情。您可以在表单中添加文本来提示它们的用途(地址、电话号码等),而不是在表单中设置空白文本字段。传统上,这是通过在input元素上设置value属性来完成的。这种方法的问题是,最初添加的文本可能会被删除,这对于实际上只是一个提示而不是一个可编辑的功能来说没有意义。这个问题已经在 HTML5 中用placeholder属性解决了。当文本字段为空时,添加到该属性的文本将出现在文本字段中。图 4-18 显示了这个样子。
图 4-18*。*四个不同的基于文本的输入字段(search、email、tel和url,添加了占位符文本
将输入设为只读
readonly属性可用于防止输入控件中的内容从其初始值被修改。如果通过 JavaScript 更新表单字段值而不允许用户更改该值,这可能会很有用,如果该值是以某种方式计算的结果,则可能会这样做。这是一个布尔属性,所以您可以简单地将它添加到元素中:
<input type="text" value="You can't delete this" readonly />
自动完成和自动对焦
自动完成是 web 浏览器的一项功能,用于帮助自动填写表单上的详细信息。如果有人在填写姓名、地址、电话号码等。,在不同的表单上重复(例如,在电子商务网站上创建帐户时),自动完成功能可以存储这些值,然后将它们填充到将来要填写的类似表单中。这是在 web 浏览器应用中设置的首选项。与这个特性相协调的是autocomplete属性,它允许浏览器的自动完成特性对表单中的单个元素或整个表单关闭。对于接收敏感数据或其他表单永远不需要的字段,可以这样做。该属性的值为on或off,如下所示:
<form method="post" autocomplete="off">
这将关闭本示例表单中所有表单控件的自动完成功能。
autofocus属性足够简单;它是一个布尔属性,当添加到一个表单控件中时,当页面加载时,焦点会立即跳转到指定的元素。这意味着用户可以立即开始输入,而不需要事先单击第一个(或任何一个)元素。它由button、input、keygen、select和textarea支撑。只有当页面上没有其他用户想首先点击的输入时,添加这个属性才是一个好主意。
使用数据列表
大多数输入类型都包含一个名为list 5 的属性,它与一个新元素datalist一起工作。此元素定义了在表单控件输入中输入数据时可用的选项列表。datalist元素本身并不显示在网页上,而是向表单中其他元素的list属性提供数据。举个例子,让我们从一个在线工作申请的表单中截取一个片段。可能会有一个文本输入字段,要求输入期望的工资范围,如下所示:
<p><input type="text" name="salary" placeholder="Enter desired salary" /></p>
用户可以输入任何金额,但提供一个常用值列表供用户选择会有所帮助。例如,可能会显示以下值:
40,000+
60,000+
80,000+
100,000+
120,000+
这些可以表示为数据列表,如下所示:
<datalist id="salaries"> <option value="40,000+" /> <option value="60,000+" /> <option value="80,000+" /> <option value="100,000+" /> <option value="120,000+" /> </datalist>
然后,文本输入字段可以通过将其list属性设置为数据列表的 ID 来使用该列表:
<p><input type="text" name="salary" placeholder="Enter desired salary" list="salaries" /></p>
结果是当用户开始在字段中输入一个值时,数据列表中的相关匹配就会弹出,如图图 4-19 所示。
5 排除的有password、checkbox、radio、file、hidden、image、button、submit、reset。
***图 4-19。*显示数据列表如何与文本输入字段相关联的三个面板。当将焦点放在文本输入字段中时,会出现关联的数据列表,并且随着字母的键入,列表会缩小到匹配的选项。
其他表单控件
毫无疑问,input元素是一个大而通用的元素,但它不是唯一的表单控件。我们已经谈到了button,但还有select(和option)和textarea。然而,这些对 HTML5 来说并不陌生。增加的是datalist,这在之前的章节中已经介绍过了;progress;meter(又称规);output;还有keygen。让我们从旧的到新的,看看每个还没有被覆盖的控件。
菜单
select元素是一个容器元素,允许任意数量的option和optgroup元素。通常显示为下拉列表,如图图 4-20 所示。
图 4-20。 A select菜单
这个元素有两个其他地方没有涉及的特定属性,disabled和size。 6 它也可能使用multiple属性(在本章前面的file输入部分首次提出)。可以添加布尔disabled属性来禁用(灰显)用户与菜单的交互。size和multiple属性是相关的。如果添加了布尔multiple属性,select菜单通常会显示为一个可滚动的列表框,允许用户通过按住 Command 键(Mac)或 Control 键(Windows)并单击多个项目来进行多项选择。接受数值的size属性决定显示多少行选项。图 4-21 显示了一个列表菜单的例子。
6 它还拥有第二章中涉及的全局属性以及本章前面涉及的name、required、autofocus和form属性。
***图 4-21。*一个列表菜单,用添加了multiple属性的select元素创建
select中的每一行都包含在一个option元素中,如下所示:
<select name="cheesemenu"> <option>Cheddar</option> <option>Stilton</option> <option>Brie</option> </select>
注意前面显示的
datalist元素也使用了option元素,但是用自结束标记对它们进行了格式化,并对列表数据使用了value属性。
option元素有四个特定的属性:disabled、selected、value和label。像select上的disabled属性一样,这是一个布尔属性,它阻止用户选择菜单中的特定项目。布尔selected属性用于向用户代理指示最初应该选择特定的option;没有它,浏览器可能什么都不显示(只是一个空白的选择框)或者显示它遇到的第一个option。例如,默认选择第二个选项,添加selected,如下所示:
<select name="cheesemenu"> <option>Cheddar</option> <option selected>Stilton</option> <option>Brie</option> </select>
多个option元素可以设置selected属性,但前提是select添加了multiple属性。
添加不同的值
value属性用于允许提交不同于特定option内容的值。如果省略了value属性,那么内容被用作值。例如,给定以下菜单:
<select name="cheesemenu"> <option value="ch01">Cheddar</option> <option value="ch02">Stilton</option> <option>Brie</option> </select>
如果选择了第一个或第二个选项,它们将分别提交值ch01和ch02。如果选择第三个选项,它将使用内容“Brie”作为其值,因为没有指定的value属性。当您向用户显示的内容与您要提交给服务器的内容不同时,这种行为非常有用。例如,如果您正在为一个电子商务网站构建一个表单,您可能会有一个产品下拉菜单。您可能希望向用户显示产品的名称,但是某种类型的产品编号对您来说在服务器端进行管理要容易得多。因此,在添加每个产品名称的同时,您可以将产品编号作为一个值添加到列表中的每个option中。名称会显示给用户,但是在选择产品并提交表单后,产品编号会提交给服务器。
注意在实践中,所有的选项都应该一致地使用或者不使用
value属性。
添加速记标签
最后,我们来看一下label属性。该属性被设计为接受一个短值来代替显示一个option的内容。label属性可以用来提供一个可选的显示标签,同时仍然保留传递给服务器的值的原始内容。这方面的代码如下所示:
<select name="cheesemenu"> <option>Cheddar</option> <option>Stilton</option> <option>Brie</option> <option label="All">All of the cheeses in all of the worlds</option> </select>
添加菜单结构
为了帮助为你的菜单提供结构,你可以使用optgroup元素来分组相似的option元素。因此,不用下面的标记:
<select name="cheesemenu"> <option>- - - English cheeses - - -</option> <option value="cheddar">Cheddar</option> <option value="stilton">Stilton</option> <option>- - -French cheeses- - -</option> <option value="brie">Brie</option> </select>
你可以用这个:
<select name="cheesemenu"> <optgroup label="English cheeses"> <option value="cheddar">Cheddar</option> <option value="stilton">Stilton</option> </optgroup> <optgroup label="French cheeses"> <option value="brie">Brie</option> </optgroup> </select>
前面的标记将如图 4-22 所示。
图 4-22*。**一个由多个optgroup元素*组成的select菜单
optgroup元素是为正确的作业使用正确标签的一个明显例子。使用optgroup元素划分option元素的一个好处是optgroup标签不能被选择,它的值也不能作为数据提交,而在前一个例子中,页面作者要么不得不忍受错误的提交,要么提供一个客户端或服务器端的验证器来确保这样的划分符没有被提交。另外,optgroup元素有一个布尔disabled属性,如果需要的话,可以用来禁用整组option元素。
文本框
textarea元素在某些方面类似于 text input元素,但是它允许多行输入,而不是只有一行。它使用一对属性cols和 r ows来控制它的大小,而不是使用一个value属性来预设任何文本内容,而是使用元素本身的内容。它是一个容器元素,而不是一个自结束的空元素。
下面的代码创建了一个 20 列宽 5 行高的textarea(如果输入超出了可视区域,就会出现滚动条)。
<textarea cols="20" rows="5">Type your content here</textarea>
尽管textarea元素是内容的容器,但是使用新的placeholder属性并将元素中的内容留空会更好地格式化前面的代码,如下所示:
<textarea cols="20" rows="5" placeholder="Type your content here"></textarea>
图 4-23 显示了结果。
图 4-23。 A textarea 20 列宽 5 行高,添加了占位符文本
textarea元素包含一个在别处没有提到的属性:wrap。此属性用于指示是否应该在文本框的可用区域中文本换行的位置向提交的文本区域数据添加换行符。这个属性的值可以是hard或soft。第一个是hard,意思是在提交的表单数据中,在文本区域中提交的文本换行的地方添加换行符。在这种状态下提交表单后,您会在 URL 中看到 URL 编码的换行符,看起来像%0D%0A(如果使用GET方法)。另一方面,soft值意味着虽然文本可以在屏幕上换行,但提交的数据将在没有任何换行符的情况下发送,该换行符指示文本在文本区域中的换行位置。这是默认行为。
文本区域控件也可以使用maxlength属性来限制可以输入的字符数量;这类似于maxlength属性在单行文本输入控件上的工作方式,同样的注意事项也适用(也就是说,如果数据长度非常重要,请在服务器端仔细检查长度)。
显示进度
这是 HTML5 规范中的一个新元素,非常简洁!从根本上来说,这很简单:展示一个人在一个多阶段的过程中走了多远。例如,一个表单可能分布在多个页面上,这个元素用于指示用户在页面总数中的哪一页。这个元素叫什么?progress!它是这样工作的:有两个属性,max和value。max属性是任务中的最大步骤数,而value是用户正在进行的当前步骤。
让我们看一个例子:
<progress max="3" value="1">Step 1 of 3</progress>
这定义了处于三个步骤的第一步。在支持该元素的浏览器中,显示可能类似于图 4-24 。
***图 4-24。*在支持的网络浏览器中呈现的progress元素
注意对于那些不支持该元素的浏览器,在元素的标签之间放置一些有意义的文本是很重要的,因为这将在不支持进度元素的情况下显示(图 4-25 )。
***图 4-25。*在不支持progress元素的 web 浏览器中,元素标签之间的文本内容将被显示。
显示仪表
meter元素(图 4-26 )可能看起来与progress元素(图 4-26 )相同,但是有一个重要的示意性区别。progress元素用于显示任务中步骤的进度,而meter元素用于显示一个量表——即一个已知范围内的特定值。它可以用来显示还有多少硬盘空间或还有多少库存。
***图 4-26。*谷歌浏览器中出现的meter元素
min和max属性设置范围的最小值和最大值,而value属性设置仪表在范围中的位置。该元素还具有许多属性,用于示意性目的,以确定特定值在设定范围内的含义。optimum、low和high属性允许将范围分割成区域。这可被网络浏览器用来根据数值在范围内的位置显示不同的量规,如图 4-27 中的所示。
***图 4-27。*一个meter元素通过高低范围减少数值
前面仪表的代码如下:
`
Space left: 100%
Space left: 90%` `
Space left: 80%
Space left: 70%
Space left: 60%
Space left: 50%
Space left: 40%
Space left: 30%
Space left: 20%
Space left: 10%
Space left: 0%
`注意,和progress元素一样,一些描述性的文本内容被放置在meter元素的标签之间。此内容将在不支持该元素的 web 浏览器中显示。
显示计算的输出
output元素用于显示计算结果。它在很大程度上是一个语义元素,因为输出看起来像页面上的纯文本。
除了全局属性和form和name属性(前面已经讨论过了),output元素还有一个属性:for。这个属性应该包含一个元素的 id 列表,这些元素将进入这个output元素正在显示的计算中:
<input id="inputa" type="number"> + <input id="inputb" type="number"> = <output id="resultfld" name="result" for="inputa inputb"></output>
典型的用例是显示脚本生成的计算结果。下面的脚本将在每次两个数字输入改变时更新output元素的值:
var inputa; var inputb; var resultfld; function init(){ inputa = document.getElementById("inputa"); inputb = document.getElementById("inputb"); resultfld = document.getElementById("resultfld"); inputa.oninput = updateResult; inputb.oninput = updateResult; } function updateResult(){ resultfld.value = Number(inputa.value)+Number(inputb.value); } window.onload = init;
密钥生成器
keygen元素用于生成一个私有和公共密钥,其公共端在表单提交时被发送到服务器。元素本身看起来相当神秘,因为默认情况下它是一个数字下拉列表,仅此而已。这些数字是加密算法中使用的密钥的位数。数字越大,密钥越难破解。这个元素的预期用例是,服务器将生成一个证书并发送给客户机,以便在两者之间建立可信的安全通信。web 页面和 web 服务器之间加密通信的加密技术超出了本书的范围,除非您已经对加密技术有所了解,否则您不会使用这个元素。 7 即使你对密码学有所了解,也不要过于依赖当前形式的这种元素。它很有可能在未来改变方向(毕竟 HTML 规范仍处于草案阶段)。例如,微软的代表已经声明他们无意支持keygen ( keygen最初是由 Internet Explorer 的竞争对手 Netscape 开发的,所以微软从不同的方向着手实现加密)。当前对元素进行标准化的方法使得所使用的实际算法是可选的,以便元素本身可以被支持(为了向后兼容),但是加密组件可以被省略。微软是否在这些条款下实现该元素还有待观察。除非你别无选择,否则你最好暂时不要管keygen,直到尘埃落定。
这种的分歧导致了
video元素中的视频编解码器没有标准化,正如你将在第五章中看到的,这意味着需要提供不止一个视频文件来兼容所有主流浏览器。
IBM 出版了一本关于公钥加密的初级读本,你可能想看一看以熟悉其中的概念:【www.ibm.com/developerwo…
添加带有字段集和标签的结构
元素允许 web 作者将表单控件分成主题链接的部分,使用户更容易地处理表单,同时也增强了辅助设备的可访问性。大多数浏览器会显示一个带有简单边框的fieldset。例如,下面的标记显示了如图图 4-28 所示的结果:
`
Cheddar Stilton Brie
Submit!
` ***图 4-28。*一个fieldset 的通常渲染的例子
要识别每个fieldset,必须使用legend元素:
`
Cheeses of the worldCheddar Stilton Brie
Submit!
`该表单现在看起来类似于图 4-29 。
***图 4-29。*一个fieldset带一个legend带一个
最后要提到的表单元素label,也增加了可用性和可访问性。该元素用于在文本标签和表单控件之间建立关联。当标签和表单控件相互关联时,可以单击其中任何一个来与控件进行交互。例如,与复选框相关联的标签意味着可以单击该标签,然后它会选择该复选框。有两种方法可以在标记中创建这样的可点击标签。第一种也是更好的方法是将表单控件包含在一个label中。这里有一个例子:
<label>Favorite cheese: <input type="text" name="ch" /></label>
在前面的例子中,单击标签中的“Favorite cheese:”文本会使嵌套的input获得焦点,在这种情况下,这意味着用户可以开始在文本字段中键入内容。另一个解决方案是使用for属性:
<label for="favcheese">Favorite cheese: </label> <input type="text" id="favcheese" name="ch" />
使用for属性的好处是表单控件不需要出现在label内部。属性for中的值是关联表单控件的 ID,这意味着两者是关联的,即使它们位于标记中不同的位置。这可能是有用的;然而,由于这种属性的手动配对,使用for属性可能会很费力。除非万不得已,否则我不建议使用它。一个用例是表单出现在表格中,标签出现在一列,表单控件出现在另一列。
注意切记表格仅用于按行和列排列表格数据,不应用于布局;这包括使用一张桌子的唯一目的是美观地布置一个形式!为此,请改用 CSS。
把所有这些放在一起
还记得市按吗?上一章虚构的报纸网站?让我们看一下收集新闻提示的站点表单,这样我们就可以看到所有这些表单控件集合在一起。
第 1 页,收集用户详细信息
该表格分为两页,第一页用于在网站上注册举报人,第二页用于记录他们的新举报。表单的首页看起来像图 4-30 。
图 4-30。**第一张表格在市按“提交小费”表格
要创建这个表单,首先我们需要一个form元素。我们将设置两个属性:action,它将转到我们的第二个表单页面,以及method。我们需要哪种方法?GET 还是 POST?嗯,用户将提交数据,这些数据很可能最终会存储在数据库中,所以这是一个主动修改数据的提交。所以,我们用 POST。此外,如果表单上出现密码输入字段,这应该是使用 POST 的一个很大的提示,它确实出现了。好,这是我们的开始形式:
<form action="form2.php" method="post"> </form>
接下来,虽然表单跨两个页面,但是有三个步骤来处理表单,因为在数据提交后会有一个确认页面,所以我们应该添加一个progress元素来显示:
`
Progress: 1/3
`请注意,value属性被设置为零,max被设置为二,但是替代内容文本是“1/3”这是因为我们将有三个步骤要完成:第一个表单、第二个表单和第二个表单提交后的确认页面。因此可选文本将会是 1/3,2/3,3/3,而value属性将会是 0,1,2。
接下来,我们看到我们需要用户创建一个用户名和密码(假设在完成这个过程后,他们能够在其他地方登录),我们可以将它们分成自己的字段集。图例用于向字段集添加标题,文本和密码输入字段设置为必填。此外,占位符文本也被添加到两者中。一个正则表达式模式被添加到密码字段,以便它只接受六个字符或更长的密码。
`…
Register New UserUsername:
Password:
…`在此之下,我们为个人详细信息区域添加了另一个字段集。第一个字段是一个通用文本输入字段,用于收集举报人的姓名。添加占位符文本,提示要输入的信息的格式:
`…
Personal DetailsName:
…`姓名输入之后是一个文本区域,用于收集举报人的邮件地址,之后是单行文本输入,用于收集城市名称。对于地址输入,我们可以使用label的for属性在标签和文本区域之间放置一个换行符。在这种情况下不需要for属性,但是您可能会发现这是一种更干净的方法,因为它防止在label的标签中包含额外的 HTML 元素:
… <p><label for="address">Address:</label><br /> <textarea id="address" name="address" cols="20" rows="5" placeholder="mailing address"></textarea></p> <p><label>City: <input type="text" name="city" placeholder="mailing address city" /></label></p> …
接下来是状态字段。这里的一个选项是使用select元素创建一个下拉列表,其中填充了所有 50 个州。当我们确信只有美国人才会填写这个表格时,这可能是最好的选择。但是,假设我们不确定用户一定来自美国。在这种情况下,另一种方法是有一个常规的文本输入字段,但将其属性设置为包含州名(或缩写)的数据列表。就在开始表单元素的下面,为此添加了一个新的datalist元素:
<form action="form2.php" method="post"> <datalist id="statelist"> <option value="AL" /> <option value="AK" /> <option value="AZ" /> <option value="AR" /> <option value="CA" /> <option value="CO" /> <option value="DE" /> …
然后回到个人详细信息字段集,添加州的文本输入。还添加了邮政编码输入字段:
… <p><label>State: <input type="text" name="states" list="statelist" placeholder="two- letter abbreviation" /></label></p> <p><label>Zip code: <input type="text" name="name" placeholder="00000 or 00000-0000" /></label></p> …
接下来是这个集合中唯一的必填字段,即电子邮件地址字段。占位符文本会提醒用户输入有效的电子邮件地址,但是表单的自动验证也会发现任何不一致之处:
… <p><label>Email: <input type="email" name="name" placeholder="you@example.com" required/></label></p> …
接下来,添加可选的电话和网站输入字段:
… <p><label>Phone: <input type="tel" placeholder="000-000-0000" /></label></p> <p><label>Website: <input type="url" placeholder="http://example.com" /></label></p> …
最后,在这个字段集中,可选的年龄字段被添加为数字输入字段。min和max属性被设置为真实的年龄范围,在上端有一些填充。结束 fieldset 标记结束该组:
`…
Age:
`接下来,一个必需的颜色选择器输入被用作对自动垃圾邮件机器人的简单检查,自动垃圾邮件机器人可能无法为“雪”选择正确的颜色。遗憾的是,pattern属性在color输入类型上不可用,所以这需要在服务器端用 JavaScript 进行检查。我们假设正在服务器上检查它:
… <p><label>Spam check. What color is snow? (choose a color) <input type="color" name="captcha" required/></label></p> …
最后,在结束的form标签之前添加一个提交按钮,完成这个表单:
`… Submit
`第 2 页,采集评论
在填写完表单并点击提交后,用户会在第二页上看到第二个表单,如图 4-31 所示。
***图 4-31。*第二张表单上的城市按“提交小费”表单
像第一个页面一样,form元素是用action和method属性创建的。此外,因为表单上有一个文件输入字段,所以我们将enctype属性设置为multipart/form-data,这样就可以发送二进制数据。接下来,添加一个progress元素,并在第一个表单上出现的元素的基础上递增:
`
Progress: 2/3
`接下来,为提示详细信息区域创建一个字段集和图例。为新闻事件的当地日期和时间添加了日期/时间输入字段。一个textarea元素用于收集提示细节,一个文件输入用于允许在必要时附加一个支持文件:
`…
Enter Tip DetailsDate/Time of incident:
Tip details:
Attach supporting file:
…`接下来,添加一个范围输入类型作为提示的“重要性”滑块。然后关闭该字段集。滑块旁边是一个只读文本输入栏,其中包含占位符文本,表示滑块上的值越大表示“越紧急”:
`…
Urgency:
…`使用 JavaScript,我们将使只读文本输入中的值在滑块移动时动态更新。我们将设置占位符文本,以指示滑块上的高数字表示“最紧急”,并在移动滑块时将文本输入更新为滑块的值。JavaScript 被添加到文档头的script元素中:
`…
…`
注意记住,在生产环境中,你可能希望将你的脚本转移到一个外部文件中,因为这样可以更好地组织你的标记和脚本。
为关于提示的“通信首选项”创建一个新的字段集。提供复选框来指示是否可以联系用户。如果是这样,那么另一个字段集嵌套在第一个字段集中,其中两个单选按钮允许用户选择他们喜欢的联系方式。默认选择“电子邮件”(带有checked属性):
`…
Communication PreferencesMay we contact you about this tip?
Preferred contact method:Phone:
Email:
…`接下来,一个meter给出了该报目前人员配备情况的一些指标,10 个员工中有 6 个在办公室。我们不会推测这个度量工具更新的频率,但是在这里使用它是一个合适的元素,因为员工数量是一个已知的量。
最后,像最后一个表单一样,提交按钮出现在最后,表单关闭:
`…
Staff in the office 6/10
Submit `第 3 页,提供确认
提交第二个表单会将用户带到确认页面,在这里,progress元素被更新到它的最终位置,并给出一条简短的感谢消息:
`
Progress: 2/2
The tip was successfully received. Thank you!
`结果页面看起来像图 4-32 。
***图 4-32。*第三页也是最后一页致谢
表单可用性
创建一个表单很容易,但是创建一个真正好的表单要难得多。 City Press 提示表单显示了创建简单表单时需要考虑的所有选项和输入变量。表单变得越复杂,就越像是一个应用而不是网页,所以你需要认真考虑可用性。即使是在城市媒体的提示表单中,也可以添加更多来使其更加有用。例如,可以将title属性添加到所有输入字段中,以便在用户将光标悬停在这些字段上时(或使用屏幕阅读器)提示这些字段所期望的内容。然而,事情比这更严重。如果你的表单处于公众开始给你钱的时候,你需要严格地测试你的表单,观察人们使用它并记录他们的反应(即使你的观众只是办公室另一边的几个同事),并确保它尽可能地工作。
对表单可用性主题的详尽讨论已经超出了本书的范围,但是下面几节中概述的指南应该足以帮助你避免一些常见的表单可用性问题。除了这一章中的信息,我推荐你阅读史蒂夫·克鲁格的经典之作不要让我思考:网站可用性的常识方法(New Riders 出版社,2000)。
将正确的输入用于正确的工作
因此,您知道所有的输入类型,但是在给定的情况下,哪种输入类型更合适呢?其中一些是显而易见的——file输入只有一个目的,没有其他类型的输入可以代替它——但是,例如,复选框和单选按钮呢?一个好的经验法则是,如果你有两个或更多选项的列表,用户必须选择一个而只能选择一个,使用单选按钮。选择一个单选按钮应该会取消选择属于同一命名组的任何其他单选按钮。但是如果列表包含许多选项,可以考虑使用一个select菜单。您将无法选择多个选项,并且您将节省一些空间(以“可发现性”为代价)。
另一方面,当有几个选择时,就使用复选框,用户可以把它们都留为空白,也可以选择任意多个。选中一个复选框不会取消选择该组中的任何其他复选框。与一系列复选框相对应的菜单是一个带有multiple 属性的select菜单,但是复选框通常更容易使用,因为它们不需要用户理解使用什么键盘/鼠标组合来选择/取消选择选项,所以您可能希望尽可能避免多选列表。
当只有一个用户可以打开或关闭的选项时,也应该使用复选框,比如同意订阅时事通讯。您不会在这里使用单选按钮,因为单选按钮只能通过选择另一个来取消选择。
还记得使用标签、字段集和图例来帮助提高可用性和可访问性。
保持简洁明了
只收集你需要的信息,仅此而已。你真的需要知道我是先生还是女士吗?你真的需要我的传真号码吗?我的职业?我的年薪?质疑表单中每个字段的存在,如果是必填字段,再次质疑它是否需要。你的营销人员可能喜欢收集大量网站访问者的个人数据,但是你的表单越长,越多不相关的用户开始感觉到它,他们放弃它的风险就越高。
不要让我思考,不要让我工作,也不要试图欺骗我
尽可能使您的表单易于完成。如果在任何时候,用户不得不暂停几秒钟,试图找出哪里出了问题,或者你的意思是什么,那么这几秒钟他可能只是想“哦,算了”,然后去做三明治。因此,例如,如果您的表单包含必填字段,请考虑将这些字段的样式设计得更突出(当然,还要添加required属性,这样表单验证就会生效)。从一开始就明确必须填写的字段。如果这是大多数字段,请考虑在可选字段旁边添加文本“可选”。
如果您需要某种格式的数据,不要依赖用户以这种格式输入数据——这是服务器上的表单处理程序应该处理的事情。例如,如果用户需要输入信用卡号码,如果她愿意,让她填写 1234 5678 9012 3456(这是她信用卡上的格式),1234567890123456,或 1234-5678-9012-3456——在合理范围内对用户有效的任何数字。灵活使用pattern属性可以允许表单输入的灵活性,但仍然可以验证关键信息和基本格式(比如检查输入的数字是否正确)。记住,计算机应该为用户节省时间。如果你愿意,可以提供一个首选格式的指南,但也要考虑到备选条目的可能性。
如果用户犯了一个服务器端代码无法解决的错误,那么用一个清晰、有意义、适当的错误消息让他知道——越快越好。使用内置的表单验证,并提供 JavaScript 和/或服务器生成的验证和错误消息作为备份。表单越复杂,出错的地方就越多,所以测试,测试,测试,确保没有无意义的错误信息。
请记住,互联网是全球性的
如果您的表单不针对任何一个国家,请尽量不要填写“州”和“邮政编码”,当然,如果您包含这些字段,也不要强制填写。同样与前一点相关的是,不要试图限制用户数据的格式,除非你完全确定它的格式。
注意与表单国际化相关的一个即将出现的属性是
dirname属性,它是在textarea、text输入和search输入元素上指定的。还记得表单数据是如何作为键/值对提交的吗?该属性创建一个发送到服务器的键,该键以输入到表单控件中的文本的方向性作为其值。这将显示为ltr(从左到右)或rtl(从右到左)。但是,不要指望这个属性今天还能工作,因为它还没有被主流浏览器实现。关于它的更多信息和代码示例可在[dev.w3.org/html5/spec/common-input-element-attributes.html#attr-input-dirname](http://dev.w3.org/html5/spec/common-input-element-attributes.html#attr-input-dirname)获得。
需要时提供后备
本章中的很多内容都是新的,可能并不适用于所有的浏览器。幸运的是,当不支持特定的输入类型时,输入类型通常会退化为常规的文本字段。但是,如果您设计了 HTML5 规范中所有丰富的控件,但没有考虑它在旧浏览器中的外观,这仍然会对表单的可用性产生严重影响。调查像 Modernizr ( [modernizr.com](http://modernizr.com))、jQueryUI ( [jqueryui.com](http://jqueryui.com))和 webforms2 ( [code.google.com/p/webforms2/](http://code.google.com/p/webforms2/))这样的项目,因为这些项目将帮助您将“polyfills”实现到您的站点中,这意味着它们(通过 JavaScript)提供了您期望在浏览器中本机可用的功能。
总结
创建表单相当容易——只需插入几个input标签,添加一点文本,点击最后的提交按钮,然后您就可以早点回家了——但是创建可用的、可访问的、符合逻辑的表单要困难得多。思考你的表单内容的意义。哪些原理图元素适合用作输入?这些都不是应该留到最后一刻的事情。你的表单可能是你的网站最重要的部分,特别是如果它是一个允许人们输入信用卡信息的表单,所以它应该是一个简单易用的模型。它不应该让人们心烦意乱,激怒他们,或者打消他们的念头——这么说似乎很奇怪,但我这辈子见过一些可怕的形式就是这样做的。最后,要准备好面对现实,为了创建最终可用的表单,您必须求助于 JavaScript 或服务器端代码(或者两者都用)来帮助您为用户提供现代 web 表单的预期特性。