HTML5-权威指南-三-

110 阅读1小时+

HTML5 权威指南(三)

原文:The Definitive Guide to HTML5

协议:CC BY-NC-SA 4.0

十、创建小节

在这一章中,我将向您展示用来表示内容中各部分的元素——实际上,就是如何将内容分开,使每个主题或概念与其他主题或概念隔离开来。本章中的许多元素都是新的,它们构成了将元素的含义从它们的表现中分离出来的重要基础。不幸的是,这意味着这些元素很难演示,因为它们对内容几乎没有视觉影响。为此,我在本章的许多示例中添加了一些 CSS 样式,以强调这些元素带来的结构和变化。

在这一章中,我不解释 CSS 样式的含义。第四章包含了 CSS 关键特性的提示,从第十六章开始描述了 CSS 的各个属性。表 10-1 对本章进行了总结。

Image

添加基本标题

h1元素代表一个标题。HTML 定义了标题元素的层次结构,其中h1是最高等级的。其他标题元素是h2h3,一直到h6。表 10-2 总结了h1h6要素。

Image

相同等级的标题通常用于分解内容,以便每个主题都在各自的部分中。降序排列的标题通常用于表示同一主题的不同方面。这些元素的另一个好处是,它们创建了一个文档大纲,用户只需通过查看标题就可以对文档的整体性质和结构有所了解,并通过跟踪标题层次结构更快地导航到感兴趣的区域。清单 10-1 显示了使用中的h1h3元素。

清单 10-1。使用 h1–H3 元素

`

             Example                                                  **

Fruits I like

**             I like apples and oranges.             **

Additional fruits

**             I also like bananas, mangoes, cherries, apricots, plums, peaches and grapes.             **

More information

**             You can see other fruits I like here.

            

Activities I like

            

I like to swim, cycle and run. I am in training for my first triathlon,             but it is hard work.

            

Kinds of Triathlon

            There are different kinds of triathlon - sprint, Olympic and so on.             

The kind of triathlon I am aiming for

            I am aiming for Olympic, which consists of the following:             
                    
  1. 1.5km swim
  2.                 
  3. 40km cycle
  4.                 
  5. 10km run
  6.             
    

`

我在清单中只显示了h1h2h3标题,因为很少有内容值得进一步深入。例外往往是非常技术性和精确的内容,如合同和规范。大多数内容最多需要两三级标题。举个例子,我在我的新书中使用了三个层次的标题。虽然 Apress 模板定义了五个级别的标题,但是如果我使用第四和第五个级别,文字编辑会感到不舒服。

你可以在图 10-1 中看到浏览器如何显示列表中的h1h2h3元素。

Image

图 10-1。使用默认的样式约定显示 h1、h2 和 h3 元素

如图所示,每一级标题都有不同的样式约定。表 10-3 显示了每个标题元素的样式约定。

Image

Image

您不必考虑h1h6元素的层次结构,但是如果您偏离了它,就会有使用户困惑的风险。分层标题如此普遍,以至于用户对它们的工作方式有一个固定的预期。

隐藏副标题

元素允许你在不影响 HTML 文档轮廓的情况下,将多个 header 元素作为一个单独的项目来处理。表 10-4 总结了hgroup要素。

Image

hgroup解决的最常见的问题就是字幕。假设我想在文档中创建一个标题为“我喜欢的水果”的部分,副标题为“我是如何爱上柑橘的”。我可以使用h1h2元素,如清单 10-2 中的所示。

清单 10-2。使用 h1 和 h2 元素创建一个带有副标题的标题

`

             Example                                                  **

Fruits I Like

**             **

How I Learned to Love Citrus

**             I like apples and oranges.             

Additional fruits

            I also like bananas, mangoes, cherries, apricots, plums, peaches and grapes.             

More information

            You can see other fruits I like here.

            

Activities I Like

            

I like to swim, cycle and run. I am in training for my first triathlon,             but it is hard work.

            

Kinds of Triathlon

            There are different kinds of triathlon - sprint, Olympic and so on.             

The kind of triathlon I am aiming for

            I am aiming for Olympic, which consists of the following:             
                    
  1. 1.5km swim
  2.                 
  3. 40km cycle
  4.                 
  5. 10km run
  6.             
    

`

这里的问题是,您无法区分作为副标题的h2元素和作为较低级标题的h2元素。如果您编写了一个脚本,遍历您的文档,根据h1h6元素构建一个大纲,您将得到一个扭曲的结果,如下所示:

Fruits I Like     How I Learned to Love Citrus     Additional fruits         More information Activities I Like     Kinds of Triathlon         The kind of triathlon I am aiming for

这给人的感觉是How I Learned to Love Citrus是一个章节标题,而不是副标题。您可以使用hgroup元素来解决这个问题,如清单 10-3 所示。

清单 10-3。使用 hgroup 元素

`

             Example                                    ****             **h1, h2, h3 { background: grey; color: white; }**             hgroup > h1 { margin-bottom: 0px;}

            hgroup > h2 { background: grey; color: white; font-size: 1em;                           margin-top: 0px; }                               

                

Fruits I Like

                

How I Learned to Love Citrus

                         I like apples and oranges.             

Additional fruits

            I also like bananas, mangoes, cherries, apricots, plums, peaches and grapes.             

More information

            You can see other fruits I like here.

            

Activities I like

            

I like to swim, cycle and run. I am in training for my first triathlon,             but it is hard work.

            

Kinds of Triathlon

            There are different kinds of triathlon - sprint, Olympic and so on.             

The kind of triathlon I am aiming for

            I am aiming for Olympic, which consists of the following:             
                    
  1. 1.5km swim
  2.                 
  3. 40km cycle
  4.                 
  5. 10km run
  6.             
    

`

一个hgroup元素在h1h6层次结构中的位置由hgroup中的第一个标题元素子元素决定。例如,清单中的hgroup相当于一个h1元素,因为它是第一个子元素。只有第一个h1h6元素包含在文档的大纲中,它给出了这样一个大纲:

Fruits I Like     Additional fruits         More information Activities I Like     Kinds of Triathlon         The kind of triathlon I am aiming for

subtitle h2元素不再令人困惑——hgroup元素告诉您忽略它。你必须处理的第二个问题是使字幕在视觉上与常规的h2元素有所区别。你可以看到我在清单中应用了一些简单的样式,其效果可以在图 10-2 中看到。你可以在第十七章的中了解列表中的 CSS 选择器是如何工作的。

Image

图 10-2。使 h 组中元素之间的关系直观明了

我不建议您采用这种简单的样式,但是您可以看到,您可以通过应用样式来消除标题元素的一些边距,并使用共同的背景色将元素放在一起,从而使hgroup元素中的元素之间的关系在视觉上更加清晰。

创建章节

section元素是 HTML5 的新元素,顾名思义,它表示文档的一部分。当你使用标题元素时,你创建了隐含的部分,但是这个元素允许你显式地显示它们,也允许你将文档的部分从h1h6元素中分离出来。对于何时使用section元素没有严格的规则,但是根据经验,section元素应该用于包含文档大纲或目录中列出的内容。Section 元素通常包含一段或多段内容和一个标题,尽管标题是可选的。表 10-5 总结了section元素。

清单 10-4 展示了使用中的section元素。

清单 10-4。使用截面元素

`

             Example                                                 h1, h2, h3 { background: grey; color: white; }             hgroup > h1 { margin-bottom: 0px; }             hgroup > h2 { background: grey; color: white; font-size: 1em;                          margin-top: 0px;}                            ****                              

Fruits I Like

                

How I Learned to Love Citrus

                         I like apples and oranges.             ****                 

Additional fruits

                I also like bananas, mangoes, cherries, apricots, plums,                 peaches and grapes.                 ****                     

More information

                    You can see other fruits I like here.                 ****             ****         ****

        

Activities I like

        

I like to swim, cycle and run. I am in training for my first triathlon,                     but it is hard work.

        

Kinds of Triathlon

        There are different kinds of triathlon - sprint, Olympic and so on.         

The kind of triathlon I am aiming for

        I am aiming for Olympic, which consists of the following:         
                
  1. 1.5km swim
  2.             
  3. 40km cycle
  4.             
  5. 10km run
  6.         
    

`

我在这个清单中定义了三个section元素,其中一个嵌套在另一个中。注意,每个标题元素都是一个h1。当使用section元素时,浏览器负责计算出标题元素的层次结构,使您不必确定和维护h1h6元素的适当顺序——至少原则上如此。实际的浏览器实现略有不同。Google Chrome、Internet Explorer 9 (IE9)和 Firefox 能够导出隐含的层次结构,并计算出每个h1元素的相对排名,如图图 10-3 所示。

