《HTML5移动开发》—— 2.1 HTML5语法

  1. 云栖社区>
  2. 博客>
  3. 正文

《HTML5移动开发》—— 2.1 HTML5语法

异步社区 2017-05-02 09:50:00 浏览1122
展开阅读全文

本节书摘来异步社区《HTML5移动开发》一书中的第2章,第2.1节,作者:【美】Estelle Weyl(埃斯特尔 韦尔),更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.1 HTML5语法

HTML5与HTML4与XHTML非常类似。后两者支持的大部分元素在HTML5中仍然是支持的。只有一些过时了的标记和属性已被剔除。在大多数情况下,如果你的文档能通过HTML4严格(Strict)模式或是XHTML模式的验证,那么它们作为HTML也能通过验证[1]。HTML和XHTML的语法虽略有不同,但是两者都被支持。仅仅把HTML 4.01或XHTML的doctype改成,就可以通过HTML5验证(稍后将介绍更多有关doctype的内容)。

HTML5比HTML4和XHTML更好,包含了之前版本的元素,剔除了已过时的元素,添加了一些新元素,还重新定义或微调了另外一些元素。

HTML5规范的编写者调查了Web上那些开发者们已经在做的:哪些文档分段是各种网站都趋向的,他们都赋给这些组件哪些类(class)和ID,哪些脚本是大多数的网站作者反复使用的,以及哪些类库功能已经激增至普遍存在。

HTML5试图处理那些个人开发者们一直自行在做的:创建一个标准;详细说明浏览器都应该如何处理这些标准;以及当他们的代码,呃,不那么标准的时候,浏览器应该如何处理开发人员标记。HTML5规范明确细化了浏览器应该如何处理,或解析,各种代码正确或错误的情况。通过关注细节,HTML5的一个目标就是告诉浏览器如何处理所有可能会发生的情况,从而浏览器可以从同样的标记构造出一致的DOM,这样开发人员就不会一直把带宽浪费在处理浏览器差异上了。

从我个人而言,我乐于见到更严格的标准。我的观点是开发者们应该正确地编写代码,而不是指望浏览器从宽解析糟糕的代码。你正在读这本书,所以我假定你是“良好代码”阵营的一员。很好!这就是你要学的东西。

2.1.1 元素

Web页面是由一系列元素组成的。有些元素是空的,其他的元素则包含文本,而另一些可以包含其他元素(或者既有元素也有文本)。大多数元素可以包含子元素或文本节点。那些不能包含子元素的,例如图像和meta元素,称为空元素(empty element)。

如图2-1所示,一个元素就是一个结构体,由一个开始标记、一些可选的(有时是必需的)属性、通常还有一些内容,以及一个结束标记,而且如果你使用XHTML风格编写代码的话,还有一个专门针对像<img><input>这样空元素自闭合标记的可选的斜杠组成。

b90812128cbfaaa734b2f248b24c8eca7e24a12f

在HTML之前版本的中,内联元素(inline element)只能包含其他内联元素和文本。根据元素的不同,块级元素(block-level element)可以包含其他块级元素、内联元素和(或)文本。它们的“后代”元素(descendant element),像“祖先”元素(ancestor element)一样,也可以由元素、属性和文本组成。

使用CSS,你可以把任何短语元素[2](phrase element)的样子更改成块(block)显示,还可以强制一个块元素或区块元素(sectioning element)显示成内联的样子(注意:我仍然在使用内联这个词。在HTML5中,内联指的是外在表现,而不是指元素类型)。
在HTML5中,我们终于从内联元素还是块元素的观念中解脱出来了——基于外观的命名约定。在HTML5中,元素被定义为区段元素、标题(heading)元素、短语元素、嵌入式(embedded)元素、流(flow)元素、元数据(metadata)元素以及交互式(interactive)元素。不过在语义上,一些观念还是保持不变的。举例来说,区段元素不能位于短语元素内部。

在选择一个元素时,要基于语义选择最恰当的元素,而不要基于默认的浏览器渲染。虽然你确实可以针对不管什么文体上的目的而使用任意元素,但你不应该这样做。每一个元素都有语义上的含义。

2.1.2 属性

所有的元素都可以有属性。有些元素有必需的属性。有关属性的一个例子是元素的href属性,如图2-1所示。属性是典型的键/值对(name/value pair),尽管布尔属性的值是可选的[3]。属性为渲染引擎提供了有关元素的附加信息,并且都位于开始标记中,而不在结束标记中。