Image

图 10-3。在 Chrome 中使用带有嵌套 h1 元素的 section 元素

这很好,但是如果您很细心,您会注意到用于显示内容为Fruits I Likeh1元素的字体比用于同一级别的另一个h1元素——Activities I like元素的字体要小。这是因为一些浏览器(包括 Chrome 和 Firefox)对出现在sectionarticleasidenav元素中的h1(以及h2h6)元素应用了不同的样式。(后三种将在本章后面介绍。)这个新样式与h2元素的样式约定相同。IE9 不应用特殊样式,如图图 10-4 所示。这才是正确的行为。

Image

图 10-4。在 Internet Explorer 中使用带有 h1 元素的 section 元素

此外,并不是所有的浏览器都支持创建相同类型的嵌套标题元素的隐含层次结构。你可以在图 10-5 中看到 Opera 是如何处理这些元素的。Safari 以同样的方式处理这些元素——忽略由section元素创建的层次结构实现。

Image

图 10-5。在 Opera 中使用带有 h1 元素的 section 元素

你可以通过创建自己的风格来克服 Chrome 和 Firefox 应用的特殊风格,这些风格优先于浏览器定义的风格(正如我在第四章中解释的那样)。Internet Explorer 会做您所期望的事情。但是你对 Opera 和 Safari 无能为力——在浏览器实现变得更加一致之前,这个方便的功能应该谨慎使用。

添加页眉和页脚

header元素表示一个节的标题。它可以包含您希望表示为标题的任何内容,包括刊头或徽标。就其他元素而言,header元素通常包含一个h1h6元素或一个hgroup元素,它还可以包含该部分的导航元素。参见nav元素(在即将到来的“添加导航块”一节中讨论)了解导航的细节。表 10-6 总结了header元素。

footer元素是对header的补充,代表一个部分的页脚。一个footer通常包含一个章节的摘要信息,可以包括作者的详细信息、权利信息、相关内容的链接、徽标和免责声明。表 10-7 总结了footer要素。

Image

Image

您可以在清单 10-5 中看到headerfooter元素。

清单 10-5。使用页眉和页脚元素

`

             Example                                                 h1, h2, h3 { background: grey; color: white; }             hgroup > h1 { margin-bottom: 0; margin-top: 0}             hgroup > h2 { background: grey; color: white; font-size: 1em;                         margin-top: 0px; margin-bottom: 2px}             body > header  *, footer > * { background:transparent; color:black;}             body > section, body > section > section,             body > section > section > section {margin-left: 10px;}

            body > header, body > footer {                 border: medium solid black; padding-left: 5px; margin: 10px 0 10px 0;             }                            

                             

Things I like

                

by Adam Freeman

                                                                                 

Fruits I Like

                    

How I Learned to Love Citrus

                                          I like apples and oranges.                              

Additional fruits

                I also like bananas, mangoes, cherries, apricots, plums,                 peaches and grapes.                                          

More information

                    You can see other fruits I like here.                                       

        

                             

Activities I like

                                          

I like to swim, cycle and run. I am in training for my first                 triathlon, but it is hard work.

                

Kinds of Triathlon

                There are different kinds of triathlon - sprint, Olympic and so on.                                      

The kind of triathlon I am aiming for

                    I am aiming for Olympic, which consists of the following:                     
                            
  1. 1.5km swim
  2.                         
  3. 40km cycle
  4.                         
  5. 10km run
  6.                     
                                                            ©2011, Adam Freeman. Visit Apress              

`

在这个例子中,我定义了三个header元素。当一个标题是body元素的子元素时,它被假定为整个文档的header(但是要小心——这与head元素不同,我在第七章中描述了后者)。当header元素是一个节的一部分时(使用section元素隐式或显式定义),它是该节的header。我在文档中添加了一些样式,以便更容易看到各个部分和标题之间的层次关系。你可以在图 10-6 中看到这一点。

注意字体的相对大小。这大概就是为什么 Google Chrome 和 Firefox 在section元素中重新定义了h1h6元素。这是为了区分顶级h1头和那些嵌套在节中的头。这并不能为风格的无端重新定义开脱,但它确实把它放在了上下文中。

Image

图 10-6。使用标题元素

你可以在图 10-7 中看到footer的效果。

Image

图 10-7。添加页脚元素

添加导航块

nav元素表示包含到其他页面或同一页面其他部分的链接的文档部分。显然,并不是所有的超链接都必须在一个nav元素中。这个元素的目的是标识文档的主要导航部分。表 10-8 描述了nav元素。

Image

Image

清单 10-6 显示了nav元素的用法。

清单 10-6。使用导航元素

`

             Example                                                 h1, h2, h3 { background: grey; color: white; }             hgroup > h1 { margin-bottom: 0; margin-top: 0}             hgroup > h2 { background: grey; color: white; font-size: 1em;                         margin-top: 0px; margin-bottom: 2px}             body > header  *, body > footer * { background:transparent; color:black;}             body > section, body > section > section,             body > section > section > section {margin-left: 10px;}

            body > header, body > footer {                 border: medium solid black; padding-left: 5px; margin: 10px 0 10px 0;             }

            body > nav { text-align: center; padding: 2px; border : dashed thin black;}             body > nav > a {padding: 2px; color: black}                            

                             

Things I like

                

by Adam Freeman

                                          

Contents

                                                                                                  

Fruits I Like

                    

How I Learned to Love Citrus

                                          I like apples and oranges.                              

Additional fruits

                I also like bananas, mangoes, cherries, apricots, plums,                 peaches and grapes.                                          

More information

                    You can see other fruits I like here.                                       

        

                             

Activities I like

                                          

I like to swim, cycle and run. I am in training for my first                 triathlon, but it is hard work.

                

Kinds of Triathlon

                There are different kinds of triathlon - sprint, Olympic and so on.                                      

The kind of triathlon I am aiming for

                    I am aiming for Olympic, which consists of the following:                     
                            
  1. 1.5km swim
  2.                         
  3. 40km cycle
  4.                         
  5. 10km run
  6.                     
                                                            More Information:             Learn More About Fruit             Learn More About Triathlons                               ©2011, Adam Freeman. Visit Apress              

`

我在文档中添加了几个nav元素,以体现这个元素的灵活性。第一个nav元素为用户提供文档内的导航。我使用了ullia元素来创建一组层次化的相对超链接。你可以在图 10-8 中看到浏览器是如何显示的。

Image

图 10-8。使用 nav 元素创建内容导航部分

我将这个nav元素放在文档的主header元素中。这不是强制性的,但我喜欢这样做,以表明这是主要的nav元素。请注意,我将h1元素与其他内容混合在一起。nav元素可以包含任何流内容,而不仅仅是超链接。我在文档的末尾添加了第二个nav元素,为用户提供一些链接来获取更多信息。你可以在图 10-9 中看到浏览器是如何渲染的。

Image

图 10-9。使用导航元素提供外部导航

nav元素的两个实例中,我在文档中给style元素添加了样式,以使添加的内容在视觉上与众不同。nav元素的样式约定没有明确表示nav元素的内容。

使用文章

article元素表示 HTML 文档中一段独立的内容,原则上可以独立于页面的其余部分进行分发或使用(比如通过 RSS 提要)。这并不是说你来独立发布它,只是说独立性是何时使用这个元素的指导。好的例子包括一篇新文章和一个博客条目。表 10-9 总结了article元素。

Image

清单 10-7 显示了使用中的article元素。

清单 10-7。使用文章元素

`

             Example                                                 h1, h2, h3, article > footer { background: grey; color: white; }             hgroup > h1 { margin-bottom: 0; margin-top: 0}             hgroup > h2 { background: grey; color: white; font-size: 1em;                         margin-top: 0px; margin-bottom: 2px}             body > header  *, body > footer * { background:transparent; color:black;}

            article {border: thin black solid; padding: 10px; margin-bottom: 5px}             article > footer {padding:5px; margin: 5px; text-align: center}             article > footer > nav > a {color: white}

            body > article > section,             body > article > section > section {margin-left: 10px;}

            body > header, body > footer {                 border: medium solid black; padding-left: 5px; margin: 10px 0 10px 0;             }             body > nav { text-align: center; padding: 2px; border : dashed thin black;}             body > nav > a {padding: 2px; color: black}                            

                             

Things I like

                

by Adam Freeman

                                          

Contents

                                      

        

                                                  

Fruits I Like

                    

How I Learned to Love Citrus

                                          I like apples and oranges.                              

Additional fruits

                I also like bananas, mangoes, cherries, apricots, plums,                 peaches and grapes.                                          

More information

                    You can see other fruits I like here                                                                                 More Information:                     Learn More About Fruit                                       

        

                                                  

Activities I like

                    

It hurts, but I keep doing it

                                                           

I like to swim, cycle and run. I am in training for my first                 triathlon, but it is hard work.

                

Kinds of Triathlon

                There are different kinds of triathlon - sprint, Olympic and so on.                                      

The kind of triathlon I am aiming for

                    I am aiming for Olympic, which consists of the following:                     
                            
  1. 1.5km swim
  2.                         
  3. 40km cycle
  4.                         
  5. 10km run
  6.                     
                                                                                More Information:                     Learn More About Triathlons                                       

        

            ©2011, Adam Freeman. Visit Apress              

`

在这个例子中,我重新组织了我的文档,使其更符合博客的一般风格,尽管它可能不是最有趣的博客。文件的主要部分分为三个部分。第一个是header,它超越了单个条目,为文档的其余部分提供了一个定位点。第二部分是footer,它平衡标题,并为用户提供一些适用于其余内容的基本信息。新增加的是第三部分:article元素。在这个例子中,每篇文章都描述了我喜欢的一种事物。这符合独立性测试,因为我喜欢的东西的每个描述都是独立的,可以独立发布,同时仍然有某种意义。我再次添加了一些样式来突出元素的截面效果,你可以在图 10-10 中看到。

Image

图 10-10。应用文章元素

article元素可以像其他新的语义元素一样灵活应用。例如,您可以嵌套article元素来指示原始文章以及您收到的每个更新或评论。和其他一些元素一样,article的价值是与上下文相关的——在一种内容中增加有意义的结构可能不会在另一种内容中增加价值。需要判断(和一致性)。

创建侧边栏

aside元素表示与周围元素关系不大的内容。这类似于书籍或杂志中的侧边栏。内容与页面的其余部分、articlesection有关,但它不是主流的一部分。它可以是一些额外的背景,一组相关文章的链接,等等。表 10-10 总结了aside要素。

清单 10-8 显示了使用中的aside元素。我给其中一篇文章添加了旁白,并添加了样式,使它看起来像一个简单的杂志风格的侧边栏。

清单 10-8。添加和样式化辅助设备

`

             Example                                                 h1, h2, h3, article > footer { background: grey; color: white; }             hgroup > h1 { margin-bottom: 0; margin-top: 0}             hgroup > h2 { background: grey; color: white; font-size: 1em;                         margin-top: 0px; margin-bottom: 2px}             body > header  *, body > footer * { background:transparent; color:black;}

            article {border: thin black solid; padding: 10px; margin-bottom: 5px}             article > footer {padding:5px; margin: 5px; text-align: center}             article > footer > nav > a {color: white}

            body > article > section,             body > article > section > section {margin-left: 10px;}

            body > header, body > footer {                 border: medium solid black; padding-left: 5px; margin: 10px 0 10px 0;             }             body > nav { text-align: center; padding: 2px; border : dashed thin black;}             body > nav > a {padding: 2px; color: black}

            aside { width:40%; background:white; float:right; border: thick solid black;                 margin-left: 5px;}             aside > section { padding: 5px;}             aside > h1 {background: white; color: black; text-align:center}                            

                             

Things I like

                

by Adam Freeman

                                          

Contents

                                      

        

                                                  

Fruits I Like

                    

How I Learned to Love Citrus

                                                           

Why Fruit is Healthy

                                         Here are three reasons why everyone should eat more fruit:                     
                            
  1. Fruit contains lots of vitamins
  2.                         
  3. Fruit is a source of fibre
  4.                         
  5. Fruit contains few calories
  6.                     
                                          I like apples and oranges.                                  

Additional fruits

                I also like bananas, mangoes, cherries, apricots, plums,                 peaches and grapes.                                          

More information

                    You can see other fruits I like here                                                                                 More Information:                     Learn More About Fruit                                                                                                   

Activities I like

                    

It hurts, but I keep doing it

                                                           

I like to swim, cycle and run. I am in training for my first                 triathlon, but it is hard work.

                

Kinds of Triathlon

                There are different kinds of triathlon - sprint, Olympic and so on.                                      

The kind of triathlon I am aiming for

                    I am aiming for Olympic, which consists of the following:                     
                            
  1. 1.5km swim
  2.                         
  3. 40km cycle
  4.                         
  5. 10km run
  6.                     
                                                                                More Information:                     Learn More About Triathlons                                                             ©2011, Adam Freeman. Visit Apress              

`

你可以在图 10-11 中看到aside元素和附加样式的效果。我向图中所示的文档添加了一些填充文本,以使内容的流动更加明显。

Image

图 10-11。应用和设计侧边元素

提供联系信息

address元素用于表示文档或article元素的联系信息。表 10-11 总结了address元素。

Image

Image

address元素是article元素的后代时,它被假定为那个article提供联系信息。否则,当一个address元素是一个body元素的子元素时(并且在bodyaddress元素之间没有article元素),则假定address为整个文档提供联系信息。

元素不能用来表示不是文档或文章的联系信息的地址。例如,您不能使用该元素在文档内容中表示客户或用户的地址。清单 10-9 显示了使用中的address元素。

清单 10-9。使用地址元素

`...

                          

Things I like

            

by Adam Freeman

                 ****             **Questions and comments? Email me**         ****                      

Contents

                          

    

                      ...`

我将address元素添加到文档的标题中。在这种情况下,我提供了一个用户/读者联系我的电子邮件地址。您可以在图 10-12 中看到添加内容。

Image

图 10-12。添加地址元素

创建详细信息部分

details元素创建了文档的一个部分,用户可以展开它来获得关于主题的更多细节。表 10-12 总结了details要素。

Image

details元素通常包含一个summary元素,它为细节部分创建一个标签或标题。表 10-13 描述了summary元素。

您可以看到在清单 10-10 中使用的detailssummary元素。

清单 10-10。使用概要和细节元素

`

             Example                                                 h1, h2, h3, article > footer { background: grey; color: white; }             hgroup > h1 { margin-bottom: 0; margin-top: 0}             hgroup > h2 { background: grey; color: white; font-size: 1em;                         margin-top: 0px; margin-bottom: 2px}             body > header  *, body > footer * { background:transparent; color:black;}             body > article > section,             body > article > section > section {margin-left: 10px;}             body > header {                 border: medium solid black; padding-left: 5px; margin: 10px 0 10px 0;             }             article {border: thin black solid; padding: 10px; margin-bottom: 5px}                 details {border: solid thin black; padding: 5px}             **details > summary { font-weight: bold}**                                                          

Things I like

                

by Adam Freeman

                                                                                 

Activities I like

                    

It hurts, but I keep doing it

                                                           

I like to swim, cycle and run. I am in training for my first                 triathlon, but it is hard work.

                **
**                     **Kinds of Triathlon**                     **There are different kinds of triathlon - sprint, Olympic and so on.**                     **I am aiming for Olympic, which consists of the following:**                     **
    **                         **
  1. 1.5km swim
  2. **                         **
  3. 40km cycle
  4. **                         **
  5. 10km run
  6. **                     **
**                 **
**                            `

你可以在图 10-13 中看到浏览器是如何显示这些元素的。并非所有的浏览器都支持details元素。比如 IE9 就有困难。

Image

图 10-13。使用详细信息和摘要属性

如图所示,浏览器提供了一个界面控件,当它被激活时,会打开并显示details元素的内容。当details元素关闭时,只有summary元素的内容可见。要在页面首次显示时打开details元素,请应用open属性。

总结

在本章中,我向您介绍了用于在文档中创建节和隔离不相关内容的元素。这些元素中的大部分都是 HTML5 的新内容。虽然您不必使用它们来创建兼容的 HTML5 文档,但是这些新元素是为 HTML 带来语义的主要增强之一。

十一、表格元素

在这一章中,我将向你展示可以用来创建表格的 HTML 元素。表格的主要用途是在网格中显示二维数据,但在 HTML 的早期版本中,使用表格来控制页面内容的布局变得很常见。在 HTML5 中,这不再被允许,必须使用新的 CSS 表格特性(在第二十一章中描述)。表 11-1 对本章进行了总结。

Image

创建基本表格

每个表必须包含三个元素:tabletrtd。还有其他的元素——我将在本章的后面解释它们——但是这是你必须开始的三个元素。第一个是table,它是 HTML 中表格内容支持的核心,表示 HTML 文档中的一个表格。表 11-2 总结了table元素。