有几个属性对于几乎所有HTML5元素来说是全局的(global)——包括核心(或全局)属性和国际化(internationalization)属性(将在下一节中介绍)——以及另一些更加元素特有的属性,这些我们将在第3章当讲到这些属性正在被修改的元素时进行介绍。

2.1.3 全局属性和国际化属性

HTML5已经添加了几个国际化属性和核心属性,这些属性可以被应用到几乎任何元素上。

id、class、title、style、lang和dir属性继续在所有元素上被支持。HTML5往核心属性列表中添加了accesskey、hidden和tabindex属性,同时还有contenteditable、contextmenu、spellcheck、draggable和dropzone共5个建议性的交互式属性。随后将讨论这些属性。

除了全局属性,所有的元素也可以有微数据(microdata)属性(WIA-ARIA角色和aria-属性)和自定义数据属性。自定义数据属性是你自己的属性,写成data-的形式,这里的由你自己设置。HTML5通过添加data-前缀以允许开发者们创建不会与未来的HTML版本冲突的属性。我们将在“data-自定义数据属性”小节描述data-属性,在第6章介绍微数据和ARIA无障碍属性。

id
id属性是一个唯一标识符。每个文档不应该存在具有相同id的两个元素,并且每个元素最多也只能有一个id。在HTML5中,id的值必须至少一个字符长,而且不能包含空格。这与之前的版本有所不同,之前版本id的值必须以字母A-Z或a-z开始,后面可以跟字母(A-Za-z)、数字(0-9)、连字符(-)、下划线(_)、冒号(:)和句号(.)。

我建议你把id限制于仅使用字母和数字,然而无论你选择使用哪种命名约定,重要的是保持统一。
id属性一般是可选的。不过,对于内部页面锚点(anchoring)和正在实现显式标签(explicit label)的表单内部元素是必需的。通过使用标签的for属性和表单元素的id属性可以把显式标签和表单元素关联起来。要注意的是,对于嵌套在一个隐式标签(implicit label)之内的表单元素,id属性不是必需的。我们将在第4章讨论标签和id属性。

id属性作为一个锚点用于使用JavaScript进行定位也非常方便,只是可能有一点重度使用。id属性,如果有被包含的话,可以用在CSS中定位元素。然而,由于id在CSS样式中的高量值或特征性,即使id选择器用起来稍微更好一些,id值也应该尽量少在CSS选择器中使用。所有这些我们将在第6章讨论。现在你只要知道,在你读完这本书的时候,你将能意识到你可以使用CSS3选择器定位到页面中的任何元素,而不需要使用id选择器就够了。

class
class是该元素所属的一个类别的名字或一些类别的列表。class属性具体说明了该元素是哪一个或哪一些类的一员。和id属性不同,任何数量的元素都可以共用同一个类。一个元素可以有多个使用空格分开的类。

就CSS样式而言,class属性中类名的顺序无关紧要。然而在样式表(stylesheet)中的顺序,却很重要(这个问题我们将在第6章进行讨论):