Image

下一个核心table元素是tr,它表示一个表格行。HTML 表格是面向行的,而不是面向列的,你必须分别表示每一行。表 11-3 总结了tr要素。

Image

Image

我们的三个核心元素中的最后一个是td,它表示一个表格单元格。表 11-4 总结了td要素。

Image

定义了这三个元素后,您可以将它们组合起来创建表格,如清单 11-1 所示。

清单 11-1。使用 table、tr 和 td 元素创建一个表格

`

             Example                                              ****             ****                 ****                 ****                 ****             ****             ****                 ****                 ****                 ****             ****         **
ApplesGreenMedium
OrangesOrangeLarge
**      `

在这个例子中,我定义了一个有两行的table元素(由两个tr元素表示)。每行有三列,每列由一个td元素表示。td元素可以包含任何流内容,但是在这个例子中我坚持使用简单的文本。您可以在图 11-1 中看到默认样式惯例是如何应用于显示表格的。

Image

图 11-1。显示一个简单的表格

这是一个非常简单的表格,但是你可以看到它的基本结构。浏览器负责调整行和列的大小以维护表格。例如,看看当我添加一些更长的内容时会发生什么,如清单 11-2 中的所示。

清单 11-2。添加一些更长的单元格内容

`

             Example                                                                                                                                                                                                                     ****                 ****                 ****                 ****             ****         
ApplesGreenMedium
OrangesOrangeLarge
PomegranateA kind of greeny-redVaries from medium to large
     `

每个新添加的td元素的内容都比前两行长。你可以在图 11-2 中看到浏览器如何调整其他单元格的大小,使它们大小相同。

Image

图 11-2。调整单元格大小以容纳更长的内容

table元素最好的特性之一是你不必担心大小的问题。浏览器确保最长的内容有足够的列宽,最高的单元格有足够的行高。

添加表头单元格

th元素表示一个标题单元格,允许我们区分数据和数据的描述。表 11-5 总结了th要素。

Image

您可以看到我是如何将th元素添加到清单 11-3 的表格中,以便为包含在td元素中的数据值提供一些上下文。

清单 11-3。向表格添加标题单元格

`

             Example                                                           ****                 ****                 ****             ****                              ****                                                            ****                                                            ****                                                        
RankNameColorSize
Favorite:ApplesGreenMedium
2nd Favorite:OrangesOrangeLarge
3rd Favorite:PomegranateA kind of greeny-redVaries from medium to large
     `

您可以看到,我能够将thtd元素混合在一行中,并创建一个仅包含th元素的行。你可以在图 11-3 中看到浏览器是如何渲染这些的。

Image

图 11-3。向表格添加标题单元格

向表格添加结构

你有一个基本的表,但你设法给自己制造了一个问题。当您设计表格样式时,您会发现很难区分th元素是在它们自己的行上,还是与数据混合在一起。这不是不可能的,只是需要密切关注..清单 11-4 展示了你如何做到这一点。

清单 11-4。区分表格中的元素

`

             Example                                    ****             **tr > th { text-align:left; background:grey; color:white}**             **tr > th:only-of-type {text-align:right; background: lightgrey; color:grey}**         ****                                                                                                                                                                                                                         
RankNameColorSize
Favorite:ApplesGreenMedium
2nd Favorite:OrangesOrangeLarge
3rd Favorite:PomegranateA kind of greeny-redVaries from medium to large
     `

在这个例子中,我创建了一个匹配所有th元素的选择器和一个仅匹配那些th元素的样式,这些元素是tr元素中该类型的唯一子元素。你可以在图 11-4 中看到样式的效果。

Image

图 11-4。添加匹配表格中第行的样式

这是一个非常可行的方法,但是缺乏灵活性。如果我向表的行添加额外的th元素,我的第二个选择器将不再工作。我真的不想每次换表的时候都要调整选择器。

为了灵活地解决这个问题,您可以使用theadtbodytfoot元素。这些元素允许您向表中添加结构,这种结构的主要好处是它使处理表的不同部分变得更简单,尤其是在使用 CSS 选择器时。

表示标题和表体

tbody元素表示构成表格主体的一组行——与标题行和脚注行相反,标题行和脚注行用theadtfoot元素表示,我们很快就会看到。表 11-6 总结了tbody要素。

Image

顺便说一下,大多数浏览器在处理table元素时会自动插入tbody元素,即使它没有在文档中指定。这意味着假设表格布局与编写的一样的 CSS 选择器可能会失败。例如,table > tr这样的选择器无法工作,因为浏览器在tabletr元素之间插入了一个tbody元素。为了解决这个问题,你必须使用一个选择器,比如table > tbody > trtable tr(没有>字符),甚至仅仅是tbody > tr

thead元素定义了一行或多行,它们是table元素的列标签。表 11-7 总结了thead元素。

如果没有thead元素,所有的tr元素都被认为属于表格的主体。清单 11-5 显示了示例表中添加的theadtbody元素,以及您可以使用的更加灵活的 CSS 选择器。

清单 11-5。将 ad 和 tbody 元素添加到表中

`

             Example                                                 **thead th { text-align:left; background:grey; color:white}**             **tbody th { text-align:right; background: lightgrey; color:grey}**                                         ****                                                                    ****             ****                                                                                                                                                                                                       ****         
RankNameColorSize
Favorite:ApplesGreenMedium
2nd Favorite:OrangesOrangeLarge
3rd Favorite:PomegranateA kind of greeny-redVaries from medium to large
     `

这看起来没什么大不了的,但是您添加到表格中的结构使得处理不同种类的单元格更加容易,并且在您修改表格的设计时不太可能失败。

添加页脚

tfoot元素表示构成表格页脚的行块。表 11-8 总结了tfoot要素。

Image

清单 11-6 展示了如何使用tfoot元素为table元素创建一个页脚。在 HTML5 之前,tfoot元素必须出现在tbody元素之前(如果省略了tbody,则出现在第一个tr元素之前)。在 HTML5 中,您可以将tfooter元素放在tbody或最后一个tr元素之后,这与浏览器显示table的方式更加一致。在清单 11-6 中,我在第一个位置显示了tfoot元素——两者都是可以接受的。我的感觉是,当使用模板以编程方式生成 HTML 时,above-the- tbody方法通常更有帮助,而在手动编写 HTML 时,below-the- tbody方法感觉更自然。

清单 11-6。使用 tfoot 元素

`

             Example                                                 thead th, **tfoot th** { text-align:left; background:grey; color:white}             tbody th { text-align:right; background: lightgrey; color:grey}                                                                                                                          ****                 ****                     ****                 ****                                                                                                                                                                                                                                          
RankNameColorSize
RankNameColorSize
Favorite:ApplesGreenMedium
2nd Favorite:OrangesOrangeLarge
3rd Favorite:PomegranateA kind of greeny-redVaries from medium to large
     `

我将页眉中的一组行复制到页脚中。在这一章的后面,我们会回来让页脚变得更有趣。我还为其中一个样式添加了第二个选择器,这样theadtfoot元素中的th和元素的样式也是相同的。您可以看到增加了如图图 11-5 所示的页脚。

Image

图 11-5。向表格添加页脚

创建不规则表格

大多数表格都是简单的网格,每个单元格在网格中占据一个位置。但是,为了表示更复杂的数据,有时需要创建不规则的表格,其中单元格分布在多行和多列中。您可以使用tdth元素的colspanrowspan属性创建这样的表。清单 11-7 展示了如何使用这些属性来创建一个不规则的表格。

清单 11-7。创建不规则表格

`

             Example                                                 thead th, tfoot th { text-align:left; background:grey; color:white}             tbody th { text-align:right; background: lightgrey; color:grey}             **[colspan], [rowspan] {font-weight:bold; border: medium solid black}**             **thead [colspan], tfoot [colspan] {text-align:center; }**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
RankNameColorSize & Votes
Favorite:ApplesGreenMedium500
2nd Favorite:OrangesOrangeLarge450
3rd Favorite:Pomegranate                         Pomegranates and cherries can both come in a range of colors                         and sizes.                     203
Joint 4th:Cherries75
PineappleBrownVery Large
© 2011 Adam Freeman Fruit Data Enterprises
     `

如果希望一个单元格跨越多行,可以使用rowspan属性。分配给该属性的值是要跨越的行数。类似地,如果希望一个单元格跨越多列,可以使用colspan属性。

Image 提示赋给rowspancolspan的值必须是整数。有些浏览器会将值 100%理解为表中的所有行或列,但这不是 HTML5 标准的一部分,也没有得到一致的实现。

我在示例文档中添加了一些额外的样式来突出显示跨越多行或多列的单元格,如图 11-6 所示。受影响的单元格以粗边框显示。

Image

图 11-6。跨越多行多列

您将colspanrowspan属性应用于您想要覆盖的网格部分的最上面和最左边的单元格。您忽略了通常会包含的tdtr元素。作为一个例子,考虑在清单 11-8 中显示的简单表格。

清单 11-8。一张简单的桌子

`

             Example                                                 td {border: thin solid black; padding: 5px; font-size:x-large};                                                                                                                                                                                                                                                                            
123
456
789
     `

本例中的表格是一个 3x3 的规则网格,如图图 11-7 所示。

Image

图 11-7。一个规则的网格

如果希望中间一列中的一个单元格跨越所有三行,可以将rowspan属性应用于单元格 2,它是您想要覆盖的网格区域的最上面(也是最左边,但在本例中这无关紧要)的单元格。您还必须删除扩展单元格将覆盖的单元格元素,在本例中是单元格 5 和 8。您可以在清单 11-9 中看到这些变化。

清单 11-9。扩展单元格以覆盖多行

`

             Example                                                 td {border: thin solid black; padding: 5px; font-size:x-large};                                                                           ****                                                                                                                                                               
123
46
79
     `

你可以在图 11-8 中看到这些变化的结果。

Image

图 11-8。扩展单元格以覆盖三行

浏览器负责确定您定义的其他单元格应该如何适应扩展的单元格。

Image 注意注意不要让两个单元格扩展到同一个区域而产生重叠的单元格。table 元素的目的是表示表格数据。使用重叠单元格的唯一原因是让表格元素布局其他元素,这应该使用 CSS 表格功能来完成(在第二十一章的中描述)。

将表头与单元格关联

tdth元素定义了headers属性,该属性可用于使表格更容易被屏幕阅读器和其他辅助技术处理。headers属性的值是一个或多个th单元格的 ID 属性值。清单 11-10 显示了如何使用这个属性。

清单 11-10。使用标题属性

`

             Example                                                 thead th, tfoot th { text-align:left; background:grey; color:white}             tbody th { text-align:right; background: lightgrey; color:grey}             thead [colspan], tfoot [colspan] {text-align:center; }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
RankNameColorSize & Votes
Favorite:ApplesGreenMedium500
2nd Favorite:OrangesOrangeLarge450
© 2011 Adam Freeman Fruit Data Enterprises
     `

我给thead中的每个th元素和出现在tbody中的th元素添加了全局id属性。对于tbody中的每个tdth,我使用了headers属性将单元格与列标题关联起来。对于td元素,我还指定了行标题(出现在第一列的标题)。

给表格添加标题

caption元素允许您定义一个标题,并将其与一个table元素相关联。表 11-9 总结了caption元素。

Image

清单 11-11 展示了使用中的caption元素。

清单 11-11。使用标题元素

`

             Example                                                 thead th, tfoot th { text-align:left; background:grey; color:white}             tbody th { text-align:right; background: lightgrey; color:grey}             [colspan], [rowspan] {font-weight:bold; border: medium solid black}             thead [colspan], tfoot [colspan] {text-align:center; }             **caption {font-weight: bold; font-size: large; margin-bottom:5px}**                             **            **                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Results of the 2011 Fruit Survey
RankNameColorSize & Votes
Favorite:ApplesGreenMedium500
2nd Favorite:OrangesOrangeLarge450
3rd Favorite:Pomegranate                         Pomegranates and cherries can both come in a range of colors                         and sizes.                     203
Joint 4th:Cherries75
PineappleBrownVery Large
© 2011 Adam Freeman Fruit Data Enterprises
     `

一个表格只能包含一个caption元素,但它不必是表格中包含的第一个元素。但是,它将始终显示在表的上方,而不管元素是在哪里定义的。你可以在图 11-9 中看到标题的效果(以及我应用的样式)。

Image

图 11-9。给表格添加标题

使用列

HTML 处理表格的方式是面向行的。您将单元格的定义放在tr元素中,并逐行构建表格。这使得对列应用样式变得很困难,尤其是在处理包含不规则单元格的表格时。这个问题的解决方案是使用colgroupcol元素。

colgroup元素表示一组列。表 11-10 总结了colgroup要素。

Image

清单 11-12 展示了colgroup元素的使用。

清单 11-12。使用 colgroup 元素

`

             Example                                                 thead th, tfoot th { text-align:left; background:grey; color:white}             tbody th { text-align:right; background: lightgrey; color:grey}             [colspan], [rowspan] {font-weight:bold; border: medium solid black}             thead [colspan], tfoot [colspan] {text-align:center; }             caption {font-weight: bold; font-size: large; margin-bottom:5px}             **#colgroup1 {background-color: red}**             **#colgroup2 {background-color: green; font-size:small}**                                                      ****             ****                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Results of the 2011 Fruit Survey
RankNameColorSize & Votes
Favorite:ApplesGreenMedium500
2nd Favorite:OrangesOrangeLarge450
3rd Favorite:Pomegranate                         Pomegranates and cherries can both come in a range of colors                         and sizes.                     203
Joint 4th:Cherries75
PineappleBrownVery Large
© 2011 Adam Freeman Fruit Data Enterprises
     `

在这个例子中,我定义了两个colgroup元素。属性指定了colgroup元素应用于多少列。清单中的第一个colgroup应用于表中的前三列,另一个元素应用于接下来的两列。我将全局的id属性应用于每个colgroup元素,并定义了使用id值作为选择器的 CSS 样式。在图 11-10 中可以看到效果。

Image

图 11-10。使用 colgroup 元素

该图展示了使用colgroup元素的一些重要方面。首先要知道的是,应用于colgroups的 CSS 样式比直接应用于trtdth元素的样式具有更低的特异性。您可以看到,应用于theadtfoot和第一列th元素的样式不受匹配colgroups的样式的影响。如果我移除除了那些针对colgroup元素的样式之外的所有样式,所有的单元格都会被修改,如图 11-11 所示。

Image

图 11-11。移除所有的样式,除了那些直接指向 colspan 元素的样式

要注意的第二点是,不规则单元格被算作它们开始所在的列的一部分。您可以在第三行看到这一点,第一个样式匹配的单元格扩展到另一个colgroup元素覆盖的区域。