<a href= " http://google.com " class="external popup search">link text</a>
title```
title属性为它应用到的任意元素提供了一种人工可读的描述。title属性在有些可视浏览器上经常被实现为一个“工具提示”(tooltip),但是其他浏览器,尤其是移动浏览器,不会显示该title属性。虽然屏幕阅读器可以设置成支持title属性,但是大部分屏幕阅读器不会把title属性的值作为默认设置进行读取,因此在提高可访问性方面不能依赖title属性。
 

title属性对于有些元素来说是必需的,例如<abbr>;对<abbr>来讲,其title属性的值就是其缩略语的扩展。除此之外的title属性一般是可选的。
然而title属性作为一个链接、图像、框架和多媒体元素的属性时还是有用的,它可以作为一种能根据用户交互显示一些零散隐藏信息的方法被派上用场。举例来说,我们可以使用CSS提取title属性的内容,然后通过把title的值作为通过::before或::after伪元素(pseudoelement)生成的内容的一部分,就可以为“工具提示”弹出式窗口创建生成的内容。

虽然title属性的值可用于渐进式增强(progressive enhancement)的漂亮花招(trick),但是因为这种花招的非可访问本质,我们不应该依赖于它来提供重要信息。而且因为用户能够访问到它,因此只能在title的内容是有用而且适合的时候才能使用title。如果你为了让你的统计可用而往title属性中添加内容,或者添加供你的JavaScript使用的代码,不要这样做!随着自定义数据属性(我们将在“data-自定义数据属性”小节介绍)的加入,rel属性和title属性巧妙的滥用已经没有必要(而且根本不适合)。

style
style属性可以让你指定某一元素只会出现一次的样式规则。该属性在快速原型设计的时候可以派上用场。除了原型设计之外,应该都不需要使用该属性,因为Web标准规定内容应该与呈现分离。

另外还要注意,当在像Safari和Chrome的Web Inspector、Firefox的Firebug、Opera的Dragaonfly、IE的F1这样的工具中使用检查器来查看代码时,使用JavaScript或者通过调试器接口添加的样式,将作为style属性的值内联出现。这是动态地生成的。浏览器可以这么做。但你最好不要!

lang
lang属性是两个全局的国际化属性之一(dir是另外一个)。一个Web页面的首要语言使用<html>元素的lang属性,通过HTTP头的Content-Language或http-equiv="language"属性进行设置。用于国际化或者定义内容的非默认语言区块时,lang属性详细说明了该元素属性值及其内容的语言种类,包括它所包含的那些没有给自己指定lang属性的所有元素。

lang属性使得搜索引擎能够按内容的语言种类编制索引,并允许屏幕阅读器使用国际发音规则。

lang属性使我们能够根据语言来样式化文本。<q>元素应该根据在lang属性中定义的语言来呈现恰当的引号,但这并没有被很好地支持。

dir
与lang属性经常一起使用,在书写阿拉伯语(Arabic)、希伯来语(Hebrew)或者其他自右向左的语言时,dir属性可以用于更改文本方向。dir属性的默认值是ltr(从左到右)。如果你的Web页面主要使用一门这种自右向左的语言,则在<html>元素中使用dir属性来设置主要的方向。

在页面正文里面,如果你有不是页面默认方向的内容,可以使用dir属性更改文本方向。虽然没有显式要求,但我还是建议无论何时你在一个元素上面包含了dir属性,同时也要包含title属性和lang属性。一般来讲,dir属性被用于把部分文本改成自右向左。包含lang属性是因为有必要通知搜索引擎、屏幕阅读器以及其他辅助技术该语言已经改变。title属性为你提供了一种方法,让你可以包含一份内容的翻译,使用你的网站的主要语言。这些属性提供了各种方法,不仅让你的网站内容对那些残障人士是可访问的,而且对你主要的“视觉障碍”用户Google也是可访问的!

注意,在HTML5中dir略有不同,现在已经引入了第三个值auto。这样dir属性可能的值就包括rtl、ltr和auto。

####2.1.4 成为HTML5核心的HTML 4属性
上面的属性都是之前版本(X)HTML的全局或核心属性,而且继续还是。还有两个在交互式元素上所支持的可访问性属性,现在HTML5中是全局属性。这些将在下面的小节中介绍。

tabindex
在以前的规范中,tabindex被包含在像链接和表单元素这样的交互式元素上,允许开发者们设置这些元素接收焦点的顺序。HTML5已经把tabindex的作用扩展至包括所有的HTML元素。

很多人使用鼠标浏览网站,点击链接和表单元素参与交互。其他人使用键盘浏览页面;点击Tab键就把焦点从一个可交互元素移动到了下一个。在非可触控手机上,用户使用导航或方向键盘(简称D-pad)上的4个方向来导航可聚焦元素。在智能机上,大多数用户通常会触控他们希望跟踪的链接或希望输入的表单元素。一旦他们已经在一个表单元素中完成输入,很多动态键盘都提供了“下一步”按钮供前进到下一个表单元素。默认情况下,只有链接和表单字段通过这种方式接收焦点。不管是通过导航键盘的向右按钮、下一步按钮还是Tab键,从当前元素到正在接收焦点的元素的顺序,就是源代码中表单元素的顺序,除非先天的顺序已经被使用tabindex属性篡改。

在HTML5中,tabindex属性的全局性质给所有元素添加了“可聚焦性”——而不仅是表单元素和链接。该属性把它的值看作是一个整数。当用户按下Tab键时,具有tabindex属性的元素将根据tabindex属性的数字值按顺序接收焦点——适合那些具有正值的tabindex。

不要使用带有正值的tabindex,除非你能够给页面上的每一个交互性元素都提供tabindex值,而且你还有很好的理由来重新排列这些顺序,并且你还要确保在该应用的整个“有生之年”你将都可以维护其正确的顺序。与此相反,我们应该使用正确的顺序来标记页面。Tab默认的顺序是与源代码中的顺序相同的。重新排列页面的Tab顺序可能会迷惑用户,从而可能导致非常糟糕的用户体验。最好以一种合理的顺序来布置页面,而且绝对不要使用tabindex属性。使用默认Tab(也就是源代码顺序)通常可以建立最佳用户体验。

所以,如果你不应该更改页面的顺序,那为什么tabindex成为一个全局变量了呢?tabindex属性成为全局性的目的是为了在所有元素上,包括非交互性上启用可编程的聚焦,一般是通过JavaScript或键盘焦点。

因为我们不希望真的更改源自页面源顺序的Tab或键盘焦点的顺序,所以tabindex的值只应该是0或−1。tabindex="-1"(任何负数值都起作用,不过−1是惯例)这样的值可被用于可编程聚焦;而tabindex="0"可被用于提供可访问性等方面的事由,假如你想要给一个链接或表单元素之外的元素提供键盘访问的同时又不更改页面的顺序的话。


你可能想知道,在通常不使用Tab进行导航的移动领域, tabindex能做什么。注意,你在填写一个表单元素的时候,有些设备上显示出来的键盘在顶部有一个“下一步”按钮。同样,就像在桌面环境上你希望通过JavaScript启用焦点一样,在手机上你可能也想这么做。并且,就像在桌面环境上一样,不是所有的用户都有一台指点设备(pointing device)[4]。许多视觉障碍人士在使用智能手机,尤其是在美国的iPhone。这样一来,tabindex就有助于可访问性。
accesskey
acesskey与tabindex类似,除了它不通过使用Tab按顺序导航到下一个具有更高tabindex值的元素进行页面导航,而是把焦点直接移动到触发访问键(activated access key)已经设置好的元素。可以把它看成是一个键盘快捷键。

acecsskey属性的值创建了键盘快捷键。例如,``<input acesskey="s"name= "search"type="text"/>`` 创建了一个accesskey等于s的搜索框。当用户按下字母“s”时,焦点就移到了搜索框。

accesskey属性的值是一个或多个使用一个空格分开的字符。通常情况下,它只是一个字符,但规范允许一个元素可以有不止一个键盘快捷键。accesskey值的语法与class属性类似,后者的属性的值是一个空格分开的标记(token)的有序集合。不过,这里的顺序是有意义的,第一个标记之后的标记被认为是为无法支持初始值的用户代理准备的回退方案。

虽然tabindex和acesskey最初都曾被视为可能解决可访问性问题的方案而备受推崇,但它们不是大家都盼望的可访问性解决方案。如前所述,tabindex由于修改页面原本正常的焦点顺序会产生糟糕的用户体验。类似地,accesskey可能会扰乱客户端浏览器设定的默认行为和快捷键。

迄今为止,我还未发现在智能手机上accesskey有什么用,但是因为我们正在学习HTML5,所以就把它包含进来了。accesskey在智能手机到来之前曾经很有用,那时在一个很小的旧手机上浏览网站是件苦差事。

####2.1.5 HTML5新内容:全局可访问性和交互性属性
HTML5包括若干新的属性,其中包括在本节介绍的一些新的全局属性。在接下来的两章,当我们讨论到一些元素的时候,将介绍这些元素特有的新的属性和值。

hidden
当含有hidden属性的时候,表示该元素尚未或者不再适用。支持的浏览器不会显示具有hidden属性,或在用户代理的样式表中定义了display:none;的元素。最好不要仅仅为了对用户隐藏元素而使用该属性,因为它是具有语义的:它表示围绕在该hidden属性的内容要么是已经过时的,要么是不再适用的。

contenteditable
contenteditable属性表示该元素是否是可编辑的。当包含该属性时,虽然用户对内容的更改并没有被保存,但的确修改了DOM,这样你就可以捕获这些更改并发回给服务器以保存。所有的桌面浏览器都支持contenteditable属性;随着Android 3.0和iOS 5.0开始提供支持,除了Opera Mini之外的所有移动设备也都支持该属性。

一旦设置了元素的contenteditable属性,触控设备上的动态键盘就应该弹开以启用编辑。

contextmenu
contextmenu属性使元素能够和一个提供了更多上下文相关信息的<menu>或<command>关联起来。该属性把你希望与之关联的<menu>元素的id的值作为它的值。除了Chrome试验性地提供支持之外,该属性尚未被其他任何浏览器所支持,因此本书并未涉及<menu>和<command>元素。

draggable
可拖动属性表示该元素是否是可拖动的。你也许已经注意到了,在大多数桌面浏览器上可以拖动图像,但无法放下。这就是目前默认的可拖动行为。为了使draggable属性变得确实有用,应该把它与JavaScript事件处理器结合起来使用,例如dragstart、drag、dragenter、dragleave、dragover、drop和dragend。除IE10之外的移动浏览器都不支持拖放,因此这些API没有包含在本书中。

dropzone
拖动一个元素是一回事,但是拖完之后你要做什么呢?HTML5提供了一个dropzone属性,可以指定在一个元素上可放下什么类型的内容。你可以使用move、copy和link属性值,分别移动、拷贝原来被拖动的内容或为其创建一个链接。因为移动浏览器没有对拖放提供很好的支持,所以我们在本书中不会对其进行进一步讨论。

spellcheck
spellcheck属性表示一个元素是否要进行拼写和语法检查。默认情况下,大多数  智能手机和平板电脑会在输入的时候自动更正(autocorrect)文本区域,但并不总是很  好——有几个拿“更正”寻开心的网站。虽然它们不支持spellcheck属性,但它们的确支持自动更正。

有趣的是,虽然iOS的默认行为是自动更正文本,但如果autocorrect属性被添加到一个文本类型输入,它实际上不检查拼写;它只会在没有包含这个属性的时候才自动更正。

ARIA无障碍属性
HTML5支持无障碍富Internet应用(ARIA)可访问性模块的role和aria-*属性。ARIA是一个单独的模块,而不是HTML5规范的一部分。使用实时区域(live region)、角色以及ARIA状态和属性,WAI-ARIA能够帮助提高动态更新内容和被劫持(hijacked)元素的易访问性。

当与富Internet应用程序交互时,使用屏幕阅读器访问的用户,可能正在让页面的一部分大声地朗读出来,同时页面的另一部分正被动态更新。ARIA实时区域可以帮助向用户表明页面其中的一部分 ——当前没有获得焦点的那部分 ——已经更新了。使用arialive的assertive、polite或默认的off值,ARIA为网站作者提供了一种方法,可以暂停屏幕阅读器,并通知用户页面的一部分已经被更新。相关的属性包括aria-atomic、aria-busy和aria-relevant。

ARIA的role属性可以在改变用途的元素上创建一个语义化结构。举例来说,其用途改变为一个grid、listbox、menu、menubar、tablist、toolbar、tree或treegrid的元素都可以认定为是这样的元素。使这看似非语义化的标记变得易于访问、可用,以及可以跟辅助技术互操作。虽然屏幕阅读器对新的HTML元素(参见第3章)的完全支持可能会使一些ARIA结构角色不再适用,但是现在就给页面添加role的article、application、banner、complementary、contentinfo、document、form、heading、main、navigation和search值可以帮助支持ARIA但尚不支持HTML5的屏幕阅读器。

关于角色需要注意的两个问题是:(1)一旦设置之后,role不应该被动态更改,因为这将会扰乱辅助技术;(2)角色优先于元素的默认语义。

除了role属性和它的很多值之外,ARIA 还为状态和属性提供了相关属性。状态属性有aria-disabled、aria-busy、aria-expanded和aria-hidden,有关属性的属性有aria-describedby、aria-haspopup和aria-labelled,这些属性在动态部件(widget)和改变用途的元素上提供了附加信息。最好的作法是针对任务使用语义最符合的现有元素,但是当你针对一个无法预期的用途(例如一个树状菜单)无论如何必须使用一个特定的元素时,应该使用ARIA。

data-自定义数据属性
在HTML5中,你可以创建自己的属性。虽然之前也可以创建自己的属性,但是标记不会通过验证。HTML5引入了自定义数据属性,这样的话,作为作者的你,可以自己定义这些属性的名称。

为了给用户交互提供数据,开发者们一直在编写无效的属性和滥用title和rel属性。仅仅使用data-前缀创建一个属性,代码就可以通过验证,而不是误用像rel和title这样的HTML4属性。

例如,在我们的CubeeDoo游戏中,我们需要维护每一张卡片的值和位置,这样当我们对它们进行比较时,我们就能够知道第一张翻开的卡片是否与第二张翻开的卡片一致,而且在我们暂停游戏以及离开屏幕时,还需要和localStorage结合来维护状态。我们可以在JavaScript中使用数组的方式来记住每一张卡片。相反地,我们在代码中创建了data- position和data-value属性,可以为每一局新游戏的设定动态地更新data-的值:
<div id="board" class="level1">
    <div data-value="0" data-position="1">
        <div class="face"></div>
        <div class="back"></div>
    </div>
    <div data-value="0" data-position="2">
        <div class="face"></div>
        <div class="back"></div>
    </div>
    <div data-value="0" data-position="3">
        <div class="face"></div>
        <div class="back"></div>
    </div>
    <div data-value="0" data-position="4">
        <div class="face"></div>
        <div class="back"></div>
    </div>
    ...
    <div data-value="0" data-position="24">
        <div class="face"></div>
        <div class="back"></div>
    </div>

网友评论

登录后评论
0/500
评论
异步社区
+ 关注