需要注意的最后一点是,colgroup元素包括一列中的所有单元格,甚至包括那些在theadtfoot元素中的单元格,并且它匹配thtd元素。colgroup元素很特殊,因为它与元素中不包含的元素相关。这意味着您不能使用colgroup元素作为更多焦点选择器的基础(例如,像#colgroup1 > td这样的选择器不匹配任何元素)。

调出单个列

您可以使用col元素来代替colgroup元素的span属性。这允许您定义一个组和其中存在的不同列。表 11-11 总结了col要素。

Image

Image

使用col元素的好处是更好的控制。您可以将样式应用于多组列以及该组中的单个列。col元素放在colgroup元素里面,如清单 11-13 所示,col的每个实例代表组中的一列。

清单 11-13。使用 col 元素

`

             Example                                                 thead th, tfoot th { text-align:left; background:grey; color:white}             tbody th { text-align:right; background: lightgrey; color:grey}             [colspan], [rowspan] {font-weight:bold; border: medium solid black}             thead [colspan], tfoot [colspan] {text-align:center; }             caption {font-weight: bold; font-size: large; margin-bottom:5px}             **#colgroup1 {background-color: red}**             **#col3 {background-color: green; font-size:small}**                                                      ****                 ****                 ****             ****                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
Results of the 2011 Fruit Survey
RankNameColorSize & Votes
Favorite:ApplesGreenMedium500
2nd Favorite:OrangesOrangeLarge450
3rd Favorite:Pomegranate                         Pomegranates and cherries can both come in a range of colors                         and sizes.                     203
Joint 4th:Cherries75
PineappleBrownVery Large
© 2011 Adam Freeman Fruit Data Enterprises
     `

您可以使用span属性创建一个表示colgroup中两列的col元素。如果不使用span属性,col元素表示一个单独的列。在这个例子中,我对colgroup和它包含的一个col元素应用了一个样式。在图 11-12 中可以看到效果。

Image

图 11-12。使用 colgroup 和 col 元素对表格应用样式

对表格元素应用边框

元素定义了属性。当您应用这个属性时,它告诉浏览器您正在使用table来表示表格数据,而不是布局其他元素。大多数浏览器通过在table和每个单元格周围绘制边框来响应border属性。清单 11-14 显示了border元素的应用。

清单 11-14。使用边框属性

`

             Example                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Results of the 2011 Fruit Survey
RankNameColorSize & Votes
Favorite:ApplesGreenMedium500
2nd Favorite:OrangesOrangeLarge450
3rd Favorite:Pomegranate                         Pomegranates and cherries can both come in a range of colors                         and sizes.                     203
Joint 4th:Cherries75
PineappleBrownVery Large
© 2011 Adam Freeman Fruit Data Enterprises
     `

分配给border属性的值必须是1或空字符串("")。该属性不控制边框的样式。你通过 CSS 做到这一点。你可以在图 11-13 中看到 Google Chrome 如何响应border属性的出现。(注意,我从这个例子中删除了style元素,以强调border属性的效果。)

Image

图 11-13。将边框属性应用到表格元素的效果

浏览器应用的默认边框并不特别吸引人,所以除了border属性之外,通常还必须使用 CSS。

Image 提示你不必将border属性应用到表格中就能使用 CSS 定义边框。但是,如果您不应用border属性,浏览器可以随意假设您将表格用于布局目的,并且它可能会以一种意想不到的方式显示表格。当我写这篇文章时,主流浏览器并不太关注border属性(除了应用默认边框),但这可能会在未来改变。

即使border属性使浏览器将边框应用于表格的每个单元格,您仍然必须在 CSS 选择器中单独定位要替换的每种元素。在创建 CSS 选择器时,您并不缺少选择:您可以通过table元素定位表格的外部边框;带有theadtbodytfoot元素的页眉、正文和页脚;通过colspancol元素的列;以及使用thtd元件的单个单元。而且,如果所有其他方法都失败了,您仍然可以使用idclass全局属性显式地创建目标。

总结

在这一章中,我带你参观了 HTML5 对表格的支持。HTML5 中最重要的变化是你不能再使用表格来处理页面布局——为此你必须依赖 CSS 表格支持,我在第二十一章中对此进行了描述。除了这一限制之外,表格具有无限的灵活性,易于设计,并且使用起来很愉快。

十二、使用表单

表单是收集用户输入的 HTML 机制。表单对 web 应用非常重要,但是多年来,HTML 中定义的功能落后于表单的使用方式。在 HTML5 中,整个表单系统都经过了彻底检查和修饰,使标准与表单的使用方式保持一致。

在这一章中,我描述了 HTML 表单的基础。我首先定义一个非常简单的表单,并在此基础上演示如何配置和控制表单的操作方式。我介绍了一个 Node.js 脚本,您可以用它来测试您的表单并查看从浏览器发送到服务器的数据。

在接下来的章节中,我将介绍高级表单特性,包括最受关注的 HTML5 变化——从用户处收集特定数据类型的新方法,以及在浏览器中验证数据的能力。这些都是重要的增强,但是许多其他的变化也值得注意。这一章和下一章都值得密切关注。

在我写这篇文章时,主流浏览器对 HTML5 表单的支持是好的,但并不完美,在采用它之前,值得检查一下每个特性的实现范围。表 12-1 对本章进行了总结。

Image

Image

创建基本表单

要创建一个基本表单,您需要三个元素:forminputbutton元素。清单 12-1 显示了一个包含简单表单的 HTML 文档。

清单 12-1。一个简单的 HTML 表单

`

             Example                                      **                                  Submit Vote         **      `

你可以在图 12-1 中看到这是如何出现在浏览器中的。

Image

图 12-1。在浏览器中显示基本表单

这个表单太简单了,没什么用,但是在你看完三个核心元素之后,你可以开始添加表单,让它更有意义和有用。

定义表单

起点是form元素,它表示 HTML 页面中表单的存在。表 12-2 总结了form要素。

Image

Image

在本章的后面,我将回头向您展示如何使用元素属性来配置form元素。目前,知道form元素告诉浏览器它正在处理一个 HTML 表单就足够了。

第二个关键元素是input,它允许您收集来自用户的输入。你可以在图 12-1 中看到,input元素已经被浏览器显示为一个简单的文本框,用户可以在其中输入内容。这是最基本类型的input元素,正如你将看到的,有很多选项可以让你收集用户的输入(包括 HTML5 中一些不错的新增内容)。我会在第十三章中解释这些。表 12-3 总结了input要素。

Image

根据type属性的值,有 29 个属性可以应用于input元素。在第十三章的中,我将展示这些属性,并解释它们的用途。

Image 提示您可以使用除了input之外的元素从用户那里收集数据。我在第十四章中解释并演示了这些。

示例中的最后一个元素是button。您需要一些方法让用户向浏览器表明所有的数据都已输入,浏览器应该将数据发送给服务器。button元素是最常用的方法(尽管,你会在第十三章的中看到,你还可以使用另一种机制)。表 12-4 总结了button元素。

Image

元素是一个多用途元素,我将在本章后面的“使用按钮元素”一节中解释它的用途。当在一个没有任何属性的form元素中使用时,button元素告诉浏览器将从用户那里收集的数据提交给服务器。

查看表单数据

您需要一个服务器,以便浏览器向其发送数据。为此,我编写了一个简单的 Node.js 脚本,该脚本生成一个 HTML 页面,其中包含表单从用户那里收集的数据。获取和设置 Node.js 的细节见第二章。清单 12-2 显示了我们将使用的脚本。正如我在第二章的中提到的,我不会深究服务器端脚本的细节,但是因为 Node.js 是基于 JavaScript 的,所以通过阅读第五章中对 JavaScript 语言特性的描述以及阅读[nodejs.org](http://nodejs.org)中的一些文档,你可以很容易地看到这个脚本做了什么。

清单 12-2。formecho.js 脚本

`var http = require('http'); var querystring = require('querystring');

http.createServer(function (req, res) {   switch(req.url) {     case '/form':         if (req.method == 'POST') {          console.log("[200] " + req.method + " to " + req.url);          var fullBody = '';          req.on('data', function(chunk) {            fullBody += chunk.toString();          });          req.on('end', function() {            res.writeHead(200, "OK", {'Content-Type': 'text/html'});              res.write('Post data');            res.write('th, td {text-align:left; padding:5px; color:black}\n');            res.write('th {background-color:grey; color:white; min-width:10em}\n');            res.write('td {background-color:lightgrey}\n');            res.write('caption {font-weight:bold}');            res.write('

');            res.write('');            var dBody = querystring.parse(fullBody);            for (var prop in dBody) {             res.write("");            }            res.write('
Form Data
NameValue
" + prop + "" + dBody[prop] + "
');            res.end();          });        } else {          console.log("[405] " + req.method + " to " + req.url);          res.writeHead(405, "Method not supported", {'Content-Type': 'text/html'});          res.end('405 - Method not supported' +                  '

Method not supported.

');        }       break;     default:       res.writeHead(404, "Not found", {'Content-Type': 'text/html'});       res.end('404 - Not found' +               '

Not found.

');       console.log("[404] " + req.method + " to " + req.url);   }; }).listen(8080);`

这个脚本收集浏览器提交的数据,并返回一个简单的 HTML 文档,在 HTML 表中显示这些数据。(我在第十一章中描述了table元素。)这个脚本监听端口8080上的浏览器连接,并且只处理使用 HTTP POST 方法从浏览器发送到/form URL 的表单。当您在本章后面查看由form元素支持的属性时,您将看到端口8080/form URL 的重要性。我将这个脚本保存到一个名为formecho.js的文件中。为了启动这个脚本,我在titan上打开了一个命令提示符,并输入了以下内容:


bin\node.exe formecho.js


Titan 运行 Windows Server 2008 R2,因此如果您使用另一个操作系统,启动 Node.js 的确切命令会有所不同。图 12-2 显示了浏览器显示在示例表单的文本框中输入Apples并按下Submit Vote按钮产生的输出。

Image

图 12-2。使用 Node.js 查看浏览器提交的表单数据

只有一项数据,因为在示例表单中只有一个input元素。Name列中的值是fave,因为这是我分配给input元素中的name属性的值。Value列中的值是Apples,因为这是我在按下Submit Vote按钮之前输入到文本框中的值。在我们创建更复杂的表单时,我将展示 Node.js 脚本的表格输出。

配置表单

我们创建了一个包含基本表单的 HTML 文档,并使用 Node.js 显示发送到服务器的数据。现在是时候向您展示可以应用于表单及其内容的基本配置选项了。

配置表单动作属性

action属性指定当form被提交时,浏览器应该将从用户那里收集的数据发送到哪里。我希望将数据提交给我的 Node.js 脚本,这意味着我希望将表单发送到我的开发服务器titan的端口8080上的/form URL。你可以看到我已经在清单 12-1 中以原始形式表达了这一点,就像这样:

... **<form method="post" action="http://titan:8080/form">** ...

如果不将action属性应用到form元素,浏览器会将表单数据发送到加载 HTML 文档的 URL。这并不像最初看起来那样毫无用处,一些流行的 web 应用开发框架都依赖于这一特性。

如果你指定了一个相对 URL,这个值将被附加到当前页面的 URL 上,或者如果你使用了在第七章的中描述的base元素,这个值将被附加到该元素的href属性的值上。清单 12-3 展示了如何使用base元素来设置表单数据的目的地。

清单 12-3。使用基本元素设置表单数据的目的地

`

             Example                            **        **                                             Submit Vote               `

Image 注意base元素影响HTML 文档中所有的相对 URL,而不仅仅是form元素。

配置 HTTP 方法属性

属性指定使用哪种 HTTP 方法将表单数据发送到服务器。允许的值是getpost,它们对应于 HTTP GETPOST方法。不应用method属性时使用的缺省值是get,这很不幸,因为大多数表单都需要 HTTP POST。您可以看到我为示例中的form指定了post值,如下所示:

... **<form method="post" action="http://titan:8080/form">** ...

GET 请求是针对安全交互的,这意味着你可以任意多次发出相同的请求,而且不会有副作用。POST 请求是针对不安全的交互,提交数据的行为改变了某种状态。在处理 web 应用时,这是最常见的情况。这些约定是由万维网联盟(W3C)制定的,你可以在[www.w3.org/Provider/Style/URI](http://www.w3.org/Provider/Style/URI)读到。

根据经验,GET 请求应该用于所有的只读信息检索,而 POST 请求应该用于任何改变应用状态的操作。使用正确的请求很重要。如果你不确定,为了谨慎起见,使用 POST 方法。

Image 提示我在本章中使用的 Node.js 脚本将只响应 POST 请求。

配置数据编码

enctype属性指定了浏览器如何编码和向服务器显示数据。该属性有三个允许值,在表 12-5 中描述。

Image

为了理解不同的编码是如何工作的,您需要在表单中添加第二个input元素,如清单 12-4 中的所示。

清单 12-4。向表单添加输入元素

`

             Example                                                            **            **             Submit Vote               `

您需要第二个input元素,这样您就可以从用户那里收集两项数据。正如您可能已经猜到的那样,您正在构建一个允许用户为他们喜欢的水果投票的表单。新的input元素将用于收集他们的名字。从清单中可以看出,我将这个元素的name值设置为name。为了演示不同表单编码的效果,我向表单添加了enctype属性,并将其设置为每种支持的编码类型。在每个实例中,我都在文本框中输入了相同的数据。在第一个文本框中,我输入了Apples,在第二个文本框中,我输入了Adam Freeman(在我的名字和名字之间留有空格)。

application/x-www-form-urlencoded 编码

这是默认编码,适用于除了向服务器上传文件的表单之外的所有表单。每个数据项的名称和值使用与编码 URL 相同的方案进行编码(因此,名称的urlencoded部分)。这是编码如何应用于示例表单中的数据:


fave=Apples&name=Adam+Freeman


特殊字符被替换为它们对应的 HTML 实体。数据项的名称和值由等号(=)分隔,数据/值元组由&符号(&)分隔。

多部分/形式数据编码

multipart/form-data编码采用了不同的方法。它更冗长,处理起来也更复杂,这就是为什么它通常只用于需要向服务器上传文件的表单——这是使用默认编码无法做到的。下面是示例表单中数据的编码方式:


`------WebKitFormBoundary2qgCsuH4ohZ5eObF

Content-Disposition: form-data; name="fave"

Apples

------WebKitFormBoundary2qgCsuH4ohZ5eObF

Content-Disposition: form-data; name="name"

Adam Freeman

------WebKitFormBoundary2qgCsuH4ohZ5eObF--

fave=Apple

name=Adam Freeman`


文本/普通编码

应该谨慎使用这种编码。对于使用这种方案时应该如何对数据进行编码,没有正式的规范,并且主流浏览器以不同的方式对数据进行编码。例如,Google Chrome 编码数据的方式与application/x-www-form-urlencoded方案相同,而 Firefox 编码数据的方式如下:


`fave=Apple

name=Adam Freeman`


每个数据项放在一行上,特殊字符不编码。我建议避免这种编码。浏览器之间的差异使其不可预测。

控制表单完成

浏览器帮助用户记住他们输入到表单中的数据,并在再次看到类似的表单时自动重用这些数据。这种技术减少了用户反复输入相同数据的需要。一个很好的例子是用户在网上购买商品或服务时输入的姓名和送货细节。每个网站都有自己的购物车和注册流程,但我的浏览器使用我在其他表格中输入的数据来加快结账流程。浏览器使用不同的技术来确定要重用的数据,但是一种常见的方法是寻找input元素的name属性。

一般来说,自动完成表单对用户是有益的,对 web 应用没有什么影响。但是有些时候你不希望浏览器填写表单。清单 12-5 展示了如何在form元素上使用autocomplete属性来实现这一点。

清单 12-5。禁用表单元素自动完成属性

`

             Example                                                                                     Submit Vote               `

autocomplete属性有两个允许的值:onoffon值允许浏览器填写表单,并且是不应用该属性时采用的默认值。

您可以通过将autocomplete属性应用到单个的input元素来更加具体,如清单 12-6 所示。

清单 12-6。将 autocomplete 属性应用于输入元素

`

             Example                                                                                     Submit Vote               `

form元素上的autocomplete属性为表单中的input元素设置默认策略。但是,如清单所示,您可以为单个元素覆盖该策略。在这个例子中,form元素上的属性禁用了自动完成,但是应用于第一个input元素的相同属性将其重新打开——但是只针对该元素。第二个input元素,还没有应用autocomplete属性,服从于form范围的策略。

一般来说,您应该让autocomplete处于启用状态——用户习惯于自动填充表单,并且在任何类型的 web 事务中通常会面对多个表单。对于你来说,取消这个功能侵犯了你的用户的偏好和工作习惯。我从自己的经验中知道,当我试图从禁用自动完成功能的网站购买商品时,尤其是当我试图填写的表单需要非常基本的信息,如我的姓名和地址时,这是很不和谐的。一些网站禁用信用卡数据的自动完成功能,这更有意义,但即使这样,这种方法也应该谨慎使用,并且应该充分考虑使用该功能的原因。

指定表单响应的目标

浏览器的默认行为是在提交表单后用服务器返回的响应替换包含表单的页面。您可以通过使用form元素上的target属性来改变这种行为。该属性的工作方式与a元素上的target属性相同,您可以从表 12-6 所示的目标范围中进行选择。

Image

Image

这些值中的每一个都代表一个浏览上下文_blank_self值是不言而喻的。其他的与框架的使用有关,我会在第十五章中解释。清单 12-7 显示了应用于form元素的target属性。

清单 12-7。使用目标属性

`

             Example                                                                                     Submit Vote               `

在这个例子中,我指定了_blank目标,它告诉浏览器在一个新窗口或标签中显示来自服务器的响应。你可以在图 12-3 中看到这种变化的效果。

Image

图 12-3。在新标签中显示来自服务器的响应

设置表单的名称

name属性允许您为表单设置一个唯一的标识符,以便在使用文档对象模型(DOM)时可以区分表单。我在第二十五章中介绍了 DOM。name属性不同于id全局属性,在大多数情况下,HTML 文档使用 CSS 选择器的id属性。清单 12-8 显示了一个nameid属性被应用到的form元素。为了简单起见,我对这两个属性使用了相同的值。

清单 12-8。在表单元素上使用 name 和 id 属性

`

             Example                                                                                     Submit Vote               `

表单提交时,name属性的值不会发送到服务器,这就是为什么这个属性只在 DOM 中有值,并且没有input元素上的name属性重要。如果一个input元素没有name属性,当form被提交时,用户输入的数据不会被发送到服务器。

给表格添加标签

您有一个从用户那里收集数据的表单,但是它不是很容易使用。你可以在图 12-4 中看到上一节添加的input元素是如何被浏览器显示的。

Image

图 12-4。示例表单

显而易见的问题是完全缺乏对用户的指导,用户必须阅读源 HTML 来弄清楚每个文本框是干什么的。您可以通过使用label元素来解决这个问题,它允许您为表单中的每个元素提供一些上下文。表 12-7 总结了label要素。

Image

Image

清单 12-9 显示了如何给用户一些上下文。

清单 12-9。使用标签元素

`

             Example                                                           

****Fruit: ****

            

**Name:** ****

            Submit Vote               `

我为每个input元素添加了一个label。注意,我向input元素添加了一个id属性,并使用这些id作为label元素上for属性的值。这就是将标签与输入关联起来的方式,对于屏幕阅读器和其他辅助技术来说,这使得处理表单更加简单。你可以在图 12-5 中看到标签是如何出现的。

Image

图 12-5。向表单添加标签

在清单中,我将input元素作为label元素的内容。这不是必需的,这两个元素可以彼此独立地定义。在布局复杂表单时,通常独立于input来定义label

Image 注意我在表单中添加了一些p元素来提供一个非常基本的布局。这是我在本章的大部分例子中要做的事情,因为它会让我们更容易看到 HTML 文档中添加的内容对表示的影响。为了给表单元素创建更漂亮的布局,你可以使用 CSS 表格特性,我在第二十一章中描述了这个特性。第九章的中描述了p元素。

自动聚焦输入元素

您可以选择显示表单时浏览器关注的input元素。这意味着用户可以直接开始在所选字段中键入内容,而不必先明确选择它。用autofocus属性指定焦点应该应用于哪个input元素,如清单 12-10 中的所示。

清单 12-10。使用自动对焦属性

`

             Example                                                           

                Fruit:             

            

Name:

            Submit Vote               `

浏览器一显示页面,就会关注第一个输入元素。在图 12-6 中,你可以看到谷歌浏览器给用户的视觉提示,指示一个聚焦的元素。

Image

图 12-6。在输入元素上自动聚焦

您只能将autofocus属性应用于一个input元素。如果您尝试多次应用该元素,浏览器将关注文档中包含该元素的最后一个元素。

禁用单个输入元素

您可以禁用input元素,这样用户就不能在其中输入数据。这并不像听起来那么奇怪。您可能希望呈现一个用于几个相关任务的一致的界面,但是并不是所有的input元素都与之密切相关。您还可以使用 JavaScript 基于用户的操作来启用元素。一个常见的例子是,当用户选择送货地址而不是用户的账单地址时,启用一组input元素来捕获地址。(你可以通过 DOM 启用这些元素,这将在第 25-31 章中描述。在第十三章的中描述了向用户显示复选框。)

您可以通过应用disabled属性来禁用input元素,如清单 12-11 所示。

清单 12-11。在输入元素上使用禁用属性

`

             Example                                                           

                Fruit:             

            

                Name:             

            Submit Vote               `

在这个例子中,我将disabled属性应用于收集用户名的input元素。你可以在图 12-7 的中看到谷歌浏览器如何显示一个被禁用的input元素。其他浏览器使用类似的风格。

Image

图 12-7。禁用输入元件

将表单元素分组在一起

当您构建更复杂的表单时,将一些元素组合在一起会很方便,这可以使用fieldset元素来实现。表 12-8 总结了这一要素。

Image

Image

您可以在清单 12-12 的中看到fieldset元素是如何应用的。我在这个例子中添加了额外的input元素,以演示一个fieldset可以应用于表单中元素的子集。

清单 12-12。使用字段集元素

`

             Example                                                                            

Name:

                

City:

                                          

#1:

                

#2:

                

#3:

                         Submit Vote               `

我用一个fieldset元素将两个收集用户详细信息的input元素组合在一起,用另一个fieldset元素将三个input元素组合在一起,允许用户为她最喜欢的三种水果投票。你可以在图 12-8 中看到浏览器如何显示fieldset元素的默认样式约定。

Image

图 12-8。使用 fieldset 元素将输入元素组合在一起

向字段集元素添加描述性标签

您将input元素分组在一起,但是仍然缺乏用户上下文。您可以通过向每个fieldset元素添加一个legend元素来解决这个问题。表 12-9 总结了这一要素。

Image

Image

legend元素必须是fieldset元素的第一个子元素,如清单 12-13 所示。

清单 12-13。使用图例元素

`

             Example                                                            **                Enter Your Details**                 

Name:

                

City:

                          **                Vote For Your Three Favorite Fruits**                 

#1:

                

#2:

                

#3:

                         Submit Vote               `

你可以在图 12-9 中看到浏览器如何显示图例元素。

Image

图 12-9。使用图例元素

使用字段集元素禁用输入组

在本章的前面,我已经向您展示了如何禁用单独的 input元素。您还可以通过将disabled属性应用到fieldset元素,在一个步骤中禁用多个 input元素。当你这样做时,fieldset包含的所有input元素都将被禁用,如清单 12-14 所示。

清单 12-14。使用字段集元素禁用输入元素

`

             Example                                                                            Enter Your Details                 

Name:

                

City:

                                          Vote For Your Three Favorite Fruits                 

#1:

                

#2:

                

#3:

                         Submit Vote               `

你可以在图 12-10 中看到禁用输入元素的效果。

Image

图 12-10。通过字段集元素禁用输入元素

使用按钮元素

button元素比它第一次出现时更加灵活。有三种方法可以使用button。这些不同操作模式的关键是type属性,它有三个值。这些在表 12-10 中描述。

Image

在接下来的部分中,我将描述这些值和它们提供的功能。

使用按钮元素提交表单

当您将type属性设置为submit时,按下按钮将提交包含该按钮的表单。当您没有应用type属性时,这是默认行为。当您以这种方式使用按钮时,您可以访问一些附加属性,这些属性在表 12-11 中有所描述。

Image

在大多数情况下,这些属性允许您覆盖或补充form元素的配置,指定动作、方法、编码方案和目标,并控制客户端验证。这些元素是 HTML5 中的新内容。清单 12-15 展示了如何将这些属性应用到button元素中。

清单 12-15。使用按钮元素属性

`

             Example                                                           

                Fruit:             

            

                Name:             

            Submit Vote               `

在这个例子中,我从form元素中省略了actionmethod属性,并通过button元素上的formactionformmethod属性提供了配置。

使用按钮元素重置表单

如果将type属性设置为reset,按下按钮会导致表单中的所有输入元素被重置为初始状态。以这种方式使用 button 元素时,没有其他属性可用。清单 12-16 展示了在 HTML 文档中添加一个重置button

清单 12-16。使用按钮元素重置表单

`

             Example                                                           

                Fruit:             

            

                Name:             

            Submit Vote **            Reset**               `

你可以在图 12-11 中看到重置表单的效果。

Image

图 12-11。重置表单

使用按钮作为通用元素

如果将type属性设置为button,就创建了一个button元素...只是一个按钮。没什么特别的意思,按了也不会怎么样。清单 12-17 展示了在示例 HTML 文档中添加这样一个button

清单 12-17。使用通用按钮

`

             Example                                                           

                Fruit:             

            

                Name:             

            Submit Vote             Reset **            Do NOT press this button**               `

这似乎不是使用元素的有效方法,但是正如我在第三十章中解释的,当按钮被按下时,你可以使用 JavaScript 来执行动作。这允许您在网页中创建自定义行为。

注意,我设计了包含在button元素中的文本。你可以使用任何语法元素来标记文本。你可以在图 12-12 中看到这个标记的效果。

Image

图 12-12。添加通用按钮元素

使用表单外的元素

在 HTML4 中,inputbutton和其他与表单相关的元素必须包含在form元素中,就像我在本章迄今为止的所有例子中演示的那样。在 HTML5 中,这种限制已经取消,您可以在文档的任何地方将元素与表单相关联。你可以使用属性form来实现,这个属性由inputbutton以及我在第十四章中描述的其他表单相关元素来定义。要将一个元素与不是先行元素的form相关联,只需将form属性设置为formid值。清单 12-18 给出了一个例子。

清单 12-18。使用表单属性

`

             Example                                                           

                Fruit:             

                 

            Name:                      

        <button form="voteform" type="submit">Submit Vote         <button form="voteform" type="reset">Reset     

`

在这个例子中,只有一个input元素是form元素的后代。另一个input元素和两个button元素都在form元素之外,但是它们使用form属性将自己与表单关联起来。

总结

在这一章中,我向你展示了 HTML5 对表单支持的基础。您看到了如何使用form元素来表示一个表单并配置表单的工作方式。我向您展示了基本的input元素,它允许您从用户那里收集简单的文本数据,还展示了button元素,它允许用户提交或重置表单(您可以将它用作通用按钮)。

HTML5 中有一些有用的新表单特性。标题项将在下一章介绍,但即使是基本的表单操作也有所改进。将一个元素与一个不是先行元素的表单相关联的能力、对自动聚焦元素的支持以及对button元素的增强都是受欢迎的新增功能。