HTML-前端

发布于:2025-05-24 ⋅ 阅读:(21) ⋅ 点赞:(0)

目录

开始学习HTML 

什么是 HTML?

剖析一个 HTML 元素

嵌套元素

块级元素和内联元素

空元素

属性

为元素添加属性

 布尔属性

省略包围属性值的引号

使用单引号还是双引号?

 剖析 HTML 文档

HTML 中的空白

 实体引用:在 HTML 中包含特殊字符

HTML 注释

总结

 “头”里有什么——HTML 元信息

什么是 HTML 头部

添加标题

主动学习:一个简单的示例

元数据: 元素

 指定文档中的字符编码

添加作者和描述

主动学习:在搜索引擎中 description 的使用

 其他类型的元数据

在你的站点增加自定义图标

在 HTML 中应用 CSS 和 JavaScript

主动学习:在网页中应用 CSS 和 JavaScript

为文档设定主语言

总结

 HTML 的标题和段落

标题和段落

实现结构层级

为什么我们需要结构化?

为什么我们需要语义?

总结

强调与重要性 

什么是强调和着重强调?

强调

着重强调

主动学习:我们是重要的!

斜体、粗体、下划线……

总结

列表 

无序列表

有序列表

嵌套列表

描述列表

描述列表示例

技能测试!

总结

文档与网站架构 

主动学习:研究示例代码

无语义元素

 换行与水平分割线


:换行元素


:主题性中断元素

规划一个简单的网站

主动学习:创建站点地图

小结

参见

文本格式进阶

引用

块引用

行内引用

引文

缩略语

缩略语示例

标记联系方式

上标和下标

展示计算机代码

标记时间和日期

总结

创建超链接 

什么是超链接?

链接的解析

块级链接

图片链接

使用标题属性添加支持信息

统一资源定位符(URL)与路径(path)快速入门

分割文档

绝对 URL 和相对 URL

链接最佳实践

使用响亮的链接措辞

链接到非 HTML 资源——留下清晰的指示

在下载链接时使用下载属性

学习主动性:创建一个导航菜单

电子邮件链接

指定详细信息

技能测试!

小结

HTML 中的图片

怎样将图片放到网页上?

备选文本

宽度和高度

图像标题

媒体资源和许可

了解许可类型

版权所有

自由许可

公共领域/CC0

搜索适用于自由许可的图像

通过为图片搭配说明文字的方式来解说图片

CSS 背景图片

网页上的其他图形

技能测试!

总结

视频和音频内容 

web 中的音频和视频

使用多个播放源以提高兼容性

媒体文件的内容

浏览器所支持的媒体文件

其他

显示视频文本

主动练习:嵌入你自己的视频与音频

技能测试!

总结

参见

HTML 表格基础

什么是表格?

表格如何工作?

表格风格

什么时候你不应该使用 HTML 表格?

动手练习:创建你的第一个表格

结果

使用 元素添加标题

动手练习:表格标题

为什么标题是有用的?

允许单元格跨越多行和列

使用 应用样式

动手练习:colgroup 和 col

总结

HTML 表格进阶特性和无障碍 

使用 为你的表格增加一个标题

动手练习:添加一个标题

添加 、 和 结构

动手练习:添加表格结构

嵌套表格

对于视力受损的用户的表格

使用列和行的标题

scope 属性

id 和 headers 属性

动手练习:使用 scope 和 headers

总结

HTML 中的表单和按钮

与用户互动

按钮

表单的解剖

元素

结构化形式

元素

专用文本字段输入

显式和隐式表单标签

元素

其他控制类型

单选按钮

禁用表单控件

复选框

多行文本输入字段

表单验证

概括


 

 

开始学习HTML 

什么是 HTML?

HTML(HyperText Markup Language,超文本标记语言)是一种用来告知浏览器如何组织页面的标记语言。HTML 可复杂、可简单,一切取决于 web 开发者。HTML 由一系列的元素组成,这些元素可以用来包围或标记不同部分的内容,使其以某种方式呈现或者工作。两端的标签可以使内容变成超链接,以连接到另一个页面;使字体表现为斜体等。例如,考虑如下内容

 My cat is very grumpy

 如果我们想要将这行文字单独呈现,可以将这行文字封装成一个段落(Paragraph)<p> 元素:
 

<p>My cat is very grumpy</p>

备注: HTML 标签不区分大小写。也就是说,输入标签时既可以使用大写字母也可以使用小写字母。例如,标签 <title> 可以写作 <title><TITLE><Title><TiTlE> 等,也都可以正常工作。不过,从一致性、可读性来说,最好仅使用小写字母。

剖析一个 HTML 元素

 让我们进一步探讨我们的前述的段落元素:

这个元素的主要部分有:

  • 开始标签(Opening tag):包含元素的名称(本例为 p),被左、右角括号所包围。开头标签标志着元素开始或开始生效的地方。在这个示例中,它在段落文本的开始之前。
  • 内容(Content):元素的内容,本例中就是段落的文本。
  • 结束标签(Closing tag):与开始标签相似,只是其在元素名之前包含了一个斜杠。这标志着该元素的结束。没有包含关闭标签是一个常见的初学者错误,它可能会产生奇特的结果。

整个元素即指开始标签、内容、结束标签三部分组成的整体。
 

嵌套元素

你也可以把元素放到其他元素之中——这被称作嵌套。如果我们想要表明我们的小猫脾气暴躁,可以将 very 一词嵌套在 <strong> 元素中,意味着这个单词被着重强调: 

<p>My cat is <strong>very</strong> grumpy.</p>

你需要确保元素被正确的嵌套:在上面的例子中我们先打开 p 元素,然后才打开 strong 元素,因此必须先将 strong 元素关闭,然后再去关闭 p 元素。下面的例子是错误的:
 

<p>My cat is <strong>very grumpy.</p></strong>

所有的元素都需要正确的打开和关闭,这样才能按你所想的方式展现。由于上述示例中的那种重叠,浏览器不得不猜测你的意图。这种猜测可能会导致意想不到的结果。

块级元素和内联元素
 

在 HTML 中有两种你需要知道的重要元素类别,块级元素和内联元素。

  • 块级元素在页面中以块的形式展现。一个块级元素出现在它前面的内容之后的新行上。任何跟在块级元素后面的内容也会出现在新的行上。块级元素通常是页面上的结构元素。例如,一个块级元素可能代表标题、段落、列表、导航菜单或页脚。一个块级元素不会嵌套在一个内联元素里面,但它可能嵌套在另一个块级元素里面。
  • 内联元素通常出现在块级元素中并环绕文档内容的一小部分,而不是一整个段落或者一组内容。内联元素不会导致文本换行。它通常与文本一起使用,例如,<a> 元素创建一个超链接,<em> 和 <strong> 等元素创建强调

     

考虑如下示例: 

<em>第一</em><em>第二</em><em>第三</em>

<p>第四</p>
<p>第五</p>
<p>第六</p>

<em> 是一个内联元素,所以就像你在下方可以看到的,第一行代码中的三个元素都没有间隙的展示在了同一行。而 <p> 是一个块级元素,所以第二行代码中的每个 p 元素分别都另起了新的一行展现,并且每个段落间都有一些间隔(这是因为默认的浏览器有着展示 <p> 元素的默认 CSS 样式)。

第一第二第三

第四

第五

第六

备注: HTML5 重新定义了元素的类别:见元素内容分类。尽管这些新的定义更精确,但却比上述的“块级元素”和“内联元素”更难理解,因此在之后的讨论中仍使用旧的定义。

备注: 在这篇文章中提到的“块”和“内联”,不应该与 CSS 盒子的类型中的同名术语相混淆。尽管它们默认是相关的,但改变 CSS 显示类型并不会改变元素的分类,也不会影响它可以包含和被包含于哪些元素。防止这种混淆也是 HTML5 摒弃这些术语的原因之一。

备注: 你可以查阅包含了块级元素和内联元素列表的参考页面。参见块级元素内联元素页面。

空元素

不是所有元素都拥有开始标签、内容和结束标签。一些元素只有一个标签,通常用来在此元素所在位置插入/嵌入一些东西。这些元素被称为空元素。例如:元素 <img> 是用来在页面插入一张指定的图片。 

<img
  src="https://roy-tian.github.io/learning-area/extras/getting-started-web/beginner-html-site/images/firefox-icon.png"
  alt="Firefox 图标" />

 备注: HTML 中,无需在一个空元素的标签末尾添加 /,例如 <img src="images/cat.jpg" alt="cat" />。然而,这也是一种有效的语法,当你希望你的 HTML 是有效的 XML 时,这么做也没问题。

属性

元素也可以拥有属性,属性看起来像这样: 

 属性包含元素的额外信息,这些信息不会出现在实际的内容中。在上述例子中,这个 class 属性是一个识别名称,以后为元素设置样式信息时更加方便。

属性必须包含:

  • 一个空格,它在属性和元素名称之间。如果一个元素具有多个属性,则每个属性之间必须由空格分隔。
  • 属性名称,后面跟着一个等于号。
  • 一个属性值,由一对引号("")引起来。
为元素添加属性

另一个例子是关于元素 <a> 的——元素 <a> 是,它使被标签包裹的内容成为一个超链接。锚元素可以添加多种属性,部分如下:

href

这个属性声明超链接的 web 地址。例如 href="https://www.mozilla.org/"

title

title 属性为超链接声明额外的信息,比如你将链接至的那个页面。例如 title="The Mozilla homepage"。当鼠标悬停在超链接上面时,这部分信息将以工具提示的形式显示。

target

target 属性用于指定链接如何呈现出来。例如,target="_blank" 将在新标签页中显示链接。如果你希望在当前标签页显示链接,忽略这个属性即可。

编辑下面的文本框中的内容,使之变成指向任一个你喜欢的 web 地址的链接。

  1. 添加 <a> 元素。
  2. 添加 href 属性和 title 属性。
  3. 指定 target 属性,使得点击链接时在新标签页打开。

 

 布尔属性

有时你会看到没有值的属性,这也是完全可以接受的。这些属性被称为布尔属性。布尔属性只能有一个值,这个值一般与属性名称相同。例如,考虑 disabled 属性,你可以将其分配给表单输入元素。用它来禁用表单输入元素,这样用户就不能输入了。被禁用的元素通常有一个灰色的外观。示例如下: 

<input type="text" disabled="disabled" />

 方便起见,我们完全可以将其写成以下形式:

<!-- 使用 disabled 属性来防止终端用户输入文本到输入框中 -->
<input type="text" disabled />

<!-- 下面这个输入框不包含 disabled 属性,所以用户可以向其中输入 -->
<input type="text" />

作为参考,上面的例子还包括一个非禁用的表单输入元素。上面两段 HTML 代码产生的效果如下:

省略包围属性值的引号

如果你看了很多其他网站的代码,你可能会遇到一些奇怪的标记风格,包括没有引号的属性值。在某些情况下它是被允许的,但是其他情况下会破坏你的标记。例如,针对之前的链接示例,我们可以像这样写一个只拥有一个 href 属性的版本:

<a href=https://www.mozilla.org/>favorite website</a>

 然而,当我们再添加一个 title 属性时,就会出现问题:

此时浏览器会误解你的标记,它会把 title 属性理解为三个属性——title 的属性值为 The,另外还有两个布尔属性 Mozilla 和 homepage,很明显不是我们所期望的!并且在这个编码里面它会报错或者出现异常行为。试一试把鼠标移动到链接上,看会显示什么 title 文字!

我们建议始终添加引号——这样可以避免很多问题,并且使代码更易读。 

使用单引号还是双引号?

在目前为止,本章内容所有的属性都是由双引号来包裹。然而,你也许在一些 HTML 中也见过单引号。这只是风格的问题,你可以从中选择一个你喜欢的。以下两种情况都可以:

<a href='https://www.example.com'>示例站点链接</a>

<a href="https://www.example.com">示例站点链接</a>

但应该注意单引号和双引号不能在一个属性值里面混用。下面的语法是错误的:

在一个 HTML 中已使用一种引号,你可以在此引号嵌套另外一种引号:

<a href="https://www.example.com" title="你觉得'好玩吗'?">示例站点链接</a>

如果你想将英文引号(单引号或双引号)当作文本显示在 html 中,你就必须使用 HTML 实体引用。像这样的代码就会破坏显示: 


要这样做:

<a href="https://www.example.com" title="Isn't this fun?">示例站点链接</a>

 剖析 HTML 文档

单独的 HTML 元素本身并不十分有用。接下来,我们来看看单个元素是如何组合成整个 HTML 页面的:

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <title>我的测试站点</title>
  </head>
  <body>
    <p>这是我的页面</p>
  </body>
</html>

这里我们有:

  1. <!DOCTYPE html>: 声明文档类型。早期的 HTML(大约 1991-1992 年)文档类型声明类似于链接,规定了 HTML 页面必须遵从的良好规则,能自动检测错误和其他有用的东西。文档类型使用类似于这样:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    

    文档类型是一个历史遗留问题,需要包含它才能使其他东西正常工作。现在,只需要知道 <!DOCTYPE html> 是最短的有效文档声明!

  2. <html></html><html> 元素。这个元素包裹了页面中所有的内容,有时被称为根元素。

  3. <head></head><head> 元素。这个元素是一个容器,它包含了所有你想包含在 HTML 页面中但不在 HTML 页面中显示的内容。这些内容包括你想在搜索结果中出现的关键字和页面描述、CSS 样式、字符集声明等等。以后的章节中会学到更多相关的内容。

  4. <meta charset="utf-8"><meta> 元素。这个元素代表了不能由其他 HTML 元相关元素表示的元数据,比如 <base><link><script><style> 或 <title>charset 属性将你的文档的字符集设置为 UTF-8,其中包括绝大多数人类书面语言的大多数字符。有了这个设置,页面现在可以处理它可能包含的任何文本内容。没有理由不对它进行设置,它可以帮助避免以后的一些问题。

  5. <title></title><title> 元素。这设置了页面的标题,也就是出现在该页面加载的浏览器标签中的内容。当页面被加入书签时,页面标题也被用来描述该页面。

  6. <body></body><body> 元素。包含了你访问页面时所有显示在页面上的内容,包含文本、图片、视频、游戏、可播放音频轨道等等。

HTML 中的空白

在上面的例子中,你可能已经注意到了在代码中包含了很多的空格——这是没有必要的;下面的两个代码片段是等价的:

<p>狗 狗 很 呆 萌。</p>

<p>狗 狗        很
         呆 萌。</p>

无论你在 HTML 元素的内容中使用多少空格(包括一个或多个空白字符或换行),当渲染这些代码的时候,HTML 解释器会将连续出现的空白字符减少为一个单独的空格符。

如果你的代码有很好的格式化,就会更容易理解你的代码中发生了什么。在我们的 HTML 中,每个嵌套元素都比它所在的元素多缩进了两个空格。你可以选择格式化的风格(例如,每一级缩进多少个空格),但你至少应该考虑格式化。

 实体引用:在 HTML 中包含特殊字符

在 HTML 中,字符 <>"' 和 & 是特殊字符。它们是 HTML 语法自身的一部分,那么你如何将这些字符包含进你的文本中呢,比如说如果你真的想要在文本中使用符号 & 或者小于号,而不想让它们被浏览器视为代码并被解释?

我们必须使用字符引用——表示字符的特殊编码,它们可以在那些情况下使用。每个字符引用以符号 & 开始,以分号(;)结束。

原义字符 等价字符引用
< &lt;
> &gt;
" &quot;
' &apos;
& &amp;

等价字符引用可以很容易记住,因为它使用的文本可以被看作是小于“&lt;”,引号是“&quot;”,其他的也是如此。要找到更多关于实体引用的信息,请参见 XML 和 HTML 字符实体引用列表(维基百科)。

在下面的示例中,有两个自然段:

htmlCopy to Clipboardplay

<p>HTML 中用 <p> 来定义段落元素。</p>

<p>HTML 中用 &lt;p&gt; 来定义段落元素</p>

在下面的实时输出中,你会看到第一段是错误的,因为浏览器会认为第二个 <p> 是开始一个新的段落!第二段是正确的,因为我们用字符引用来代替了角括号(< 和 > 符号)。

 备注: 不需要为任何其他符号使用实体引用,因为只要你的 HTML 的字符编码设置为 UTF-8,现代浏览器就能很好地处理实际符号。

HTML 注释

HTML 拥有在代码中写注释的机制。浏览器会忽略注释,有效地使注释对用户来说不可见。注释的目的是让你在代码中加入注释,以解释你的逻辑或编码。如果你在离开很久后回到一个代码库,以至于你不能完全记住它,这就非常有用。同样,当不同的人在进行修改和更新时,注释也是非常宝贵的。

为了将一段 HTML 中的内容置为注释,你需要将其用特殊的记号 <!-- 和 --> 包裹起来,比如:

<p>我在注释外!</p>

<!-- <p>我在注释内!</p> -->

正如你下面所见的那样,第一段出现在了实时输出中,但是第二段却没有。

 

总结

你已经来到了这篇文章的结尾——希望你享受基础的 HTML 学习的旅程。

在这里你应该可以理解 HTML 语言的全貌和基本的工作原理。你应该还学会了一些元素和属性的使用。在这个模块的后续文章中,我们会深入一些你已经见过的东西的细节,并且展示语言的一些其他概念。

备注: 当你开始学习更多的 HTML 知识时,可能也想了解一些层叠样式列表(CSS)的基础知识。CSS 是一种用来设计网页样式的语言(比如,用它改变字体、颜色或页面布局等)。你很快就会发现,HTML 和 CSS 能很好地协调配合。

 “头”里有什么——HTML 元信息

在页面加载完成的时候,HTML 文档中的头部是不会显示在 web 浏览器的。它包含了诸如页面的 <title>(标题)、指向 CSS 的链接(如果你选择用 CSS 来为 HTML 内容添加样式)、指向自定义网页图标的链接和其他的元数据(描述 HTML 的数据,比如作者和描述文档的重要关键词)等信息。Web 浏览器将使用文档头部的信息正确渲染 HTML 文档。本文将涵盖上述内容并拓展,以便为你的标记工作打下良好基础。

前提: 初步了解 HTML(参见 开始学习 HTML)。
学习目标: 学习 HTML 头部的概念、用途、所包含的重要项目,以及它对 HTML 文档所起的作用

什么是 HTML 头部

让我们简单回顾一下上一章节的 HTML 文档

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <title>我的测试页面</title>
  </head>
  <body>
    <p>这是我的页面</p>
  </body>
</html>

HTML 头部包含 HTML <head> 元素的内容,与 <body> 元素内容不同,页面在浏览器加载后它的内容不会在浏览器中显示,它的作用是保存页面的一些元数据。上述示例的头部非常简短:

<head>
  <meta charset="utf-8" />
  <title>我的测试页面</title>
</head>

然而,大型页面的头部会相当大。可以试着到一些喜欢的网站上,使用开发者工具查看网页的头部内容。我们在这里的目的不是向你展示如何使用所有可能放在头部的东西,而是教你如何熟悉使用你想要包括在头部的主要元素。让我们开始吧。

添加标题

之前已经讲过 <title> 元素,它可以为文档添加标题。但别和 <h1> 元素搞混了,<h1> 是为 body 添加顶级标题的。有时候 <h1> 也叫作网页标题,但是二者并不相同。

  • <h1> 元素在页面加载完毕时显示在页面中,通常只出现一次,用来标记页面内容的标题(故事名称、新闻摘要等等)。
  • <title> 元素是一项元数据,用于表示整个 HTML 文档的标题(而不是文档内容)。

主动学习:一个简单的示例

  1. 为了开始这个练习,我们希望你到我们的 GitHub 库中下载一份 title-example.html 网页副本。要做到这一点,你可以选择下面两种操作之一:

    1. 使用你的代码编辑器,从页面中拷贝粘贴代码到一个新的文本文件中,然后将其保存到一个适当的地方。
    2. 按下 GitHub 页面中的“Raw”按钮(可能会在浏览器新标签中显示源代码),从浏览器的菜单中选择 另存为...,然后选择一个地方来保存这个文件。
  2. 在浏览器中打开文件,你会看到类似这样效果:

    一个简单的 web 页面,在 'title' 元素上设置了文档标题,在 'h1' 元素上设置了页面标题

    现在很明显的可以看到 <h1> 和 <title> 出现的地方!

  3. 你应该尝试着在你的代码编辑器中打开这些代码,编辑这些元素的内容,然后在你的浏览器中刷新页面。祝你玩得开心。

<title> 元素也被以其他的方式使用着。比如说,如果你尝试为某个页面添加书签(在 Firefox 浏览器中,点击书签 > 将当前标签页添加到书签,或点击地址栏末尾的星标),你会看到 <title> 的内容被作为建议的书签名。

在 Firefox 浏览器中,一个网页被添加了书签;书签的名称已经自动填入了 'title' 元素的内容。

正如你即将在下面看到的那样,<title> 元素的内容也被用在搜索的结果中。

元数据:<meta> 元素

元数据就是描述数据的数据,而 HTML 有一个“官方的”方式来为一个文档添加元数据——<meta> 元素。当然,其他在这篇文章中提到的东西也可以被当作元数据。有很多不同种类的 <meta> 元素可以被包含进你的页面的 <head> 元素,但是现在我们还不会尝试去解释所有类型,这只会引起混乱。我们会解释一些你常会看到的类型,先让你有个概念。 

 指定文档中的字符编码

在上面的示例中,这行是被包含的:

<meta charset="utf-8" />

 这个元素简单的指定了文档的字符编码——在这个文档中被允许使用的字符集。utf-8 是一个通用的字符集,它包含了任何人类语言中的大部分的字符,意味着该 web 页面可以显示任意的语言;所以对于你的每一个页面都使用这个设置会是一个好主意!比如说,你的页面可以很好的处理英文和日文:

假如你将字符集设置为 ISO-8859-1(拉丁字母表的字符集),那么页面将出现乱码:

 备注: 一些浏览器(比如 Chrome)会自动修正错误的编码,所以根据你所使用的浏览器不同,你或许不会看到这个问题。无论如何,你仍然应该为你的页面手动设置编码为 utf-8,来避免在其他浏览器中可能出现的问题。

添加作者和描述

许多 <meta> 元素包含了 name 和 content 属性:

  • name 指定了 meta 元素的类型;说明该元素包含了什么类型的信息。
  • content 指定了实际的元数据内容。

这两个 meta 元素对于定义你的页面的作者和提供页面的简要描述是很有用的。让我们看一个例子:

<meta name="author" content="Chris Mills" />
<meta
  name="description"
  content="The MDN Web Docs Learning Area aims to provide
complete beginners to the Web with all they need to know to get
started with developing web sites and applications." />

指定作者在某些情况下是很有用的:如果你需要联系页面的作者,问一些关于页面内容的问题。一些内容管理系统能够自动获取页面作者的信息,然后用于某些用途。

指定一个包括与你的页面内容有关的关键词的描述是有用的,因为它有可能使你的页面在搜索引擎进行的相关搜索中出现得更多(这些行为在术语上被称为:搜索引擎优化 或 SEO)。

主动学习:在搜索引擎中 description 的使用

description 也被使用在搜索引擎显示的结果页中。下面通过一个例子来说明:

  1. 访问 MDN Web 文档的首页

  2. 查看网页源代码(通过鼠标右键点击网页在弹出的菜单中选择查看网页源代码)。

  3. 找到 description meta 标签。就和如下展示的这样(可能会时常改变):

    <meta
      name="description"
      content="The MDN Web Docs site
      provides information about Open Web technologies
      including HTML, CSS, and APIs for both Web sites and
      progressive web apps." />
    
  4. 现在,在你喜欢的搜索引擎里搜索“MDN Web Docs”(下图展示的是在谷歌搜索里的情况)。你会看到 description <meta> 和 <title> 元素如何在搜索结果里显示——很值得这样做哦!

备注: 在谷歌搜索里,在主页面链接下面,你将看到一些相关子页面——这些是站点链接,可以在 Google's webmaster tools 配置——这是一种可以使你的站点对搜索引擎更友好的方式。

备注: 许多 <meta> 特性已经不再使用。例如,keyword <meta> 元素(<meta name="keywords" content="fill, in, your, keywords, here">,为搜索引擎提供关键词,用于确定该页面与不同搜索词的相关性)已经被搜索引擎忽略了,因为作弊者填充了大量关键词到 keyword,错误地引导搜索结果。

 其他类型的元数据

当你在网站上查看源码时,你也会发现其他类型的元数据。你在网站上看到的许多功能都是专有创作,旨在向某些网站(如社交网站)提供可使用的特定信息。

例如,Facebook 编写的元数据协议 Open Graph Data 为网站提供了更丰富的元数据。在 MDN Web 文档源代码中,你会发现:

<meta
  property="og:image"
  content="https://developer.mozilla.org/mdn-social-share.png" />
<meta
  property="og:description"
  content="The Mozilla Developer Network (MDN) provides
information about Open Web technologies including HTML, CSS, and APIs for both Web sites
and HTML Apps." />
<meta property="og:title" content="Mozilla Developer Network" />

上面代码展现的一个效果就是,当你在 Facebook 上链接到 MDN Web 文档时,该链接将显示一个图像和描述:这为用户提供更丰富的体验。

Twitter 还拥有自己的类型的专有元数据协议(称为 Twitter Cards),当网站的 URL 显示在 twitter.com 上时,它具有相似的效果。例如下面:

<meta name="twitter:title" content="Mozilla Developer Network" />

在你的站点增加自定义图标

为了进一步丰富你的网站设计,你可以在元数据中添加对自定义图标的引用,它们会在某些场景下显示。最常见的用例为 favicon(为“favorites icon”的缩写,在浏览器的“收藏夹”及“书签”列表中显示)。

这个不起眼的图标已经存在很多年了,16 像素的方形图标是第一种类型。你可以看见(取决于浏览器)这些图标出现在浏览器每一个打开的标签页中以及书签面板中的书签页面旁边。

页面添加网页图标的方式有:

  1. 将其保存在与网站的索引页面相同的目录中,以 .ico 格式保存(大多数浏览器支持更通用的格式,如 .gif 或 .png

  2. 将以下行添加到 HTML 的 <head> 块中以引用它:

    <link rel="icon" href="favicon.ico" type="image/x-icon" />
    

下面是一个 favicon 出现在书签面板中的例子:

你可能还需要在不同的场景使用不同的图标。例如,你可以在 MDN Web 文档的源代码中找到它:

<link rel="icon" href="/favicon-48x48.[some hex hash].png" />
<link rel="apple-touch-icon" href="/apple-touch-icon.[some hex hash].png" />

这是一种使网站在保存到苹果设备主屏幕时显示图标的方法。你甚至可以为不同的设备提供不同的图标,以确保图标在所有设备上都看起来美观。例如:

<!-- 含有高分辨率 Retina 显示屏的 iPad Pro:-->
<link
  rel="apple-touch-icon"
  sizes="167x167"
  href="/apple-touch-icon-167x167.png" />
<!-- 三倍分辨率的 iPhone:-->
<link
  rel="apple-touch-icon"
  sizes="180x180"
  href="/apple-touch-icon-180x180.png" />
<!-- 没有 Retina 的 iPad、iPad mini 等:-->
<link
  rel="apple-touch-icon"
  sizes="152x152"
  href="/apple-touch-icon-152x152.png" />
<!-- 二倍分辨率的 iPhone 和其他设备:-->
<link rel="apple-touch-icon" href="/apple-touch-icon-120x120.png" />
<!-- 基本图标 -->
<link rel="icon" href="/favicon.ico" />

这些注释解释了每个图标的用途——这些元素涵盖的东西提供一个高分辨率图标,这些高分辨率图标当网站保存到 iPad 的主屏幕时使用。

不用担心现在实现所有这些类型的图标——这是一个相当先进的特性,不要求你有这方面的知识来通过课程的进展。这里的主要目的是让你提前了解有这一样东西,以防当你浏览其他网站的源代码时不理解源代码的含义。如果你确实想了解更多关于所有这些值以及如何选择它们,请阅读 <link> 元素的参考页面。

备注: 如果你的网站使用了内容安全策略(Content Security Policy,CSP)来增加安全性,这个策略会应用在 favicon 图标上。如果你遇到了图标没有被加载的问题,你需要确认 Content-Security-Policy 响应头的 img-src 指令 没有阻止访问图标。

在 HTML 中应用 CSS 和 JavaScript

如今,几乎你使用的所有网站都会使用 CSS 来让网页更加炫酷,并使用 JavaScript 来让网页有交互功能,比如视频播放器、地图、游戏以及更多功能。这些应用在网页中很常见,它们分别使用 <link> 元素以及 <script> 元素。 

  • <link> 元素经常位于文档的头部,它有 2 个属性,rel="stylesheet" 表明这是文档的样式表,而 href 包含了样式表文件的路径:

    <link rel="stylesheet" href="my-css-file.css" />
    
  • <script> 元素也应当放在文档的头部,并包含 src 属性来指向需要加载的 JavaScript 文件路径,同时最好加上 defer 以告诉浏览器在解析完成 HTML 后再加载 JavaScript。这样可以确保在加载脚本之前浏览器已经解析了所有的 HTML 内容。这样你就不会因为 JavaScript 试图访问页面上不存在的 HTML 元素而产生错误。实际上有很多方法来处理在你的页面上加载 JavaScript,但对于现代浏览器来说,这是最可靠的方法(对于其他方法,请阅读脚本加载策略)。

    <script src="my-js-file.js" defer></script>
    

 备注: <script> 元素看起来像一个空元素,但它并不是,因此需要一个结束标记。还可以选择将脚本放入 <script> 元素中,而不是指向外部脚本文件。

主动学习:在网页中应用 CSS 和 JavaScript

  1. 开始操作之前,先拷贝我们的 meta-example.htmlscript.js 和 style.css 文件,并把它们保存到本地电脑的同一目录下,确保使用了正确的文件名和文件格式。
  2. 使用浏览器和文字编辑器同时打开你的 HTML 文件。
  3. 根据上面的信息,添加 <link> 和 <script> 元素到你的 HTML 文件中,这样你的 HTML 就可以应用 CSS 和 JavaScript 了。

如果按照上述步骤正确地执行,当你保存 HTML 文件并重新刷新浏览器的话,你会发现页面已经变样了:

  • JavaScript 在页面中添加了一个空列表。现在当你点击列表中的任何地方,浏览器会弹出一个对话框要求你为新列表项输入一些文本内容。当你点击 OK 按钮,刚刚那个新的列表项会添加到页面上;当你点击那些已有的列表项,会弹出一个对话框允许你修改列表项的文本。
  • CSS 使页面背景变成了绿色,文本变得大了一点。它还将 JavaScript 添加到页面中的一些内容进行了样式化。(带有黑色边框的红色条是 CSS 添加到 JavaScript 生成的列表中的样式)

 备注: 如果你卡在这个练习当中,无法正常应用 CSS 和 JavaScript,试着查看一下我们的 css-and-js.html 页面实例。

为文档设定主语言

最后,值得一提的是可以(而且有必要)为站点设定语言,这个可以通过添加 lang 属性到 HTML 开始的标签中来实现(就像 meta-example.html 那样),如下所示:

<html lang="zh-CN">
  …
</html>

这在很多方面都很有用。如果你的 HTML 文档的语言设置好了,那么你的 HTML 文档就会被搜索引擎更有效地索引(例如,允许它在特定于语言的结果中正确显示),对于那些使用屏幕阅读器的视障人士也很有用(例如,法语和英语中都有“six”这个单词,但是发音却完全不同)。

你还可以将文档的分段设置为不同的语言。例如,我们可以把日语部分设置为日语,如下所示:

<p>Japanese example: <span lang="ja">ご飯が熱い。</span>.</p>

这些代码是根据 ISO 639-1 标准定义的。你可以在 HTML 和 XML 的语言标签找到更多相关内容。

总结

已经到了我们快速学习 HTML 头部的尾声——你还能学到更多的相关的,但是现阶段详尽的讲的太多会令人无聊且困惑,我们只希望你现在在这学到最基本的概念!下一篇我们将要学习 HTML 文字处理基础

 
HTML 的标题和段落

HTML 的主要工作之一是赋予文本结构,使浏览器能够按照开发者的意图显示 HTML 文档。本文介绍了如何使用 HTML 通过定义标题和段落来提供基本的页面结构。 

前提: 基本熟悉了基本 HTML 语法中所涵盖的内容。
学习成果:
  • 如何创建包含标题和标题下内容的良好文档结构。
  • 使用语义 HTML 而不是表现 HTML,以及为什么这很重要。
  • 需要合理地使用标题级别,即不能跳过级别,也不能因为要达到某种字体大小而随意使用级别(这是 CSS 的工作)。
  • 搜索引擎优化优势:例如,标题中的关键词会得到加强。
  • 无障碍优势:屏幕阅读器等辅助技术(AT)使用标题(和其他地标)作为导航内容的路标。如果没有标题,辅助技术用户很难使用 HTML 文档。

标题和段落

 无论是阅读故事、报纸、大学教科书还是杂志等,大多数结构化文本都由标题和段落组成。

 结构化内容会使读者的阅读体验更轻松,更愉快。

在 HTML 中,每个段落是通过 <p> 元素进行定义的,比如下面这样: 

<p>我是一个段落,千真万确。</p>

每个标题都必须被包裹在一个标题元素中:

<h1>我是文章的标题</h1>

 一共有六种标题元素标签——h1h2h3h4h5 和 h6。每个元素代表文档中不同级别的内容:<h1> 表示主标题,<h2> 表示二级子标题,<h3> 表示三级子标题,依此类推。

实现结构层级

举个例子,在一个故事中,<h1> 表示故事的标题,<h2> 表示每个章节的标题,<h3> 表示每个章节下的子标题,以此类推。

<h1>三国演义</h1>

<p>罗贯中</p>

<h2>第一回 宴桃园豪杰三结义 斩黄巾英雄首立功</h2>

<p>
  话说天下大势,分久必合,合久必分。周末七国分争,并入于秦。及秦灭之后,楚、汉分争,又并入于汉……
</p>

<h2>第二回 张翼德怒鞭督邮 何国舅谋诛宦竖</h2>

<p>
  且说董卓字仲颖,陇西临洮人也,官拜河东太守,自来骄傲。当日怠慢了玄德,张飞性发,便欲杀之……
</p>

<h3>却说张飞</h3>

<p>
  却说张飞饮了数杯闷酒,乘马从馆驿前过,见五六十个老人,皆在门前痛哭。飞问其故,众老人答曰:“督邮逼勒县吏,欲害刘公;我等皆来苦告,不得放入,反遭把门人赶打!”……
</p>

所涉及的元素具体代表什么,完全取决于作者编辑的内容,只要层次结构是合理的。在创建此类结构时,只需要记住一些最佳实践:

  • 最好只对每个页面使用一次 <h1>——这是顶级标题,所有其他标题位于层次结构中的下方。
  • 请确保在层次结构中以正确的顺序使用标题。不要使用 <h3> 来表示副标题,后面再跟 <h2> 来表示二级副标题——这是没有意义的,会导致奇怪的结果。
  • 在现有的六个标题层次中,除非觉得有必要,否则应该争取每页使用不超过三个。有很多层次的文件(例如,深层次的标题层次)会变得笨重,难以浏览。在这种情况下,如果可能的话,建议将内容分散到多个页面。

为什么我们需要结构化?

回答这个问题前,让我们先来看一段文档示例——并从运行这段文档示例(美味的豆沙食谱)开始。你应该在本地机器上保存一份这个文件的副本,因为在以后的练习中会需要它。这个文件的主体目前包含了多条内容。它们没有任何标记,但都用换行符隔开(按回车键进入下一行)。

然而,当在浏览器中打开文档时,会看到文本显示为一整块!

 

这是因为没有元素给内容结构,所以浏览器不知道什么是标题,什么是段落。此外:

  • 用户在阅读网页时,往往会快速浏览以查找相关内容,经常只是阅读开头的标题(我们通常在一个网页上会花费很少的时间)。如果用户不能在几秒内看到一些有用的内容,他们很可能会感到沮丧并离开。
  • 对网页建立索引的搜索引擎将标题的内容视为影响网页搜索排名的重要关键字。没有标题,你的网页在搜索引擎优化方面效果不佳。
  • 严重视力障碍者通常不会阅读网页;他们用听力来代替。完成这项工作的软件叫做屏幕阅读器。该软件提供了快速访问给定文本内容的方法。在使用的各种技术中,它们通过朗读标题来提供文档的概述,让用户能快速找到他们需要的信息。如果标题不可用,用户将不得不听到整个文档被大声朗读。
  • 使用 CSS 样式化内容,或者使用 JavaScript 做一些有趣的事情,你需要包含相关内容的元素,使得 CSS / JavaScript 可以有效地定位它。

因此,我们需要给我们的内容进行结构性标记。

主动学习:为我们的内容赋予结构

为什么我们需要语义?

在我们身边的任何地方都要依赖语义——我们依靠以前的经验来告诉我们一个日常物品的功能是什么;当我们看到某个东西时,我们知道它的功能是什么。举个例子,我们知道红色交通灯表示“停止”,绿色交通灯表示“通行”。如果运用了错误的语义,事情会迅速地变得非常棘手(难道有某个国家使用红色代表通行?我不希望如此)

同样的道理,我们需要确保使用了正确的元素来给予内容正确的含义、作用以及外形。在这里,h1 元素也是一个语义元素,它所包裹的文本具有“页面上的顶级标题”的作用(或意义)。

<h1>这是一个顶级标题</h1>

一般来说,浏览器会给它一个更大的字形来让它看上去像个标题(虽然也可以使用 CSS 让它变成任何你想要的样式)。更重要的是,它的语义值将以多种方式被使用,比如通过上文提到过的搜索引擎和屏幕阅读器。

在另一方面,你可以让任一元素看起来像一个顶级标题,考虑如下:

<span style="font-size: 32px; margin: 21px 0; display: block;"
  >这是顶级标题吗?</span
>

这是一个 <span> 元素,它没有语义。当想要对它用 CSS(或者 JavaScript)时,可以用它包裹内容,且不附加任何额外的意义(在未来的课程中你会发现更多这类元素)。我们已经对它使用了 CSS 来让它看起来像一个顶级标题。然而,由于它没有语义值,所以它不会有任何上文提到的帮助。最好的方法是使用相关的 HTML 元素来标记这个项目。

总结

关于 HTML 标题和段落的学习到此结束。接下来,我们将探讨语义 HTML 的更多方面:给予词语强调。

强调与重要性 

上一篇文章探讨了语义在 HTML 中的重要性,重点是标题和段落。本文将继续以语义为主题,探讨对文本进行强调和重要性处理的 HTML 元素(与印刷媒体中的斜体和粗体文字类似)。 

前提: 基本熟悉了基本 HTML 语法中所涵盖的内容。
学习成果:
  • 强调和着重强调的含义,以及在 HTML 中应用它们的基本元素,如 <em> 和 <strong>
  • 识别根本不应再使用的呈现性标记(例如 <big> 和 <font>),它们已经被弃用。
  • 识别被重新利用以获得新语义的呈现性标记(例如 <i> 和 <b>)。

什么是强调和着重强调?

 在日常用语中,我们常常会加重某个字的读音,或者用加粗等方式突出某句话的重点。与此类似,HTML 也提供了相应的标签,用于标记某些文本,使其具有加粗、倾斜、下划线等效果。下面,我们将学习一些最常见的标签。

强调

在口语表达中,我们有时会强调某些字,用来改变这句话的意思。同样地,在书面用语中,我们可以使用斜体字来达到同样的效果。例如,下面两个句子便有不同的意思:

我很庆幸你没有迟到。

我很庆幸你没有迟到

 第一句话听起来真的像松了一口气——因为没有迟到。相反,第二句话因为以斜体强调了“庆幸”和“迟到”两词,听起来具有讽刺性而且有隐含的攻击性,表达对一个人迟到的恼怒。

在 HTML 中我们用 <em>(emphasis)元素来标记这样的情况。这样做既可以让文档读起来更有趣,也可以被屏幕阅读器识别,并以不同的语调发出。浏览器默认样式为斜体,但你不应该纯粹为了获得斜体风格而使用这个标签。如果仅仅为了获得斜体样式而不增加语义辅助,你应该使用 <span> 元素和一些 CSS,或者是 <i> 元素(见下文)。 

<p>我很<em>庆幸</em>你没有<em>迟到</em>。</p>

着重强调

为了强调重要的词,在口语方面我们往往用重音强调,在书面用语中则是用粗体字来达到强调的效果。例如下面这段:

这杯液体毒性很大

就指望你了,千万不要迟到!

在 HTML 中我们用 <strong>(strong importance)元素来标记这样的情况。除了使文档更有用之外,屏幕阅读器也能识别这些内容,并可将其配置为以不同的语音语调进行朗读。浏览器默认样式为粗体,但你不应该纯粹为了获得粗体风格而使用这个标签。如果仅仅为了获得粗体样式而不增加语义辅助,你应该使用 <span> 元素和一些 CSS,或者是 <b> 元素(见下文)。 

<p>这杯液体<strong>毒性很大</strong>。</p>

<p>就指望你了,千万<strong>不要</strong>迟到!</p>

 如有需要,你可以将 strong 元素和 em 元素相互嵌套:

<p>
  这杯液体<strong>毒性很大</strong>——如果饮用了它,你<strong>可能<em>会死</em></strong>。
</p>

主动学习:我们是重要的!

在这个主动学习部分,我们提供了一个可编辑的示例。在这个示例中,我们希望你能尝试在你认为需要斜体强调和着重强调的词上添加斜体强调和着重强调的内容,只是为了进行一些练习。

斜体、粗体、下划线……

到目前为止,我们所讨论的元素都有明确的相关语义。<b><i> 和 <u> 的情况却有点复杂。它们出现于人们要在文本中使用粗体、斜体、下划线但 CSS 仍然不被完全支持的时期。像这样仅仅影响表象而且没有语义的元素,被称为表现元素(presentational element)并且不应该再被使用。因为正如我们在之前看到的,语义对无障碍、搜索引擎优化(SEO)等非常重要。

HTML5 重新定义了 <b><i> 和 <u>,赋予了它们新的但有点令人困惑的语义角色。

最好的经验法则是:只有在没有更合适的元素时,才适合使用 <b><i> 或 <u> 来表达传统上用粗体、斜体或下划线表达的意思;而通常情况下是有更合适的元素可供使用的。<strong><em><mark> 或 <span> 可能是更加合适的选择。

始终保持无障碍的开发理念。斜体的概念对使用屏幕阅读器的人或使用拉丁字母以外的书写系统的人没有什么帮助。

  • <i> 被用来传达传统上用斜体表达的意义:外国文字、分类名称、技术术语、思想……
  • <b> 被用来传达传统上用粗体表达的意义:关键字、产品名称、引导句……
  • <u> 被用来传达传统上用下划线表达的意义:专有名词、拼写错误……

备注: 人们强烈地将下划线与超链接联系起来。因此,在网页中,最好只给链接加下划线。在语义上合适的时候使用 <u> 元素,但要考虑使用 CSS 将默认的下划线改为在网页中更合适的东西。下面的例子说明了如何做到这一点: 

<!-- 学名 -->
<p>
  红喉北蜂鸟(学名:<i>Archilocus colubris</i>)是北美东部最常见的蜂鸟品种。
</p>

<!-- 舶来词 -->
<p>
  菜单上有好多舶来词汇,比如 <i lang="uk-latn">vatrushka</i>(东欧乳酪面包)、<i
    lang="id"
    >nasi goreng</i
  >(印尼炒饭)以及 <i lang="fr">soupe à l'oignon</i>(法式洋葱汤)。
</p>

<!-- 已知的错误书写 -->
<p>总有一天我会改掉写<u class="spelling-error">措字</u>的毛病。</p>

<!-- 在定义中,被定义的术语 -->
<dl>
  <dt>语义化 HTML</dt>
  <dd>根据元素的<b>语义</b>意义而不是外观来使用它们。</dd>
</dl>

 

总结

强调和重要性的讨论暂时告一段落。下面我们来看看如何在 HTML 中表示列表。

列表 

现在,让我们把目光转向列表。列表在生活中无处不在——从你的购物清单,到你每天回家时下意识遵循的方向列表,再到你在这些教程中遵循的说明列表!HTML 有一套方便的元素,可以让我们定义不同类型的列表,这一点你可能不会感到惊讶。在 Web 中,我们有三种类型的列表:无序列表、有序列表和描述列表。本课将向你展示如何使用不同类型的列表。 

前提: 基本熟悉了基本 HTML 语法中所涵盖的内容。
学习成果:
  • 三种类型的列表的 HTML 结构——无序列表、有序列表和描述列表。
  • 每种列表类型的正确使用方法。
  • 列表的更广泛用途,如导航菜单。

无序列表

无序列表用于标记列表项目顺序无关紧要的列表——让我们以购物清单为例。

每份无序的清单从 <ul> 元素开始,需要包裹清单上所有被列出的项目: 

<ul>
  豆浆
  油条
  豆汁
  焦圈
</ul>

 然后就是用 <li>(list item,列表项)元素把每个列出的项目单独包裹起来:

<ul>
  <li>豆浆</li>
  <li>油条</li>
  <li>豆汁</li>
  <li>焦圈</li>
</ul>

 

有序列表

有序列表需要按照项目的顺序列出来——让我们以一组方向指示为例:

这个标记的结构和无序列表一样,除了需要用 <ol> 元素而不是 <ul> 元素将所有项目包裹: 

<ol>
  <li>沿这条路走到头</li>
  <li>右转</li>
  <li>直行穿过第一个十字路口</li>
  <li>在第三个十字路口处左转</li>
  <li>继续走 300 米,学校就在你的右手边</li>
</ol>

 

主动学习:标记我们的食谱

<h1>宫保鸡丁的做法</h1>
<p>宫保鸡丁,川菜系中的传统名菜,由鸡丁、干辣椒、花生米等炒制而成。由于其入口鲜辣,鸡肉的鲜嫩配合花生的香脆,广受大众欢迎。</p>
<p>相传宫保鸡丁是清朝光绪年间的署理四川总督丁宝桢所发明,是他招待客人时叫家厨煮的菜肴。由于丁宝桢后来被封为东宫少保(太子少保),所以被称为“丁宫保”,而这道菜亦被称为“宫保鸡丁”</p>

<h2>原料</h2>
<ul>
  <li>去骨鸡胸肉:一斤八两</li>
  <li>干红辣椒:八钱</li>
  <li>炸花生米:一两五钱</li>
  <li>花椒粒:两大匙</li>
  <li>葱:两根(切段)</li>
  <li>蛋白:一个</li>
  <li>淀粉:三大匙</li>
  <li>酱油:两大匙</li>
  <li>蒜末:半茶匙</li>
  <li>糖:半茶匙</li>
  <li>白醋:一茶匙</li>
  <li>色拉油:适量</li>
  <li>盐:两茶匙</li>
</ul>

<h2>做法</h2>
<ol>
  <li>先用蛋白一个、盐半茶匙及淀粉两大匙搅拌均匀,调成“腌料”,鸡胸肉切成约一厘米见方的碎丁并用“腌料”搅拌均匀,腌渍半小时。</li>
  <li>用酱油一大匙、淀粉水一大匙、糖半茶匙、盐四分之一茶匙、白醋一茶匙、蒜末半茶匙调拌均匀,调成“综合调味料”。</li>
  <li>鸡丁腌好以后,色拉油下锅烧热,先将鸡丁倒入锅内,用大火快炸半分钟,炸到变色之后,捞出来沥干油汁备用。</li>
  <li>在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。</li>
  <li>如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。</li>
  <li>如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。</li>
</ol>

<h2>大千鸡</h2>
<p>张大千居加拿大期间,曾按自己喜好改变宫保鸡丁的做法,并传授当地厨师,厨师将之命名为“大千鸡”,以兹纪念。大千鸡与宫保鸡丁不同之处,是使用经细工去皮、出骨、剔膜的鸡腿肉,以干辣椒、豆瓣酱为味,而且不用花生。</p>

 

嵌套列表

将一个列表嵌入到另一个列表是完全可以的。你可能想让一些子项目列在一级项目之下。让我们从食谱示例中获取第二个列表:

<ol>
  <li>
    先用蛋白一个、盐半茶匙及淀粉两大匙搅拌均匀,调成“腌料”,鸡胸肉切成约一厘米见方的碎丁并用“腌料”搅拌均匀,腌渍半小时。
  </li>
  <li>
    用酱油一大匙、淀粉水一大匙、糖半茶匙、盐四分之一茶匙、白醋一茶匙、蒜末半茶匙调拌均匀,调成“综合调味料”。
  </li>
  <li>
    鸡丁腌好以后,色拉油下锅烧热,先将鸡丁倒入锅内,用大火快炸半分钟,炸到变色之后,捞出来沥干油汁备用。
  </li>
  <li>
    在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。
  </li>
  <li>如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。</li>
  <li>如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。</li>
</ol>

 由于最后两项与它们的前一项非常密切相关(它们看起来更像该项的子项或选项),将它们编辑成无序列表,并嵌套在该项的子项中可能更合理。就像下面这样:

<ol>
  <li>
    先用蛋白一个、盐半茶匙及淀粉两大匙搅拌均匀,调成“腌料”,鸡胸肉切成约一厘米见方的碎丁并用“腌料”搅拌均匀,腌渍半小时。
  </li>
  <li>
    用酱油一大匙、淀粉水一大匙、糖半茶匙、盐四分之一茶匙、白醋一茶匙、蒜末半茶匙调拌均匀,调成“综合调味料”。
  </li>
  <li>
    鸡丁腌好以后,色拉油下锅烧热,先将鸡丁倒入锅内,用大火快炸半分钟,炸到变色之后,捞出来沥干油汁备用。
  </li>
  <li>
    在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。
    <ul>
      <li>
        如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。
      </li>
      <li>如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。</li>
    </ul>
  </li>
</ol>

 

描述列表

 描述列表的目的是标记一组项目及其相关描述,如术语和定义或问题和答案。让我们来看一组术语和定义的示例:

 描述列表使用与其他列表类型不同的包裹标签——<dl>;此外,每一项都用 <dt>(description term,描述术语)元素包裹。每个描述都用 <dd>(description definition,描述定义)元素包裹。

描述列表示例

让我们来完成下面的标记例子:

<dl>
  <dt>内心独白</dt>
  <dd>
    戏剧中,某个角色对自己的内心活动或感受进行念白表演,这些台词只面向观众,而其他角色不会听到。
  </dd>
  <dt>语言独白</dt>
  <dd>
    戏剧中,某个角色把自己的想法直接进行念白表演,观众和其他角色都可以听到。
  </dd>
  <dt>旁白</dt>
  <dd>
    戏剧中,为渲染幽默或戏剧性效果而进行的场景之外的补充注释念白,只面向观众,内容一般都是角色的感受、想法、以及一些背景信息等。
  </dd>
</dl>

 浏览器的默认样式会在描述列表的术语及其定义之间产生缩进。

 单个术语的多个描述

请注意,一个术语可以同时有多个描述,例如: 

<dl>
  <dt>旁白</dt>
  <dd>
    戏剧中,为渲染幽默或戏剧性效果而进行的场景之外的补充注释念白,只面向观众,内容一般都是角色的感受、想法、以及一些背景信息等。
  </dd>
  <dd>
    写作中,指与当前主题相关的一段内容,通常不适于直接置于内容主线中,因此置于附近的其他位置(通常位于主线内容旁边一个文本框内)。
  </dd>
</dl>

技能测试!

关于 HTML 基本语义元素的三篇文章已经读完,但你还记得最重要的信息吗?你可以找到一些进一步的测试,以验证你在继续前进之前已经保留了这些信息——参见技能测试:HTML 文本基础知识

总结

列表就到此为止。接下来我们将进行更高层次的讨论。我们已经展示了如何实现一些单个页面的功能,但如何构建整个 HTML 页面呢?接下来将讨论文档结构。

文档与网站架构 

HTML 不仅能够定义网页的单独部分(例如“段落”或“图片”),还可以使用块级元素(例如“标题栏”、“导航菜单”、“主内容列”)来定义网站中的复合区域。本文将探讨如何规划基本的网站结构,并根据规划的结构来编写 HTML。

前提: 阅读 开始学习 HTMLHTML 文字处理初步 、创建超链接,掌握相关基础知识。
学习目标: 会用语义标签来构建文档,会搭建简单的网站结构。

 文档的基本组成部分

网页的外观多种多样,但是除了全屏视频或游戏,或艺术作品页面,或只是结构不当的页面以外,都倾向于使用类似的标准组件: 

页眉

通常横跨于整个页面顶部有一个大标题 和/或 一个标志。这是网站的主要一般信息,通常存在于所有网页。

导航栏

指向网站各个主要区段的超链接。通常用菜单按钮、链接或标签页表示。类似于标题栏,导航栏通常应在所有网页之间保持一致,否则会让用户感到疑惑,甚至无所适从。许多 web 设计人员认为导航栏是标题栏的一部分,而不是独立的组件,但这并非绝对;还有人认为,两者独立可以提供更好的 无障碍访问特性,因为屏幕阅读器可以更清晰地分辨二者。

主内容

中心的大部分区域是当前网页大多数的独有内容,例如视频、文章、地图、新闻等。这些内容是网站的一部分,且会因页面而异。

侧边栏

一些外围信息、链接、引用、广告等。通常与主内容相关(例如一个新闻页面上,侧边栏可能包含作者信息或相关文章链接),还可能存在其他的重复元素,如辅助导航系统。

页脚

横跨页面底部的狭长区域。和标题一样,页脚是放置公共信息(比如版权声明或联系方式)的,一般使用较小字体,且通常为次要内容。还可以通过提供快速访问链接来进行 SEO

一个“典型的网站”可能会这样布局:

 以上简单示例不是很精美,但是足够说明网站的典型布局方式了。一些站点拥有更多列,其中一些远比这复杂,但一切在你掌握之中。通过合适的 CSS,你可以使用相当多种的任意页面元素来环绕在不同的页面区域来做成你想要的样子,但如前所述,我们要敬畏语义,做到正确选用元素

这是因为视觉效果并不是一切。我们可以修改最重要内容(例如导航菜单和相关链接)的颜色、字体大小来吸引用户的注意,但是这对视障人士是无效的,“粉红色”和“大字体”对他们并不奏效。 

备注: 全球色盲患者比例为 4%,换句话说,每 12 名男性就有一位色盲,每 200 名女性就有一位色盲。全盲和视障人士约占世界人口(约 70 亿)的 13%(2015 年 全球约有 9.4 亿人口存在视力问题)。 

HTML 代码中可根据功能来为区段添加标记。可使用元素来无歧义地表示上文所讲的内容区段,屏幕阅读器等辅助技术可以识别这些元素,并帮助执行“找到主导航“或”找到主内容“等任务。参见前文所讲的页面中元素结构和语义不佳所带来的后果。 

为了实现语义化标记,HTML 提供了明确这些区段的专用标签,例如:

主动学习:研究示例代码

上图的示例可用下面的代码表示(完整代码请参见 GitHub),请结合图片观察代码,并找出代码中可见的区段:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>二次元俱乐部</title>
    <link
      href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Sonsie+One"
      rel="stylesheet" />
    <link
      href="https://fonts.googleapis.com/css?family=ZCOOL+KuaiLe"
      rel="stylesheet" />
    <link href="style.css" rel="stylesheet" />
  </head>

  <body>
    <header>
      <!-- 本站所有网页的统一主标题 -->
      <h1>聆听电子天籁之音</h1>
    </header>

    <nav>
      <!-- 本站统一的导航栏 -->
      <ul>
        <li><a href="#">主页</a></li>
        <!-- 共 n 个导航栏项目,省略…… -->
      </ul>

      <form>
        <!-- 搜索栏是站点内导航的一个非线性的方式。 -->
        <input type="search" name="q" placeholder="要搜索的内容" />
        <input type="submit" value="搜索" />
      </form>
    </nav>

    <main>
      <!-- 网页主体内容 -->
      <article>
        <!-- 此处包含一个 article(一篇文章),内容略…… -->
      </article>

      <aside>
        <!-- 侧边栏在主内容右侧 -->
        <h2>相关链接</h2>
        <ul>
          <li><a href="#">这是一个超链接</a></li>
          <!-- 侧边栏有 n 个超链接,略略略…… -->
        </ul>
      </aside>
    </main>

    <footer>
      <!-- 本站所有网页的统一页脚 -->
      <p>© 2050 某某保留所有权利</p>
    </footer>
  </body>
</html>

 请花一些时间来阅读,其中的注释应该能够帮助你理解这些代码。现在能够理解上面的代码就可以,因为编写一套正确的 HTML 结构是理解文档布局的前提,布局工作就交给 CSS 吧。在学习 CSS 一章时我们再展开介绍



HTML 布局元素细节

理解所有 HTML 区段元素具体含义是很有益处的,这一点将随着个人 web 开发经验的逐渐丰富日趋显现。更多细节请查阅 HTML 元素参考。现在,你只需要理解以下主要元素的意义:

  • <main> 存放每个页面独有的内容。每个页面上只能用一次 <main>,且直接位于 <body> 中。最好不要把它嵌套进其他元素。
  • <article> 包围的内容即一篇文章,与页面其他部分无关(比如一篇博文)。
  • <section> 与 <article> 类似,但 <section> 更适用于组织页面使其按功能(比如迷你地图、一组文章标题和摘要)分块。一般的最佳用法是:以 标题 作为开头;也可以把一篇 <article> 分成若干部分并分别置于不同的 <section> 中,也可以把一个区段 <section> 分成若干部分并分别置于不同的 <article> 中,取决于上下文。
  • <aside> 包含一些间接信息(术语条目、作者简介、相关链接,等等)。
  • <header> 是简介形式的内容。如果它是 <body> 的子元素,那么就是网站的全局页眉。如果它是 <article> 或<section> 的子元素,那么它是这些部分特有的页眉(此 <header> 非彼标题)。
  • <nav> 包含页面主导航功能。其中不应包含二级链接等内容。
  • <footer> 包含了页面的页脚部分。

无语义元素

有时你会发现,对于一些要组织的项目或要包装的内容,现有的语义元素均不能很好对应。有时候你可能只想将一组元素作为一个单独的实体来修饰来响应单一的用 CSS 或 JavaScript。为了应对这种情况,HTML 提供了 <div> 和 <span> 元素。应配合使用 class 属性提供一些标签,使这些元素能易于查询。

<span> 是一个内联的(inline)无语义元素,最好只用于无法找到更好的语义元素来包含内容时,或者不想增加特定的含义时。例如:

<p>
  国王喝得酩酊大醉,在凌晨 1 点时才回到自己的房间,踉跄地走过门口。<span
    class="editor-note"
    >[编辑批注:此刻舞台灯光应变暗]</span
  >.
</p>

这里,“编辑批注”仅仅是对舞台剧导演提供额外指引;没有具体语义。对于视力正常的用户,CSS 应将批注内容与主内容稍微隔开一些。 

<div> 是一个块级无语义元素,应仅用于找不到更好的块级元素时,或者不想增加特定的意义时。例如,一个电子商务网站页面上有一个一直显示的购物车组件。 

<div class="shopping-cart">
  <h2>购物车</h2>
  <ul>
    <li>
      <p>
        <a href=""><strong>银耳环</strong></a
        >:$99.95.
      </p>
      <img src="../products/3333-0985/" alt="Silver earrings" />
    </li>
    <li>...</li>
  </ul>
  <p>售价:$237.89</p>
</div>

 这里不应使用 <aside>,因为它和主内容并没有必要的联系(你想在任何地方都能看到它)。甚至不能用 <section> ,因为它也不是页面上主内容的一部分。所以在这种情况下就应使用 <div>,为满足无障碍使用特征,还应为购物车的标题设置一个可读标签。

 警告: div 元素非常便利但容易被滥用。由于它们没有语义值,会使 HTML 代码变得混乱。要小心使用,只有在没有更好的语义方案时才选择它,而且要尽可能少用,否则文档的升级和维护工作会非常困难。

 换行与水平分割线

有时会用到 <br> 和 <hr> 两个元素,需要介绍一下。

<br>:换行元素

<br> 可在段落中进行换行;<br> 是唯一能够生成多个短行结构(例如邮寄地址或诗歌)的元素。比如:

<p>
  从前有个人叫小高<br />
  他说写 HTML 感觉最好<br />
  但他写的代码结构语义一团糟<br />
  他写的标签谁也懂不了。
</p>

 没有 <br> 元素,这段会直接显示在长长的一行中(如前文所讲,HTML 会忽略大部分空格);使用 <br> 元素,才使得诗看上去像诗:

<hr>:主题性中断元素

<hr> 元素在文档中生成一条水平分割线,表示文本中主题的变化(例如话题或场景的改变)。一般就是一条水平的直线。例如:

<p>
  原来这唐僧是个慈悯的圣僧。他见行者哀告,却也回心转意道:“既如此说,且饶你这一次。再休无礼。如若仍前作恶,这咒语颠倒就念二十遍!”行者道:“三十遍也由你,只是我不打人了。”却才伏侍唐僧上马,又将摘来桃子奉上。唐僧在马上也吃了几个,权且充饥。
</p>
<hr />
<p>
  却说那妖精,脱命升空。原来行者那一棒不曾打杀妖精,妖精出神去了。他在那云端里,咬牙切齿,暗恨行者道:“几年只闻得讲他手段,今日果然话不虚传。那唐僧已此不认得我,将要吃饭。若低头闻一闻儿,我就一把捞住,却不是我的人了。不期被他走来,弄破我这勾当,又几乎被他打了一棒。若饶了这个和尚,诚然是劳而无功也。我还下去戏他一戏。”
</p>

 将渲染成:

规划一个简单的网站

在完成页面内容的规划后,一般应按部就班地规划整个网站的内容,要可能带给用户最好的体验,需要哪些页面、如何排列组合这些页面、如何互相链接等问题不可忽略。这些工作称为信息架构。在大型网站中,大多数规划工作都可以归结于此,而对于一个只有几个页面的简单网站,规划设计过程可以更简单,更有趣!

    1. 时刻记住,大多数(不是全部)页面会使用一些相同的元素,例如导航菜单以及页脚内容。若网站为商业站点,不妨在所有页面的页脚都加上联系方式。请记录这些对所有页面都通用的内容:接下来,可为页面结构绘制草图(这里与前文那个站点页面的截图类似)。记录每一块的作用:
    2. 下面,对于期望添加进站点的所有其他(通用内容以外的)内容展开头脑风暴,直接罗列出来。
    3. 下一步,试着对这些内容进行分组,这样可以让你了解哪些内容可以放在同一个页面。这种做法和 卡片分类法 非常相似。
    4. 接下来,试着绘制一个站点地图的草图,使用一个气泡代表网站的一个页面,并绘制连线来表示页面间的一般工作流。主页面一般置于中心,且链接到其他大多数页面;小型网站的大多数页面都可以从主页的导航栏中链接跳转。也可记录下内容的显示方式。

    主动学习:创建站点地图

    自己创造一个网站(什么网站呢?)并尝试执行上述步骤。

    备注: 记得保存你的杰作,今后可能会用到哦。

    小结

    现在你应该对如何构建网页/站点有了更好的理解。下一节我们将学习如何调试 HTML。

    参见

    文本格式进阶

    HTML 中有许多可以用于定义文本语义的其他元素,我们没有在强调和重要性中提到它们。本文中所介绍的元素虽然少有人知,但仍然值得去学习(而且本文不是一份完整的列表)。在这里你将学习标记引用、描述列表、计算机代码和其他相关文本、下标和上标、联系信息等。 

    前提: 熟悉 HTML 基础,如基础 HTML 语法所述。文本级语义,例如标题和段落列表
    学习成果:
    • 引用。
    • 缩写和首字母缩略词。
    • 地址。
    • 时间和日期。
    • 上标和下标。

    引用

    HTML 也有用于标记引用的特性,至于使用哪个元素标记,取决于你引用的是一块还是一行。

    块引用

    如果其他地方引用一个块级内容(一个段落、多个段落、一个列表等),你应该把它用 <blockquote> 元素包裹起来表示,并且在 cite 属性里用 URL 来指向引用的资源。例如,下面的示例代码就是引用的 MDN 的 <blockquote> 元素页面:

    <p>
      <strong>HTML <code>&lt;blockquote&gt;</code> 元素</strong>(或<em
        >HTML 块级引用元素</em
      >)表示所附文本为扩展引用。
    </p>

    要把这些转换为块引用,我们要这样做:

    <p>这是块引用:</p>
    <blockquote
      cite="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/blockquote">
      <p>
        <strong>HTML <code>&lt;blockquote&gt;</code> 元素</strong>(或<em
          >HTML 块级引用元素</em
        >)表示所附文本为扩展引用。
      </p>
    </blockquote>

    浏览器的默认样式会将其渲染为缩进的段落,以表明这是一个引用;引用上面的段落是为了证明这一点。

    行内引用

    除了使用 <q> 元素以外,行内元素用同样的方式工作。例如,下面的标记包含了从 MDN <q> 页面的引用:

    <p>
      引用元素 <code>&lt;q&gt;</code> 是<q
        cite="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/q"
        >用于不需要段落分隔的短引用。</q
      >
    </p>

    浏览器默认将其作为普通文本放入引号内表示引用,就像下面:

    引文

    cite 属性的内容听起来很有用,但不幸的是,浏览器、屏幕阅读器并没有充分利用它。如果不使用 JavaScript 或 CSS 编写自己的解决方案,就没有办法让浏览器显示 cite 的内容。如果你想在页面上提供引文的来源,你需要在文本中通过链接或其他适当的方式来提供它。

    这里有 <cite> 元素,但它是为了包含所引用资源的标题(如书名)。然而,你没有理由不把 <cite> 内的文字以某种方式链接到引用源。

    <p>
      根据<a href="/zh-CN/docs/Web/HTML/Element/blockquote"><cite>MDN 块引用页</cite></a>:
    </p>
    
    <blockquote
      cite="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/blockquote">
      <p>
        <strong>HTML <code>&lt;blockquote&gt;</code> 元素</strong>(或<em>HTML 块级引用元素</em>)表示所附文本为扩展引用。
      </p>
    </blockquote>
    
    <p>
      引用元素 <code>&lt;q&gt;</code> 是<q cite="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/q">用于不需要段落分隔的短引用。</q>——<a href="/zh-CN/docs/Web/HTML/Element/q"> <cite>MDN q 页面</cite></a>
    </p>

     引文默认的字体样式为斜体。

    缩略语

    另一个你在 Web 上看到的相当常见的元素是 <abbr>——它常被用来包裹一个缩略语或缩写,并且提供缩写的解释。当包括这两种情况时,在第一次使用时提供纯文本的完整扩展,同时用 <abbr> 来标记缩写。这为用户代理提供了如何公布/显示内容的提示,同时告知所有用户该缩写的含义。

    如果为缩写提供扩展信息的意义不大,而且该缩写或首字母缩写是一个相当简短的术语,则应提供该术语的完整扩展,作为 title 属性的值:

    缩略语示例

    让我们一起看一个示例。

    <p>我们使用 <abbr>HTML</abbr> 超文本标记语言来组织网页文档。</p>
    
    <p>
      第 33 届<abbr title="夏季奥林匹克运动会">奥运会</abbr>已于 2024 年 7
      月在法国巴黎举行。
    </p>

     这些代码的显示效果如下:

    备注: 在之前版本的 html 中还包含对另一个元素 <acronym> 的支持,但是它已经从 HTML 标准中移除,因为可以只使用 <abbr> 元素代表缩略语。不应再使用 <acronym>。 

    标记联系方式

    HTML 有个用于标记联系方式的元素——<address>。它仅仅包含联系方式,例如:

    <address>Chris Mills, Manchester, The Grim North, UK</address>

     其中可以包含更复杂的标记和其他形式的联系方式,如:

    <address>
      <p>
        Chris Mills<br />
        Manchester<br />
        The Grim North<br />
        UK
      </p>
    
      <ul>
        <li>Tel: 01234 567 890</li>
        <li>Email: me@grim-north.co.uk</li>
      </ul>
    </address>

     注意,如果链接的页面包含了联系信息,像下面这样也是可以的:

    <address>
      由 <a href="../authors/chris-mills/">Chris Mills</a> 编写的页面。
    </address>

     备注: <address> 元素只能用于提供最近的 <article> 或 <body> 元素所含文件的联系信息。在一个网站的页脚使用它来包括整个网站的联系信息,或者在一篇文章里面使用它来包括作者的联系信息,这都是正确的,但不能用来标记与该页面内容无关的地址列表。

    上标和下标

    当你使用日期、化学方程式和数学方程式时会偶尔使用上标和下标,以确保它们的正确含义。<sup> 和 <sub> 元素可以解决这样的问题。例如:

    <p>我的生日是在 2021 年 5 月 25 日(译者注:英文原文为 25<sup>th</sup>)</p>
    <p>
      咖啡因的化学方程式是 C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>。
    </p>
    <p>如果 x<sup>2</sup> 的值为 9,那么 x 的值必为 3 或 -3。</p>

     这些代码输出的结果是:

    展示计算机代码

    有大量的 HTML 元素可以来标记计算机代码:

    • <code>:用于标记计算机通用代码。
    • <pre>:用于保留空白字符(通常用于代码块)——如果文本中使用了缩进或多余的空白,浏览器将忽略它,你将不会在渲染的页面上看到它。但是,如果你将文本包含在 <pre></pre> 标签中,那么空白将会以与你在文本编辑器中看到的相同的方式渲染出来。
    • <var>:用于标记具体变量名。
    • <kbd>:用于标记输入电脑的键盘(或其他类型)输入。
    • <samp>:用于标记计算机程序的输出。

    让我们看看这些元素的示例以及它们如何被用来表示计算机代码。如果你想要完整文件,可以看一下 other-semantics.html 这个示例文件。你可以下载文件并在浏览器打开查看,以下是代码的一个片段: 

    <pre><code>const para = document.querySelector('p');
    
    para.onclick = function() {
      alert('噢,噢,噢,别点我了。');
    }</code></pre>
    
    <p>
      请不要使用 <code>&lt;font&gt;</code> 、
      <code>&lt;center&gt;</code> 等表现元素。
    </p>
    
    <p>在上述的 JavaScript 示例中,<var>para</var> 表示一个段落元素。</p>
    
    <p>按 <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>A</kbd> 选择全部内容。</p>
    
    <pre>$ <kbd>ping mozilla.org</kbd>
    <samp>PING mozilla.org (63.245.215.20): 56 data bytes
    64 bytes from 63.245.215.20: icmp_seq=0 ttl=40 time=158.233 ms</samp></pre>

     上面的代码显示效果如下:

    标记时间和日期

    HTML 还支持将时间和日期标记为可供机器识别的格式的 <time> 元素,例如:

    <time datetime="2016-01-20">2016 年 1 月 20 日</time>

    为什么需要这样做?因为世界上有许多种书写日期的格式,上边的日期可能被写成:

    • 20 January 2016
    • 20th January 2016
    • Jan 20 2016
    • 20/06/16
    • 06/20/16
    • The 20th of next month
    • 20e Janvier 2016
    • 2016 年 1 月 20 日
    • 等等

    但是这些不同的格式不容易被电脑识别——假如你想自动抓取页面上所有事件的日期并将它们插入到日历中,<time> 元素允许你附上清晰的、可被机器识别的时间或日期来实现这种需求。

    上述基本的例子仅仅提供了一种简单的可被机器识别的日期格式,这里还有许多其他支持的格式,例如:

    <!-- 标准简单日期 -->
    <time datetime="2016-01-20">20 January 2016</time>
    <!-- 只包含年份和月份-->
    <time datetime="2016-01">January 2016</time>
    <!-- 只包含月份和日期 -->
    <time datetime="01-20">20 January</time>
    <!-- 只包含时间,小时和分钟数 -->
    <time datetime="19:30">19:30</time>
    <!-- 还可包含秒和毫秒 -->
    <time datetime="19:30:01.856">19:30:01.856</time>
    <!-- 日期和时间 -->
    <time datetime="2016-01-20T19:30">7.30pm, 20 January 2016</time>
    <!-- 含有时区偏移值的日期时间 -->
    <time datetime="2016-01-20T19:30+01:00"
      >7.30pm, 20 January 2016 is 8.30pm in France</time
    >
    <!-- 提及特定周 -->
    <time datetime="2016-W04">The fourth week of 2016</time>

    总结

    到这里标志着对不太常见的 HTML 文本语义的学习告一段落。你在本课程中所看到的内容并不是 HTML 文本元素的完整列表——我们只是想涵盖一些基本要素,以及一些你在实际中会较常见到的元素。接下来,我们将学习链接,这是网络最重要的功能之一。


    创建超链接 

    超链接非常重要——它们使互联网成为一个互联的网络。本文介绍了创建链接所需的语法,并讨论了链接的最佳实践。

    前提: 基本熟悉HTML(包含在开始学习HTML中),HTML文本格式(包含在HTML文字处理基础中)。
    目标: 学习如何有效地实现将多个超文本链接放在一起的文件链接。

    什么是超链接?

    超链接是互联网提供的最令人兴奋的创新,它们从一开始就一直是一个特性,使互联网成为互联的网络。超链接使我们能够将我们的文档链接到任何其他文档(或其他资源),也可以链接到文档的指定部分,我们可以在一个简单的互联网上提供应用程序。几乎任何网络内容都可以转换为链接,点击(或激活)超链接通过网络浏览器转到另一个网址(URL 

    备注: URL 可以指向 HTML 文件、文件、图像、文本文档、视频和音频文件以及可以在网络上保存的任何其他内容。如果浏览器不知道如何显示或处理文件,它会询问您是否要打开文件(需要选择合适的本地应用来打开处理或文件)或下载文件(后续处理它)。 

    以BBC的主页为例,里面就包含了非常多的链接,分别连接到不同新闻、网站的其他地方(导航功能),或者登入/注册页面(用户工具)等等。 

    链接的解析

    通过将文本或其他内容包裹在<a>元素内部,并给它一个包含网址的href属性(也称为超文本引用目标,将包含一个网址)来创建一个基本链接。

    <p>
      我创建了一个指向
      <a href="https://www.mozilla.org/zh-CN/">Mozilla 主页</a>的链接。
    </p>
    

    结果如下图所示:

    我创建了一个指向Mozilla 主页的链接。

    块级链接

    就像前面提到的那样,任何内容,甚至块级元素都可以作为链接出现。如果使标题元素成为链接,则将它包裹在某个点元素(<a>)内,就像这个代码段一样:

    <a href="https://developer.mozilla.org/zh-CN/">
      <h1>MDN Web 文档</h1>
    </a>
    <p>自从 2005 年起,就开始记载包括 CSS、HTML、JavaScript 等网络技术。</p>
    

    将标题转化为链接:

    图片链接

    如果需要作为链接的图片,使用<a>元素来包裹要引用图片的<img>元素。下面的示例使用相对路径来引用本地存储的 SVG 图像文件。

    <a href="https://developer.mozilla.org/zh-CN/">
      <img src="mdn_logo.svg" alt="MDN Web 文档" />
    </a>
    

    这将 MDN 转化为链接:

     备注: 您将在以后的文章中了解更多如何在网络中使用图片的信息。

    使用标题属性添加支持信息

    您可能要添加到您的链接的另一个属性是title。这旨在包含关于链接的补充信息,例如页面包含各种信息或需要注意的事情。

    <p>
      我创建了一个指向
      <a
        href="https://www.mozilla.org/zh-CN/"
        title="了解 Mozilla 使命以及如何参与贡献的最佳站点。">
        Mozilla 主页</a
      >的超链接。
    </p>
    

     结果如下(当鼠标光标悬停在链接上时,标题将作为提示信息出现):

     备注: 链接的标题仅当鼠标暂停停止时才会显示,这意味着使用键盘来导航网页的人很难获取标题信息。如果页面的标题信息非常重要,您应该使用所有用户都能方便获取的方式来呈现,例如放在常规文本中。

    统一资源定位符(URL)与路径(path)快速入门

    要全面了解链接目标,您需要了解统一资源定位符和文件路径。本小节将介绍相关的信息。

    统一资源定位符(Uniform Resource Locator,URL)是一个定义在网络上位置的一个文本字符串。例如,Mozilla 的简体中文主页位于https://www.mozilla.org/zh-CN/

    URL 使用路径查找文件。路径指定文件系统中你感兴趣的文件所在的位置。看一下一个简单的目录结构的例子(参见创建超链接目录)。

     

    这个目录结构的根目录称为creating-hyperlinks。当在本地处理网站时,你包含一个包含整个网站的目录。在根目录中,我们有index.htmlcontacts.html文件。在真实的网站上,index.html将成为我们的主页或着陆页(作为网站或特定网站部分的入口的网页)。

    我们的根目录还有两个目录——pdfs并且projects,它们分别包含一个 PDF(project-brief.pdf)文件和一个index.html文件。请注意你可以在同一个项目中有两个index.html文件,前提是它们在不同的文件系统目录下。第二个index.html可能是项目相关信息的入门页面。

    • 指向当前目录:如果你想在index.html(具体index.html)中包含一个指向contacts.html的超链接,你只需要指定想要链接到的文件名。因为它与当前文件是在同一个目录的,所以你应该使用的URL是contacts.html

      <p>
        要联系某位工作人员,请访问我们的<a href="contacts.html">联系人页面</a>。
      </p>
      
    • 指向子目录:如果你想在index.html(其实index.html)中包含一个指向projects/index.html的超链接,你需要先进入projects项目目录,然后通过指定目录的名称,然后是正斜杠,然后是文件的名称指明要链接到的文件index.html。因此你要使用的URL是projects/index.html

      <p>请访问我的<a href="projects/index.html">项目主页</a>。</p>
      
    • 指向上级目录:如果你想在projects/index.html中包含一个指向pdfs/project-brief.pdf的超链接,你必须先返回上级目录,然后再回到pdfs目录。“返回上一个目录级”使用两个英文点号表示(..),因此你应该使用的网址是../pdfs/project-brief.pdf

      <p>点击打开<a href="../pdfs/project-brief.pdf">项目简介</a>。</p>
      

    备注: 如果需要,你可以将这些功能的多个实例组合成复杂的URL。例如../../../complex/path/to/my/file.html

    分割文档

    超链接除了可以链接到文档外部,也可以链接到 HTML 文档的特定部分(被称为文档片段)。要做到这一点,你必须首先给要链接到的元素分配一个id属性。通常情况下,链接到一个特定的标题是有意义的,这看起来像下面这样:

    <h2 id="Mailing_address">邮寄地址</h2>
    

    为了链接到那个特定的id,则将其放在 URL 的末尾,并在前面包含井号(#),例如:

    <p>
      要提供意见和建议,请将信件邮寄至<a href="contacts.html#Mailing_address"
        >我们的地址</a
      >。
    </p>
    

     你甚至可以在同一个文档下,通过链接文档片段,来链接到当前文档的另一部分

    <p>本页面底部可以找到<a href="#Mailing_address">公司邮寄地址</a>。</p>
    

    绝对 URL 和相对 URL

    你可能会在网络上遇到两个术语,绝对URL相对URL(或者称为,绝对链接相对链接):

    绝对 URL:指向由其在 Web 上的绝对位置定义的位置,包括协议域名。像下面的例子,如果index.html页面上传到了projects这一个目录。并且projects目录位于 web 服务站点的根目录,web 站点的域名为https://www.example.com,那么这个页面就可以通过https://www.example.com/projects/index.html访问(或者通过https://www.example.com/projects/来访问,因为在没有指定特定的 URL 的情况下,大多数 web 服务器会默认访问加载index.html这些页面)

    无论绝对URL在哪里使用,它总是指向确定的相同位置。

    相对 URL:指向与你链接的文件的相关位置,前面我们在前面中所看到的位置。例如,如果我们想从示例文件链接https://www.example.com/projects/index.html转到相同目录下的一个 PDF 文件,URL 就是文件名(例如project-brief.pdf),没有其他的信息要求。如果 PDF 文件能够在projects的子目录pdfs中访问到,相对路径就是pdfs/project-brief.pdf(对应的绝对 URL 是https://www.example.com/projects/pdfs/project-brief.pdf

    一个相对的 URL 将指向不同的位置,这取决于引用的文件的实际位置——例如,如果我们把index.html文件从projects目录移动到 Web 站点的根目录(最高级别,而不是任何目录中),里面的pdfs/project-brief.pdf相对 URL 将指向https://www.example.com/pdfs/project-brief.pdf,而不是https://www.example.com/projects/pdfs/project-brief.pdf

    当然,project-brief.pdf文件和pdfs文件夹的位置不会因为你移动了index.html文件而突然发生变化——这涉及到你的链接指向错误的位置,因此如果单击它,将无法工作。你得小心点!

    链接最佳实践

    以下是一些在编写链接时可以遵循的最佳实践。

    使用响亮的链接措辞

    把链接放在你的页面上很容易。但这还不够。我们需要让所有的读者都可以使用链接,无论他们当前的环境和访问的工具(不可)。例如:

    • 使用屏幕阅读器的用户喜欢从页面上的一个链接跳到另一个链接,并省略下面的链接阅读。
    • 搜索引擎使用链接文本来索引目标文件,因此在链接文本中包含关键词是一个很好的主意,可以有效地描述相关的信息。
    • 读者往往会浏览页面而不是阅读每个字,他们的眼睛会被页面的特征吸引,比如链接。他们会找到描述性的链接。

    下面是一个具体的例子:

    好的链接文本:下载 Firefox

    <p><a href="https://www.mozilla.org/zh-CN/firefox/">下载 Firefox </a></p>
    

     不好的链接文本:点击这里下载 Firefox

    其他提示:

    • 不要把URL作为链接文本的一部分——URL看起来很丑,当屏幕阅读器出现一个字母一个重复字母的读出来的时候听起来就更丑了。
    • 不要在链接文本中说“链接”或“链接到”——它只是无用的内容。屏幕阅读器告诉人们有一个链接。可视化基因知道有一个链接,因为链接通常是用不同的颜色设计的,并且存在下划线(这个一般不应该被打破,因为用户习惯了)。
    • 保持你的链接标签问题短——这非常重要,因为屏幕阅读器需要解释整个链接文本。
    • 尽量减少相同文本的多个副本链接到不同位置的情况。如果存在标记为“单击此处”、“单击此处”、“单击此处”这样留下上下文的链接文本,很容易对使用屏幕阅读器的用户带来问题。

    链接到非 HTML 资源——留下清晰的指示

    当链接到一个需要下载的资源(如 PDF 或 Word 文档)或流媒体(如视频或音频)或其他可能的类似效果(打开一个弹出窗口)时,您应该添加明确的措辞,以求简洁。

    下面的例子会让人反感:

    • 你在使用低带宽连接的情况下,点击一个链接,意外地突然开始下载大文件。

    让我们看看一些例子,看看在这里可以使用什么样的文本:

    <p>
      <a href="https://www.example.com/large-report.pdf">
        下载销售报告(PDF,大小为 10 MB)
      </a>
    </p>
    
    <p>
      <a href="https://www.example.com/video-stream/" target="_blank">
        观看视频(将在新标签页中播放,HD 画质)
      </a>
    </p>
    

    在下载链接时使用下载属性

    当你链接到要下载的资源而不是在浏览器中打开时,你可以使用download属性来提供一个默认的保存文件名。下面是一个 Firefox 的 Windows 最新版本下载链接的示例:

    <a
      href="https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=zh-CN"
      download="firefox-latest-64bit-installer.exe">
      下载最新的 Firefox 中文版 - Windows(64 位)
    </a>
    

    学习主动性:创建一个导航菜单

    在这个练习中,我们希望你把一些页面和导航菜单链接起来,创建一个多页面的网站。这是创建网站的一种常见方式——每个页面都使用相同的页面结构,包括相同的导航菜单,所以当点击链接时,给人的印象是你停留在同一个地方,而不同的内容被带了出来。

    您需要将以下四页的本地副本放在相同的目录中。有关完整的文件列表,请参见navigation-menu-start目录:

    你应该:

    1. 在一个页面上的指定位置添加一个无序列表,其中包含要链接到的页面的名称。导航菜单通常只是一个链接列表,因此这在语义上是确定的。
    2. 将每个页面的名称转换为该页面的链接。
    3. 将导航菜单复制到每个页面。
    4. 在每一页上,只删除相同页面的链接——一个页面包含自己的链接是令人困惑和毫无意义的,而缺少链接到你当前的页面就像很好的视觉提示作用。

    最终的例子应该是这样的:

     备注: 如果您住了,或者不确定是否正确,可以访问navigation-menu-marked-up目录,来查看正确的答案。

    电子邮件链接

    当点击一个链接或按钮时,可能会开启新邮件的发送,而不是连接到一个资源或页面。这种情况可以使用<a>元素和mailto:URL 协议实现。

    其沟通和最常用的使用形式为指定的电子邮件地址的mailto:链接。例如:

    <a href="mailto:nowhere@mozilla.org">向 nowhere 发邮件</a>
    

    这会创建一个链接,看起来像这样:向无处发邮件

    通常,电子邮件地址是可选的。如果您省略了它(实际上,您的href属性只是简单的“mailto:”),发送新的电子邮件的窗口也可能被用户的邮件客户端打开,只是没有他们的地址信息,这通常在“分享”链接是很有用的,用户可以选择的发送地址邮件。

    指定详细信息

    除了电子邮件地址,您还可以提供其他信息。事实上,任何标准的邮件头字段都可以添加到您提供的常用mailtoURL 中。其中最主题(主题)、抄送(抄送)和主体(正文)(这不是一个真正的标头字段,但允许您为新邮件指定一个简短的内容消息)。每个字段及其值都被指定为查询项。

    下面是一个包含抄送、密件抄送、主题和主体的示例:

    <a
      href="mailto:nowhere@mozilla.org?cc=name2@rapidtables.com&bcc=name3@rapidtables.com&subject=The%20subject%20of%20the%20email&body=The%20body%20of%20the%20email">
      发送含有 cc、bcc、主题和主体的邮件
    </a>
    

     备注: 每个字段的值必须使用 URL 编码,即使用百分号转义的非打印字符(不可见字符如制表符、换行符、分页符)和空格。同时注意使用问号(?)来分隔主 URL 与参数值,以及使用 & 符来分隔mailto:URL 中的相关参数。这是标准的 URL 查询标记方法。阅读GET 方法以了解哪种 URL 查询标记方法是更常用的。

    这里还有一些其他的示例mailto链接:

    技能测试!

    您已经完成本文的结尾,但还记得最重要的信息吗?您可以找到一些进一步的测试,以验证您在继续前进之前已经保留了这些信息——见技能测试:链接

    小结

    这就是链接!在课程的高级中,当你开始研究链接的样式时,会回顾一些链接部分。接下来是 HTML,我们将回顾文本语义,并查看你会发现有用的更高级/不寻常的功能,文本格式进阶是你的下一站。


    HTML 中的图片

    最初,web 仅有文字,非常乏味。幸运的是,不久之后,我们就能在网页中嵌入图片和其他更有趣的内容类型了。尽管有多种多媒体类型需要考虑,但是从在网页中嵌入简单图片的 <img> 元素开始更加合理。在这篇文章中,我们将详细介绍如何使用 <img> 元素,包括它的基本属性,如何用 <figure> 元素为它添加标题,它与 CSS 背景图片的关系,以及其他 web 平台上的图形类型。

    多媒体和嵌入图片
    前提: 安装基本软件,掌握 处理文件的基本知识,熟悉 HTML 基础(参见 HTML 入门。)
    目标: 学习如何在 HTML 中嵌入简单的图片,为它们添加标题,以及 HTML 图片与 CSS 背景图片的关系。

    怎样将图片放到网页上?

    要想在网页上放置简单的图像,我们需要使用 <img> 元素。这个元素是空元素(即无法包含任何子内容和结束标签),它需要两个属性才能起作用:src 和 altsrc 属性包含一个 URL,该 URL 指向要嵌入页面的图像。src 属性可以是相对 URL 或绝对 URL,这与 <a> 元素的 href 属性类似。如果没有 src 属性,img 元素就没有图像可加载。

    'alt' 属性的描述如下

    备注: 为了更容易理解下面的内容,建议你阅读 URL 和路径简明入门来复习一下相对和绝对 URL 的概念。

    例如,如果你的图像叫做 dinosaur.jpg,并且它位于与 HTML 页面相同的目录中,你可以这样嵌入图像: 

    <img src="dinosaur.jpg" alt="恐龙" />
    

     如果图像在名为 images 的子目录中,该子目录位于与 HTML 页面相同的目录中,你可以这样嵌入它:

    <img src="images/dinosaur.jpg" alt="恐龙" />
    

    以此类推。

    备注: 搜索引擎还会读取图像文件名并将其计入 SEO。因此,你应该为图像起一个描述性的文件名;dinosaur.jpg 比 img835.png 更好。

    你也可以使用图像的绝对 URL 进行嵌入,例如: 

    <img src="https://www.example.com/images/dinosaur.jpg" alt="恐龙" />
    

     然而,不建议使用绝对 URL 进行链接。你需要托管你想要在网站上使用的图像,在比较简单的情况下,通常我们会把网站的图像保存在与 HTML 相同的服务器上。此外,从维护的角度来说,使用相对 URL 比绝对 URL 更有效率(当你将网站迁移到不同的域名时,你不需要更新所有 URL,使其包含新域名)。在更高级的设置中,你可能会使用内容分发网络(CDN)来传递图像。

    如果这些图像并非由你创建,你应该查看它们发布的许可证条款,确保自己有使用它们的权限(有关更多信息,请参阅下面的媒体资源和许可证)。 

     无论是使用绝对 URL 还是相对 URL,上述代码片段将会得到以下结果:

    备注: 像 <img> 和 <video> 这样的元素有时被称为可替换元素(replaced elements)。这是因为元素的内容和大小由外部资源(如图像或视频文件)定义,而不是由元素本身的内容定义。你可以在可替换元素中了解更多相关信息。 

    备注: 你也可以在 GitHub 仓库中找到本节的完整示例(请参阅源代码)。 

    备选文本

    我们接下来要看的属性是 alt。它的值应该是图片的文本描述,用于在图片无法显示或者因为网速慢而加载缓慢的情况下使用。例如,我们可以把上面的代码修改成这样:

    <img
      src="images/dinosaur.jpg"
      alt="The head and torso of a dinosaur skeleton;
              it has a large head with long sharp teeth" />
    

    测试 alt 文本的最简单方法是故意拼错文件名。如果我们的图片名字拼成 dinosooooor.jpg,浏览器就不会显示图片,而会显示 alt 文本:

    那么,为什么我们需要备选文本呢?它可以派上用场的地方有很多:

    • 用户有视力障碍,需要通过屏幕阅读器来浏览网页。事实上,图片备选描述文本对大多数用户都很有用。
    • 就像上面所说的,你也许会把图片的路径或文件名拼错。
    • 浏览器不支持该图片类型。某些用户仍在使用纯文本的浏览器,例如 Lynx,这些浏览器会把图片替换为备选文本。
    • 这些文字描述可以提供给搜索引擎使用,例如搜索引擎可能会将图片的文字描述和查询条件进行匹配。
    • 用户可能会关闭图片显示以减少数据的传输,这在手机上是十分普遍的,因为在一些国家带宽有限且昂贵。

    到底应该在 alt 里写点什么呢?这首先取决于为什么这张图片会在这儿,换句话说,如果这张图片没显示出来,会少了什么:

    • 装饰:如果图片仅用于装饰,你应该使用 CSS 背景图片,但如果必须使用 HTML,请添加空的 alt=""。如果图片不是内容的一部分,那么屏幕阅读器不应该浪费时间读取它。
    • 内容:如果你的图片提供了重要的信息,就要在 alt 文本中简要的提供相同的信息,甚至更近一步,把这些信息写在主要的文本内容里,这样所有人都能看见。不要写冗余的备选文本(如果在主要文本中将所有的段落都重复两遍,对于没有失明的用户来说多烦啊!),如果在主要文本中已经对图片进行了充分的描述,写 alt="" 就好。
    • 链接:如果你把图片嵌套在 <a> 标签里,来把图片变成链接,那你还必须提供无障碍的链接文本。在这种情况下,你可以写在同一个 <a> 元素里,或者写在图片的 alt 属性里,随你喜欢。
    • 文本:你不应该将文本放到图像里。例如,如果你的主标题需要有阴影,你可以用 CSS 来达到这个目的,而不是把文本放到图片里。如果真的必须这么做,那就把文本也放到 alt 里。

    本质上,关键在于即使图片无法被看见,也能提供可用的体验,这确保了所有人都不会错失某部分内容。尝试在浏览器中使图片不可见然后看看网页变成什么样了,你会很快意识到在图片无法显示时备选文本能帮上多大忙。 

    备注: 如需了解更多信息,请参阅我们的替代文本指南。 

    宽度和高度

    你可以用 width 和 height 属性来指定你的图片的宽度和高度。它们的值是不带单位的整数,以像素为单位表示图像的宽度和高度。

    你可以用多种方式了解你的图片的宽度和高度,例如在 Mac 上,你可以用 Cmd + I 来得到显示的图片文件的信息。回到我们的例子,你可以这样做:

    <img
      src="images/dinosaur.jpg"
      alt="The head and torso of a dinosaur skeleton;
              it has a large head with long sharp teeth"
      width="400"
      height="341" />

    这样做有一个好处。你页面的 HTML 和图片是分开的资源,由浏览器用相互独立的 HTTP(S) 请求来获取。一旦浏览器接收到 HTML,它就会开始将其显示给用户。如果图片尚未接收到(通常会是这种情况,因为图片文件的大小通常比 HTML 文件大得多),那么浏览器将只渲染 HTML,并在图片接收到后立即更新页面。

    例如,假设在图片之后有一些文本:

    <h1>Images in HTML</h1>
    
    <img
      src="dinosaur.jpg"
      alt="The head and torso of a dinosaur skeleton; it has a large head with long sharp teeth"
      title="A T-Rex on display in the Manchester University Museum" />
    <blockquote>
      <p>
        But down there it would be dark now, and not the lovely lighted aquarium she
        imagined it to be during the daylight hours, eddying with schools of tiny,
        delicate animals floating and dancing slowly to their own serene currents
        and creating the look of a living painting. That was wrong, in any case. The
        ocean was different from an aquarium, which was an artificial environment.
        The ocean was a world. And a world is not art. Dorothy thought about the
        living things that moved in that world: large, ruthless and hungry. Like us
        up here.
      </p>
      <footer>- Rachel Ingalls, <cite>Mrs. Caliban</cite></footer>
    </blockquote>

    一旦浏览器下载了 HTML,它就开始显示页面。

    当图片加载完成时,浏览器会将图片添加到页面中。由于图片占据空间,浏览器必须将文本向下移动,以适应图片的位置:

    这样移动文本对用户来说非常分散注意力,尤其是如果他们已经开始阅读文本的情况下。

    如果你在 HTML 中使用 width 和 height 属性来指定图片的实际大小,那么在下载图片之前,浏览器就知道需要为其留出多少空间。

    这样的话,当图片下载完成时,浏览器不需要移动周围的内容。

     设置图像的高度和宽度再次变得重要是关于该特性的历史的一篇优秀文章。

    备注: 虽然如我们所说,使用 HTML 属性来指定图片的实际大小是一个好的实践,但你不应该使用它们来调整图片的大小。

    如果设置的图片大小过大,你的图片将看起来粗糙、模糊或太小,不仅浪费带宽而且图片还不符合用户需求。如果长宽比不正确,图片也可能会变形。在将图片放到网页上之前,你应使用图像编辑器将其设置为正确的大小。

    如果确实需要更改图片的大小,应该使用 CSS 来实现。

    图像标题

    类似于超链接,你可以通过给图片增加 title 属性来提供更多的信息。在我们的例子中,可以这样做:

    <img
      src="images/dinosaur.jpg"
      alt="The head and torso of a dinosaur skeleton;
              it has a large head with long sharp teeth"
      width="400"
      height="341"
      title="A T-Rex on display in the Manchester University Museum" />
    

    这会给我们一个鼠标悬停提示,和链接标题一样:

    然而,我们并不推荐它——title 有很多无障碍问题,这些问题主要是基于这样一个事实,即屏幕阅读器的支持并不完善,除此之外大多数浏览器都不会显示它,除非你将鼠标悬停在上面(例如:无法使用键盘的用户),如果你对更多的信息感兴趣,请阅读 Scott O'Hara 写的 title 属性的考验与磨难

    更好的做法是将这样的支持信息包含在主要文章文本中,而不是附加在图片上。

    媒体资源和许可

    你在网络上找到的图像(以及其他媒体资源类型)都以不同的许可类型发布。在你构建的网站上使用图像之前,请确保你拥有该图像的所有权、获得使用许可或遵守所有者的许可条件。

    了解许可类型

    让我们来看看你在网络上可能会遇到的一些常见许可类别。

    版权所有

    原创作品(例如歌曲、书籍或软件),其所有者通常以封闭的版权保护方式发布他们的作品。这意味着,默认情况下,他们(或他们的出版商)拥有独家使用(例如展示或分发)其作品的权利。如果你想使用带有版权所有许可的受版权保护的图像,你需要执行以下操作之一:

    • 从版权持有人获得明确的书面许可。
    • 支付许可费用以使用它们。这可以是一次性费用,用于无限制使用(“免版税”),或者可能是“按照时间段、地理区域、行业或媒体类型等特定费用”的“权利管理”方式。
    • 仅将使用限制在你所在司法辖区中被视为合理使用合理交易的用途。

    作者不必在其作品中包含版权声明或许可条款。一旦原创作品在有形媒介上创建出来,版权就会自动存在。因此,如果你在网上找到一张图像,没有版权声明或许可条款,最安全的做法是假定它受到版权保护,所有权保留。

    自由许可

    如果图像是根据自由许可发布的,例如 MITBSD 或适当的知识共享(CC)许可,你无需支付许可费用或寻求许可即可使用它。但是,你仍需履行各种许可条件,这些条件因许可而异。

    例如,你可能需要:

    • 提供指向图像原始来源的链接,并标明创作者。
    • 指示是否对其进行了任何更改。
    • 使用相同许可证分享使用该图像创建的任何派生作品。
    • 不分享任何派生作品。
    • 不将该图像用于任何商业作品。
    • 在使用该图像的任何发布中包含许可证的副本。

    你应该查阅适用的许可证以了解你需要遵循的具体条款。

     备注: 你可能会在自由许可的上下文中遇到“copyleft”一词。Copyleft 许可(例如 GNU 通用公共许可证(GPL) 或“相同方式共享”创作共用许可证)规定派生作品需要按照原始许可证发布。

    Copyleft 许可在软件界中很常见。其基本思想是使用 copyleft 许可的代码构建的新项目(这被称为原始软件的“分支”)也需要根据相同的 copyleft 许可进行许可。这确保新项目的源代码也可供他人学习和修改。请注意,一般来说,为软件起草的许可证(例如 GPL)并不适合非软件作品,因为它们并不考虑非软件作品。

    请查阅本节提供的链接,了解不同许可类型及其规定的条件。

    公共领域/CC0

    进入公共领域的作品有时被称为“无版权保留”——它们不受版权保护,可以在未经许可且无需履行任何许可条件的情况下使用。作品可以因为版权到期或特定放弃权利等方式进入公共领域。

    将作品置于公共领域的最有效方法之一是将其许可为 CC0,这是一种特定的创作共用许可,为此目的提供了清晰明确的法律工具。

    在使用公共领域图像时,请获取证明该图像属于公共领域的证据,并将该证据保存记录。例如,使用截图记录原始来源(该来源需要清晰显示许可状态),并考虑在你的网站上添加一个页面,列出所获得的图像及其许可要求。

    搜索适用于自由许可的图像

    你可以使用图像搜索引擎或直接从图像存储库中找到适用于你的项目的自由许可图像。

    使用图像描述以及相关的许可条款搜索图像。例如,当搜索“黄色恐龙”时,可以添加“公共领域图像”、“公共领域图像库”、“开放许可图像”或类似的词语到搜索查询中。

    某些搜索引擎会提供工具,帮助你查找具有自由许可的图像。例如,使用 Google 时,转到“图片”选项卡搜索图像,然后单击“工具”。在结果工具栏中有一个“使用权限”下拉菜单,你可以选择专门搜索根据创作共用许可授权的图像。

    图像存储库网站,例如 FlickrShutterStock 和 Pixabay,具有搜索选项,允许你仅搜索具有自由许可的图像。一些网站专门分发具有自由许可的图像和图标,例如 Picryl 和 The Noun Project

    要想遵守图像发布的许可条件,你需要找到许可详细信息,阅读来源提供的许可证或指示页面,然后按照这些说明操作。值得信赖的图像存储库会清楚地列出其许可条件,并且易于查找。

    通过为图片搭配说明文字的方式来解说图片

    说到说明文字,有很多种方法可以添加一段说明文字来搭配图片。比如,你可以这么做:

    <div class="figure">
      <img
        src="images/dinosaur.jpg"
        alt="The head and torso of a dinosaur skeleton;
                it has a large head with long sharp teeth"
        width="400"
        height="341" />
    
      <p>A T-Rex on display in the Manchester University Museum.</p>
    </div>
    

    这没有问题,它包含了你需要的内容,并且很方便使用 CSS 调整样式。但是这里有一个问题,从语义的角度上来讲,图片和说明文字并没有什么联系,这会给使用屏幕阅读器的人造成麻烦,比如如果有 50 张图片和其搭配的 50 段说明文字,那么哪段说明文字是和哪张图片有关联的呢?

    更好的做法是使用 HTML 的 <figure> 和 <figcaption> 元素,它正是为此而被创造出来的:为图片提供一个语义容器,在说明文字和图片之间建立清晰的关联。我们之前的例子可以重写为:

    <figure>
      <img
        src="images/dinosaur.jpg"
        alt="The head and torso of a dinosaur skeleton;
                it has a large head with long sharp teeth"
        width="400"
        height="341" />
    
      <figcaption>
        A T-Rex on display in the Manchester University Museum.
      </figcaption>
    </figure>
    

     <figcaption> 元素告诉浏览器和辅助技术工具,这段说明文字描述了 <figure> 元素的内容。

    备注: 从无障碍的角度来说,说明文字和 alt 文本扮演着不同的角色。看得见图片的人们同样可以受益于说明文字,而 alt 文字只有在图片无法显示时才会发挥作用。所以,说明文字和 alt 的内容不应该一样,因为当图片无法显示时,它们会同时出现。尝试不让你的图片显示,看看效果如何。 

    figure 里不一定要是图片,只要是这样的独立内容单元即可:

    • 用简洁、易懂的方式表达意图。
    • 可以置于页面线性流的某处。
    • 为主要内容提供重要的补充说明。

    figure 可以是几张图片、一段代码、音视频、方程、表格或类似的东西。

    CSS 背景图片

    你也可以使用 CSS 把图片嵌入网站中(JavaScript 也行,不过那是另外一回事了)。CSS 属性 background-image 和其他的 background-* 属性是用来控制背景图片的。比如,要想为页面中的每个段落设置一个背景图片,你可以这样做:

    p {
      background-image: url("images/dinosaur.jpg");
    }
    

    按理说,这种做法相对于 HTML 中插入图片的做法,可以更好地控制图片和设置图片的位置,那么为什么我们还要使用 HTML 图片呢?如上所述,CSS 背景图片只是为了装饰——如果你只是想要在你的页面上添加一些漂亮的东西,来提升视觉效果,那 CSS 的做法是可以的。但是这样插入的图片完全没有语义上的意义,它们不能有任何备选文本,也不能被屏幕阅读器识别,等等。这就是 HTML 图片有用的地方了。

    总而言之,如果图像对你的内容有意义,则应使用 HTML 图像。如果图像纯粹是装饰,则应使用 CSS 背景图片。

    备注: 你可以在 CSS 模块里学到更多关于 CSS 背景图片的知识。 

    网页上的其他图形

    我们已经了解到可以使用 <img> 元素显示静态图像,或者通过使用 background-image 属性来设置 HTML 元素的背景。你还可以动态生成图形,或在生成后对图像进行操作。浏览器提供了使用代码创建 2D 和 3D 图形的方法,以及包含来自上传文件或用户摄像头实时流的视频。以下是有关这些更高级图像主题的文章链接:

    Canvas

    <canvas> 元素提供了使用 JavaScript 绘制 2D 图形的 API。

    SVG

    你可以借助可缩放矢量图形(SVG)来使用线条、曲线和其他几何形状来渲染 2D 图形。借助矢量图形,你可以创建能够以任意尺寸清晰缩放的图像。

    WebGL

    WebGL API 指南将帮助你入门 WebGL,这是用于 Web 的 3D 图形 API,可让你在 Web 内容中使用标准的 OpenGL ES。

    使用 HTML 音频和视频

    与 <img> 类似,你可以使用 HTML 将 <video> 和 <audio> 嵌入到网页中,并控制其播放。

    WebRTC

    WebRTC 中的 RTC 代表实时通信(Real-Time Communications),这是一种可以在浏览器客户端(对等方)之间进行音频/视频流和数据共享的技术。

    技能测试!

    你已经阅读完本文,但你能记住重要的信息吗?在继续之前,你可以进行一些进一步的测试,以验证你是否掌握了这些信息。请参阅技能测试:HTML 图像

    总结

    到此为止,我们已经详细介绍了图片和说明文字,在下篇文章中,我们将进一步看看如何使用 HTML 在网页上嵌入音频和视频

    视频和音频内容 

    现在我们已经可以轻松地为网页添加简单的图像,下一步我们开始为 HTML 文档添加音频和视频播放器。在这篇文章中,我们会使用 <video> 和 <audio> 元素来完成这件事;然后我们还会了解如何为视频添加标题/字幕。 

    前提: 已安装基本软件,具备处理文件的基本知识,熟悉 HTML 基础知识(如在入门 HTML 中介绍的内容)以及 HTML 中的图像
    目标: 学习如何将视频和音频内容嵌入网页,并为视频添加标题/字幕。

    web 中的音频和视频

    最早的在线视频和音频的流行得益于专有的基于插件的技术,如 Flash 和 Silverlight。这两种技术存在安全性和无障碍问题,现已过时,取而代之的是原生的 HTML 解决方案,该解决方案包括 <video> 和 <audio> 元素以及用于控制它们的 JavaScript API。在这里,我们不讨论有关 JavaScript 的问题,仅仅讲解有关 HTML 的基础。

    我们不会教你如何制作音频和视频,因为那需要完全不同的技术。如果你没有音频和视频的话,也没有关系,我们为你提供了示例音频和视频文件以及示例代码供你实验。

    备注: 在开始之前,你应当了解一些在线视频提供商,例如 YouTubeDailymotionVimeo 还有 Bilibili,以及在线音频提供商,例如 Soundcloud。这些公司可以让你以方便、简单的方式来托管和消费视频,所以你不必担心庞大的带宽消耗。在线视频提供商甚至提供现成的代码用于为你的 web 网页嵌入视频/音频。如果你使用这样的服务,你便可以避免在这篇文章中我们讨论的一些难题。在下一篇文章中,我们将会再讨论这样的服务。 

    <video> 元素

    你可以借助 <video> 元素来轻松地嵌入视频。一个简单的例子如下:

    <video src="rabbit320.webm" controls>
      <p>
        你的浏览器不支持 HTML 视频。可点击<a href="rabbit320.mp4">此链接</a>观看。
      </p>
    </video>
    

    值得注意的特性有:

    src

    同 <img> 元素的使用方式相同,src(来源)属性指向你想要嵌入到网页中的视频资源,它们的运作方式完全相同。

    controls

    用户应当能够控制视频和音频的播放(这对于患有癫痫的人来说尤为重要)。你必须使用 controls 属性来让视频或音频包含浏览器自带的控制界面,或者使用适当的 JavaScript API 构建自己的界面。至少,界面必须包括启动和停止媒体以及调整音量的方法。

    <video> 元素内的段落

    这个叫做后备内容,当浏览器不支持 <video> 元素的时候,就会显示这段内容,借此我们能够对旧的浏览器提供回退。你可以添加任何后备内容,在这个例子中我们提供了一个指向这个视频文件的链接,从而使用户至少可以访问到这个文件,而不会局限于浏览器的支持。

    已嵌入视频文件的网页样式如下:

    你可以尝试实时示例,或者查看源代码

    使用多个播放源以提高兼容性

    以上的例子中有一个问题,那就是不同浏览器对视频/音频格式的支持程度不一样,导致你可能无法播放某些视频/音频。幸运的是,你有办法防止这个问题发生。

    媒体文件的内容

    我们先来快速的了解一下相关术语。像 MP3、MP4 还有 WebM 这些格式叫做容器格式。他们定义了构成媒体文件的音频轨道和视频轨道的储存结构,其中还包含描述这个媒体文件的元数据,以及使用什么编解码器对其通道进行编码等等。

    一个包含电影的 WebM 文件,其主要包括一个主视频轨道和一个备用视角轨道,以及相应的英语和西班牙语音轨,还有英语解说音轨,如下图所示。文件还包括用于电影的闭路字幕文本轨道、西班牙语字幕以及解说的英文字幕。

    容器中的音频和视频轨道存储着按照相应编解码器格式编码的数据。音频轨道使用不同于视频轨道的格式进行编码。每条音频轨道都采用音频编解码器编码,而视频轨道则使用(你可能已经猜到了)视频编解码器编码。我们之前提到过,不同浏览器支持不同的视频和音频格式,以及不同的容器格式,如 MP3、MP4 和 WebM,这些容器可以包含不同类型的视频和音频。

    例如:

    • WebM 容器通常包括了 Vorbis 或 Opus 音频和 VP8/VP9 视频。这在所有的现代浏览器中都支持,除了某些老版本浏览器。
    • MP4 容器通常包括 AAC 或 MP3 音频和 H.264 视频。这在所有的现代浏览器中都支持。
    • Ogg 容器倾向于使用 Vorbis 音频和 Theora 视频。其在 Firefox 和 Chrome 当中受到完美的支持,不过这个容器已经被更强大的 WebM 格式所取代。

    有一些特殊情况。例如,对于某些类型的音频,通常编解码器的数据存储没有容器或简化容器。其中一个例子就是 FLAC 编解码器,它通常存储在 FLAC 文件中,FLAC 文件只是 FLAC 的原始轨迹。

    另一种情况是一直流行的 MP3 文件。“MP3 文件”实际上是存储在 MPEG 或 MPEG-2 容器中的 MPEG-1 音频层 III(MPEG-1 Audio Layer III,MP3)音频轨道。这一点特别有趣,因为尽管大多数浏览器不支持在 <video> 和 <audio> 元素中使用 MPEG 媒体,但由于 MP3 的流行,它们可能仍然支持 MP3。

    音频播放器倾向于直接播放音轨,例如 MP3 和 Ogg 文件。它们不需要容器。

    浏览器所支持的媒体文件

    备注: 一些流行的格式,如 MP3 和 MP4/H.264,尽管非常出色,但它们受到专利的限制;也就是说,有一些专利涵盖了它们所基于的某些或全部技术。在美国,MP3 直到 2017 年都受到专利保护,而 H.264 至少到 2027 年仍受专利保护。

    由于这些专利,浏览器如果希望实现对这些编解码器的支持,通常必须支付巨额的许可费用。此外,一些人更倾向于避免使用受限制的软件,而只使用开放格式。由于这些法律和偏好原因,web 开发者往往不得不支持多种格式以满足他们的整个用户群。

    刚刚所说的编解码器主要用于将音频和视频压缩成可管理的文件(原始的音频和视频文件非常大)。浏览器支持多种编解码器,如 Vorbis 和 H.264,它们用于已压缩的音视频与二进制数据的相互转换。不同的编解码器和不同的容器都有各自的优缺点,这会影响你做出选择。

    由于每种浏览器支持的容器文件格式和编解码器都有所不同,情况变得更加复杂。为了尽可能确保你的网站或应用能在用户的浏览器上正常工作,你可能需要提供多种格式的媒体文件。如果你的网站没有提供任何用户的浏览器支持的格式,那么你的媒体内容将无法播放。

    由于确保你的应用程序中的媒体内容能在你想要覆盖的每一种浏览器、平台和设备上都正常显示有些复杂,因此选择最合适的编解码器和容器组合可能会是一项挑战。为了选择最适合你需求的容器文件格式,请参考选择正确的容器;要为你的内容和目标受众选择合适的媒体编解码器,请参考选择视频编解码器以及选择音频编解码器

    当然,这里有一点需要注意:移动浏览器和桌面浏览器对格式的支持可能不一样。此外,桌面和移动浏览器都可能外包媒体播放处理(可能是全部媒体也可能是仅仅是那些它无法内部处理的特定类型)。因此,媒体支持在一定程度上依赖于用户安装了哪些软件。

    我们该怎么做呢?请请看如下更新后的例子(也可以在这里体验):

    <video controls>
      <source src="rabbit320.mp4" type="video/mp4" />
      <source src="rabbit320.webm" type="video/webm" />
      <p>你的浏览器不支持此视频。可点击<a href="rabbit320.mp4">此链接</a>观看</p>
    </video>

    在这里我们将 src 属性从 <video> 元素中移除,转而将它放在几个单独的 <source> 元素当中,这些元素分别指向各自的资源。在本例当中,浏览器会检查 <source> 元素,并且播放第一个与其自身 codec 相匹配的媒体。WebM 和 MP4 这两种格式在目前已经足够,只要视频支持这两种格式,那么其在大多数平台和浏览器上都能正确播放。

    每个 <source> 元素都含有 type 属性,这个属性是可选的,但是建议你添加这个属性——它包含了 <source> 指定的 MIME 类型,同时浏览器也会通过检查这个属性来迅速的跳过那些不支持的格式。如果你没有添加 type 属性,浏览器会尝试加载每一个文件,直到找到一个能正确播放的格式,但是这样会消耗掉大量的时间和资源。

    请参考我们的媒体类型和格式指南,以选择最适合你的需求的容器和编解码器,同时查找合适的 MIME 类型以指定每种媒体类型。

    其他 <video> 特性

    有许多你可以用在 HTML 视频上的特性,请看我们的下一个例子:

    <video
      controls
      width="400"
      height="400"
      autoplay
      loop
      muted
      preload="auto"
      poster="poster.png">
      <source src="rabbit320.mp4" type="video/mp4" />
      <source src="rabbit320.webm" type="video/webm" />
      <p>你的浏览器不支持此视频。可点击<a href="rabbit320.mp4">此链接</a>观看</p>
    </video>
    

    这串代码将会给我们呈现出如下用户界面:

    特性包括:

    width 和 height

    你可以用属性控制视频的尺寸,也可以用 CSS 来控制视频尺寸。无论使用哪种方式,视频都会保持它原始的长宽比——也叫做纵横比。如果你设置的尺寸没有保持视频原始长宽比,那么视频边框将会拉伸,而未被视频内容填充的部分,将会显示默认的背景颜色。

    autoplay

    这个属性会使音频和视频内容立即播放,即使页面的其他部分还没有加载完全。建议不要在你的网站上自动播放视频(或音频),因为用户可能会反感。

    loop

    这个属性可以让视频(或者音频)文件在结束时再次开始播放。这个也可能很恼人,同样不建议使用,除非有必要。

    muted

    这个属性会导致媒体播放时,默认关闭声音。

    poster

    这个属性指向了一个图像的 URL,这个图像会在视频播放前显示。通常用于粗略的预览或者广告。

    preload

    这个属性被用来缓冲较大的文件,有三个值可选:

    • "none":不缓冲文件
    • "auto":页面加载后缓存媒体文件
    • "metadata":仅缓冲文件的元数据

    你可以在 GitHub 体验以上的例子,也可以查看源代码。注意我们在体验的版本中并没有使用 autoplay 属性——如果页面一加载就开始播放视频的话,就不会看到封面(poster)了。

    <audio> 元素

    <audio> 元素与 <video> 元素的使用方式几乎完全相同,只有一些细微的差别,比如下面的边框不同,一个典型的例子如下:

    <audio controls>
      <source src="viper.mp3" type="audio/mp3" />
      <source src="viper.ogg" type="audio/ogg" />
      <p>你的浏览器不支持该音频,可点击<a href="viper.mp3">此链接</a>收听。</p>
    </audio>
    

    这串代码将会产生如下的效果:

    备注: 你可以在 GitHub 运行音频示例(也可以查看音频播放器源代码)。 

    因为音频播放器没有视觉部件,它所占用的空间比视频播放器要小(你只需要显示出能控制音频播放的控件)。其他一些 HTML <audio> 与 <video> 的差异如下:

    • <audio> 元素不支持 width/heigth 属性——由于其并没有视觉部件,也就没有内容要设置 width/height
    • 它同时也不支持 poster 属性——同样,因为没有视觉部件。

    除此之外,<audio> 元素支持所有 <video> 元素的特性——你可以回顾上面的章节来了解更多的有关信息。

    显示视频文本

    现在,我们将讨论一个略微先进的概念,这个概念将会十分的有用。许多人不想(或者不能)听到 Web 上的音频/视频内容,至少在某些情况下是这样的,比如:

    • 许多人患有听觉障碍(通常来说是很难听清声音的人,或者聋人),他们不能听见音频中的声音。
    • 还有一些人无法听音频,因为他们在一个非常嘈杂的环境当中(比如在拥挤的酒吧内恰好赶上了球赛)。
    • 在某些环境下播放音频会分散注意力或造成干扰(比如在图书馆或伴侣正在休息时),这种情况下,拥有字幕就显得非常实用了。
    • 有一些人他们不会说视频当中的语言,因此他们需要文字记录或者是翻译来帮助他们理解媒体内容。

    为这些人提供音频/视频中话语的文字记录,将会对他们有很大的帮助。幸运的是,借助 HTML 视频,我们可以做到这一点。我们只需使用 WebVTT 文件格式和 <track> 元素即可。

     备注: “转录(transcribe)”是指将视频/音频中说的话记录成文字形式,转录的结果称为“文字记录(transcript)”。

     WebVTT 是一个格式,用来编写文本文件,这个文本文件包含了众多的字符串,这些字符串会带有一些元数据,它们可以用来描述这个字符串将会在视频中显示的时间,甚至可以用来描述这些字符串的样式以及定位信息(尽管有限制)。这些字符串叫做 cue ,你可以根据不同的需求来显示不同类型的 cue,最常见的如下:

    subtitles

    外语材料的翻译字幕,来帮助那些听不懂音频中说的什么的人理解音频当中的内容。

    captions

    同步翻译对白,或是描述一些有重要信息的声音,来帮助那些不能听音频的人理解音频中的内容。

    定时描述

    由媒体播放器朗读的文本,其向盲人或其他视力受损用户描述重要的视觉内容。

    一个典型的 WebVTT 文件如下:

    要让其与 HTML 媒体一起显示,你需要做如下工作:

    1. 将其保存为 .vtt 文件,放在服务器可以提供服务的地方(见下文),例如和 HTML 文件放在同一文件夹。
    2. 用 <track> 标签链接 .vtt 文件,<track> 标签需放在 <audio> 或 <video> 标签当中,同时需要放在所有 <source> 标签之后。使用 kind 属性来指明是 subtitlescaptions 还是 descriptions。然后,使用 srclang 来告诉浏览器你是用什么语言来编写的 subtitles。最后,添加 label,以帮助读者在查找时识别语言。

    如下是例子: 

    <video controls>
      <source src="example.mp4" type="video/mp4" />
      <source src="example.webm" type="video/webm" />
      <track kind="subtitles" src="subtitles_es.vtt" srclang="es" label="Spanish" />
    </video>
    

     为了尝试这种方法,需要在本地 HTTP 服务器上托管文件。在浏览器的输出中,会看到一个显示字幕的视频,有点像这样:

     更多细节,包括如何添加标签,请阅读为 HTML 视频添加标题和字幕。在 Github 上可以找到与本文相关的样例,它们由 Ian Devlin 编写(或者查看源代码)。这个样例使用了 JavaScript 代码,用户借此可以选择不同的字幕。注意,若想要显示字幕,你需要点击“CC”按钮,并且选择某个选项(English、Deutsch 或 Español)。

    备注: 文本轨道还可以帮助你进行 SEO,因为搜索引擎对文字特别感兴趣。搜索引擎甚至可以借助文本轨道直接链接到视频中的某个位置。 

    主动练习:嵌入你自己的视频与音频

    在这个实践学习当中,我们希望你能够走出去,并且记录一些你自己的视频和音频——如今,大多数手机都能够非常方便的记录视频和音频,并且如果你可以将它上传到你的电脑上面,你可以使用它。你可能需要做一些格式转换,如果是视频的话,你需要将它们转化为 WebM 或者 MP4,如果是音频的话,你需要将它们转化为 MP3 或者 Ogg。不过你并不需要担心,有许多的程序都能够帮你轻松解决这些问题,例如 Miro 视频转换器和 Audacity。我们非常希望你能够亲自动手。

    如果你无法取得任何的音频或者视频,你可以使用我们为你提供的示例音频和视频文件 来练习。同时你也可以使用我们的代码来作为参考。

    我们希望你能够:

    1. 将你的音频和视频文件保存在你电脑上的一个新目录中。
    2. 在相同的路径下,创建一个新的 HTML 文件,命名为 index.html
    3. 在页面上添加 <audio> 和 <video> 元素;让它们显示浏览器默认的控件。
    4. 在当中添加 <source> 标签,并添加 type 属性,以便于浏览器能够找到其能够支持的格式并加载它。
    5. 在 <video> 元素中添加 poster 属性,这会在视频播放之前显示。尽情创作属于自己的海报图形吧。

    另外,你可以尝试研究一下文本音轨,试着为你的视频添加一些字幕。

    技能测试!

    你已经完成了这篇教程的学习,但你是否还记得教程里最重要的内容呢?在继续之前,你可以通过一些测试来验证你是否已经掌握了这些内容,请参见技能测试:内嵌多媒体。需要注意,这个测试中的第三个问题可能会需要一些之后讲到的技术,所以我们建议你尝试之前阅读一下下一篇教程

    总结

    我们祝愿你可以沉浸在 Web 网站的音频和视频当中,下一篇文章,我们将会学习到另外一种在 web 页面中嵌入内容的方法,比如使用 <iframe> 或者 <object>

    参见


    HTML 表格基础

    本文将从 HTML 表格开始,介绍一些基本的内容,如行和单元格、标题、使单元格跨越多个列和行,以及如何将列中的所有单元组合在一起进行样式化。

    前提: HTML 基本概念(参见 HTML 介绍)。
    目标: 了解熟悉 HTML 表格基本知识。

    什么是表格?

    表格是由行和列(表格数据)组成的结构化数据集,它让你快速简单地查找某个表示不同类型数据之间的某种关系的值。比如说,某个人和他的年龄,一天或是一周,当地游泳池的时间表。

     表格在人类社会中很常见,而且已经存在很长时间了,下面这张 1800 年的美国人口普查文件中就可以证明:

     因此,HTML 的创建者们提供了一种方法来构建和呈现 web 上的表格数据,这也就不足为奇了。

    表格如何工作?

    表格的一个特点就是固定不变。通过在行标题和列标题之间建立视觉关联,信息可以容易地被解读。例如,请看下表,找到一个拥有 62 颗卫星的类木气态巨行星。可以通过关联相关行标题和列标题找到答案。

     

    正确使用时,HTML 表格可以很好地通过屏幕阅读器等辅助工具进行处理,因此一个成功的 HTML 表格应该能为视力正常和视力受损的用户带来更好的体验。

    表格风格

    可以在 GitHub 上查看这个在线示例!你会注意到,这里的表格看起来可读性更好,这是因为你在本页上面看到的表格只使用了最少的样式,而 GitHub 版本则使用了更多的 CSS。

    不要幻想;为了能够让表格在 web 上有效,你需要用 CSS 提供一些样式信息,以及尽可能好的 HTML 固定结构。在本模块中,我们将专注于 HTML 部分;在你完成这里的内容之后,你可以浏览样式化表格来了解 CSS 的部分。

    虽然在本模块中我们不会专注于 CSS,但是我们提供了一个较小的 CSS 样式表让你使用,和默认的没有采用任何 CSS 样式的表相比,表格会更加可读。你可以在这里获取样式表,还可以找到一个应用样式表的 HTML 模板,它们将为你提供一个尝试使用 HTML 表格的良好起点。

    什么时候你不应该使用 HTML 表格?

    HTML 表格应该用于表格数据,这正是 HTML 表格设计出来的用途。不幸的是,许多人习惯用 HTML 表格来实现网页布局,例如:一行包含头部,一行包含几列内容,一行包含尾部。你可以在我们的无障碍学习模块中的页面布局章节获得更多细节内容和一个示例。这种做法以前是很常见的,因为以前 CSS 在不同浏览器上的兼容性比较糟糕;表格布局现在不太普遍,但你可能仍然会在网络的某些角落看到它们。

    简单来说,使用表格布局而不使用 CSS 布局技巧是很糟糕的。主要的理由有以下几个:

    1. 表格布局减少了视觉受损的用户的无障碍: 盲人所使用的屏幕阅读器会解析存在于 HTML 页面上的标签,然后为用户读出其中的内容。因为对于布局来说,表格不是一个正确的工具,使用的标记比使用 CSS 布局技术更复杂,所以屏幕阅读器的输出会让他们的用户感到困惑。
    2. 表格会产生很多标签: 正如刚才提到的,表格布局通常会比正确的布局技术涉及更复杂的标签结构,这会导致代码变得更难于编写、维护、调试。
    3. 表格不能自动响应: 当你使用正确的布局容器(比如 <header><section><article> 或是 <div>)时,它们的默认宽度是父元素的 100%;而表格的默认大小是根据其内容而定的。因此,需要采取额外的措施来获取表格布局样式,以便有效地在各种设备上工作。

    动手练习:创建你的第一个表格

    对于表格的理论知识,我们已经说了很多了,所以,让我们来看一个使用的例子,并建立一个简单的表格。

    1. 首先,将 blank-template.html 和 minimal-table.css 文件拷贝到你的本地环境上。

    2. 每一个表格的内容都包含在这两个标签中:<table></table>。在你的 HTML 的 <body> 中添加这些内容。

    3. 在表格中,最小的内容容器是单元格,是通过 <td> 元素创建的(其中“td”代表“table data”)。把下面的内容添加到你的表格标签中:

      <td>我是第一个单元格</td>
      
    4. 如果我们想要一行四个单元格,我们需要把这组标签拷贝三次,更新你表中的内容,让它看起来是这样的:

      <td>我是第一个单元格</td>
      <td>我是第二个单元格</td>
      <td>我是第三个单元格</td>
      <td>我是第四个单元格</td>
      

    你会看到,单元格不会放置在彼此的下方,而是自动与同一行上的其他单元格对齐。每个 <td> 元素 创建一个单独单元格,它们共同组成了第一行。我们添加的每个单元格都使行的长度变长。

    如果想让这一行停止增加,并让单元格从第二行开始,我们需要使用 <tr> 元素(其中“tr”代表“table row”)。让我们现在来证实一下。

    1. 把你已经创建好的 4 个单元格放入 <tr> 标签,就像这样:

      <tr>
        <td>我是第一个单元格</td>
        <td>我是第二个单元格</td>
        <td>我是第三个单元格</td>
        <td>我是第四个单元格</td>
      </tr>
      
    2. 现在你已经实现了一行,可以继续增加至两行、三行。每一行都需要一个额外的 <tr> 元素来包装,每个单元格的内容都应该写在 <td> 中。

    结果

    这样会产生一个如下所示的表:

    使用 <th> 元素添加标题

    现在,让我们把注意力转向表格标题,位于行或列开头的特殊单元格,定义了行或列包含的数据类型(例如,本文第一个示例中的“人员”和“年龄”单元格)。为了说明它们为什么这么有用,来看下面这个例子,首先是源代码:

    <table>
      <tr>
        <td>&nbsp;</td>
        <td>诺基</td>
        <td>弗洛尔</td>
        <td>艾拉</td>
        <td>胡安</td>
      </tr>
      <tr>
        <td>品种</td>
        <td>杰克罗斯犬</td>
        <td>贵宾犬</td>
        <td>流浪犬</td>
        <td>可卡犬</td>
      </tr>
      <tr>
        <td>年龄</td>
        <td>16</td>
        <td>9</td>
        <td>10</td>
        <td>5</td>
      </tr>
      <tr>
        <td>主人</td>
        <td>岳母</td>
        <td>我</td>
        <td>我</td>
        <td>嫂子</td>
      </tr>
      <tr>
        <td>饮食习惯</td>
        <td>吃掉所有人的剩菜</td>
        <td>啃咬食物</td>
        <td>吃得多</td>
        <td>吃到爆炸为止</td>
      </tr>
    </table>
    

     这是表格实际呈现的效果:

     这里的问题是:虽然你可以弄清楚发生了什么,但是尽可能的交叉参考数据并不容易。如果列和行的标题以某种方式出现,那将会更好。

    动手练习:表格标题

    让我们来改进这个表格。

    1. 首先,把 dogs-table.html 和 minimal-table.css 文件保存到你的本地环境,HTML 文件包含上文你看到的几种狗的数据。
    2. 为了将表格的标题在视觉上和语义上都能被识别为标题,你可以使用 <th> 元素(其中“th”代表“table header”),用法和 <td>是一样的,除了它表示为标题,不是普通的单元格以外。进入你的 HTML 文件,将表格中应该是标题的 <td> 元素标记的内容,都改为用 <th> 元素标记。
    3. 保存你的 HTML 文件,然后在浏览器中加载,然后你应该会看到,现在的标题更像标题了。

    备注: 你可以在 GitHub 中找到完成的版本 dogs-table-fixed.html也可以查看在线示例)。

    为什么标题是有用的?

    我们已经给出了部分答案,当标题明显突出的时候,你可以更加简单地找到你想找的数据,设计上也会看起来更好。

    备注: 即使你不给表格添加你自己的样式,表格标题也会带有一些默认样式:加粗和居中,让标题可以突出显示。

    表格标题也有额外的好处,随着 scope 属性(我们将在下一篇文章中了解到),这个属性允许你让表格变得更加无障碍,每个标题与相同行或列中的所有数据相关联。屏幕阅读设备能一次读出一列或一行的数据,这是非常有帮助的。

    允许单元格跨越多行和列

    有时候希望单元格跨越多行或多列。下面是一个显示常见动物名字的简单示例。在某些情况下,希望在动物名称旁边显示雄性和雌性的名称。有时候又不需要,这种情况下,只希望动物名称横跨整个表格。

    一开始的标记写法是这样的:

    <table>
      <tr>
        <th>动物</th>
      </tr>
      <tr>
        <th>河马</th>
      </tr>
      <tr>
        <th>马</th>
        <td>公马</td>
      </tr>
      <tr>
        <td>母马</td>
      </tr>
      <tr>
        <th>鳄鱼</th>
      </tr>
      <tr>
        <th>鸡</th>
        <td>母鸡</td>
      </tr>
      <tr>
        <td>公鸡</td>
      </tr>
    </table>
    

     但是输出的结果不是我们想要的:

    需要一个方法,让“动物”、“河马”和“鳄鱼”横跨两列,让“马”和“鸡”竖跨两行。幸好,表格中的标题和单元格有 colspan 和 rowspan 属性,可以实现这些效果。这两个属性接受一个没有单位的数字值,数字决定了它们的宽度或高度是几个单元格。比如,colspan="2" 会使单元格横跨两列。

    让我们使用 colspan 和 rowspan 来改进现有的表格。

    1. 首先,把 animals-table.html 和 minimal-table.css 文件复制到你的本地环境,HTML 文件中包含了你刚才看到的动物示例的数据。
    2. 接着,使用 colspan 让“动物”、“河马”和“鳄鱼”横跨两列。
    3. 最后,使用 rowspan 让“马”和“鸡”竖跨两行。
    4. 保存后,用浏览器打开你写的 HTML 文件,看看改进的地方。

    备注: 这样设计列的样式仅限于几个属性borderbackgroundwidth 和 visibility。要设置其他属性,必须对列中的每个 <td> 或 <th> 进行样式设置,或者使用复杂的选择器,如 :nth-child

    下面是一个简单的示例: 

    <table>
      <tr>
        <th>数据 1</th>
        <th style="background-color: yellow">数据 2</th>
      </tr>
      <tr>
        <td>加尔各答</td>
        <td style="background-color: yellow">橙汁</td>
      </tr>
      <tr>
        <td>机器人</td>
        <td style="background-color: yellow">爵士乐</td>
      </tr>
    </table>
    

     下面就是上述代码的结果:

     这并不理想,因为必须在列中的所有三个单元格中重复样式信息(在实际项目中,可能会在所有单元格中设置一个 class,并在单独的样式表中指定样式)。

    使用 <col> 应用样式

    可以在 <col> 元素上一次性指定信息,而不是像上面这样做。<colgroup> 容器就在开始标记 <table> 下面,<col> 元素在 <colgroup> 容器内指定。可以通过如下方式指定表格,来创建与上述相同的效果:

    <table>
      <colgroup>
        <col />
        <col style="background-color: yellow" />
      </colgroup>
      <tr>
        <th>数据 1</th>
        <th>数据 2</th>
      </tr>
      <tr>
        <td>加尔各答</td>
        <td>橙汁</td>
      </tr>
      <tr>
        <td>机器人</td>
        <td>爵士乐</td>
      </tr>
    </table>
    

    定义了两个“样式列”,其中一个为第二列每列指定样式信息。没有为第一列设计样式,但仍必须包含一个空白的 <col> 元素,否则样式将只应用于第一列。

    如果想将样式信息应用于两列,只需包含一个带有 span 属性的 <col> 元素即可,就像这样:

    <colgroup>
      <col style="background-color: yellow" span="2" />
    </colgroup>
    

    就像 colspan 和 rowspan 一样,span 需要一个无单位的数字值,用来指定让这个样式应用到表格中多少列。

    备注: 如果表格、列和列中的单元格都是单独样式化的,那么应用于单元格的样式将绘制在列样式之上,而列样式将绘制在表格之上。这是因为先渲染表格层,然后渲染列层,单元格层渲染在所有其他表格层之上

    动手练习:colgroup 和 col

    又到了需要你自己独立完成的时间了。

    下面是一位语言教师的课程表。星期五,她有一门新的课程,全天教授荷兰语,但她也在周二和周四教授几节德语课。她希望突出显示包含她授课天数的栏目。

    通过下面这些步骤来重构这个表格。

    1. 首先,把 timetable.html 文件复制到你的本地环境。这个 HTML 文件包含你在上文中看到的表格,不过是减去样式信息的。
    2. 在表格的顶部添加一个 <colgroup> 元素,就放在 <table> 标签下面,<colgroup>可以添加 <col> 元素(继续看下面剩余的步骤)。
    3. 第一列和第二列不需要应用样式。
    4. 为第三列添加一个背景颜色。style 属性是 background-color:#97DB9A;
    5. 为第四列设置一个独立的宽度,style 属性是 width: 100px;
    6. 为第五列添加一个背景颜色。style 属性是 background-color: #97DB9A;
    7. 为第六列添加不同的背景颜色和边框,表示这是一个特殊的日子,她要教一门新课。style 属性是 background-color:#DCC48E; border:4px solid #C1437A;
    8. 最后两天是休息日,所以只需将它们设置为无背景颜色,但需要设置宽度;style 属性是 width: 100px;

    看看你是否能完成这个示例,如果你遇到了困难,或想要核对你完成的作品,你可以在 GitHub 上找到完成的版本 timetable-fixed.html也可以查看在线示例)。

    总结

    本章节仅仅包含了 HTML 表格的基础。在下一篇文章中,我们将介绍一些表格进阶特性,并开始考虑方便视力障碍的人士的访问。

    HTML 表格进阶特性和无障碍 

    本模块的第二篇文章中,我们来看一下 HTML 表格更进阶的特性,比如表格的标题、摘要,以及将表格中的各行分组成表头、表体和表尾三部分,以及为视力受损的用户提供表格无障碍。

    前提: HTML 的基础知识(参见 HTML 简介)。
    目标: 学习 HTML 表格更进阶的特性,以及表格无障碍。

    使用 <caption> 为你的表格增加一个标题

    你可以通过 <caption> 元素为你的表格增加一个标题,再把 <caption> 元素放入 <table> 元素中。你应该把它放在 <table> 开始标签的下面。

    <table>
      <caption>
        侏罗纪时期的恐龙
      </caption>
    
      …
    </table>
    

    从上面简单的例子可以推断,标题意味着包含对于表格内容的描述,这对那些希望可以快速浏览网页中的表格对他们是否有帮助的读者们来说,是非常好的功能。特别是盲人用户,不需要让屏幕阅读设备读出很多单元格的内容,来让用户了解这张表格讲的是什么,而是可以依靠标题的内容,来决定是否需要了解更详细的内容。

    标题就放在 <table> 标签的下面。

    备注: 同样,summary 属性也可以在 <table> 元素中使用,用来提供一段描述,可以被屏幕阅读设备阅读。但是我们推荐使用 <caption> 元素来代替,因为 summary 已经废弃了,且不能被视力正常的用户阅读(它不会出现在页面上)。

    动手练习:添加一个标题

    我们来试试看吧,回顾一下我们在之前的文章中第一次遇到的例子。

    1. 打开你的语言老师的学校时间表,就是 HTML 表格基础 结尾中的例子,或者把 timetable-fixed.html 文件复制到本地。
    2. 为表格添加一个合适的标题。
    3. 保存你的代码,然后用浏览器打开,看看你的表格是什么样的。

    备注: 你也可以在 GitHub 上找到我们的版本 timetable-caption.html查看在线运行版本)。

    添加 <thead>、<tbody> 和 <tfoot> 结构

    由于你的表格在结构上有点复杂,如果把它们定义得更加结构化,那会帮助我们更能了解结构。一个明确的方法是使用 <thead><tbody> 和 <tfoot>,这些元素允许你把表格中的部分标记为表头、表体和表尾三部分。

    这些元素不会使表格更易于屏幕阅读器用户访问,也不会造成任何视觉上的改变。然而,它们在应用样式和布局上会起到作用,可以更好地让 CSS 应用到表格上。给你一些有趣的例子,在长表格的情况下,你可以在每个打印页面上使表格页眉和页脚重复,你也可以让表格的正文部分显示在一个单独的页面上,并通过上下滚动来获得内容。

    要使用它们,应按以下顺序排列:

    • <thead> 元素必须包住表格的表头部分。一般是第一行,往往都是每列的标题,但是不是每种情况都是这样的。如果你使用了 <col>/<colgroup> 元素,那么 <thead> 元素就需要放在它们的下面。
    • <tbody> 元素需要包住表格内容的主要部分(不是表头和表尾)。
    • <tfoot> 元素需要包住表格的表尾部分。一般是最后一行,往往是对前面所有行的总结。

    备注: <tbody> 总是包含在每个表中,如果你没有在代码中指定它,那就是隐式的。可以来验证一下,打开一个你之前没有包含 <tbody> 的例子,然后在你的浏览器开发者工具中观察你的代码,你会看到浏览器为你添加了这个标签。你也许会想问,为什么你应该在所有表中都需要这个元素,因为它可以让你更好地控制表格结构和样式。

    动手练习:添加表格结构

    让我们动手使用这些新元素。

    1. 首先,把 spending-record.html 和 minimal-table.css 复制到你的本地环境。

    2. 尝试在浏览器中打开它,你会发现看起来不错,但是它可以被改善得更好。“SUM”行包含了已经使用的金额的总和,不过它出现在了错误的位置,以及代码中还遗失了一些细节。

    3. 将明显的标题行改为使用 <thead> 元素,“SUM”行使用 <tfoot> 元素,剩余的内容使用 <tbody> 元素。

    4. 先保存,再刷新。你会看到,添加了 <tfoot> 元素后,“SUM”行跑到了表格的底部。

    5. 接着,添加一个 colspan 属性,使“SUM”单元格占 4 个单元格的位置,所以实际数字是显示在“Cost”列的底部。

    6. 让我们为表格添加一些简单的额外属性,能够让你理解这些属性是如何帮助更好地让表格应用 CSS 的。在你的 HTML 文件的 head 标签部分,你会看到一个空的 <style> 元素。在 style 元素中添加下列 CSS 代码:

      tbody {
        font-size: 95%;
        font-style: italic;
      }
      tfoot {
        font-weight: bold;
      }
      
    7. 先保存,再刷新,然后观察一下结果。如果没有 <tbody> 和 <tfoot> 元素,你也许会写更加复杂的选择器或规则来应用同样的样式。

    备注: 我们并不期望你现在就能完全理解 CSS。在你阅读我们的 CSS 模块时,你会学到更多这方面的知识(CSS 介绍是一个好的起点;文章样式化表格也专门讲述了如何对表格添加样式)。

    你完成的表格应该如下所示: 

    备注: 你也可以在 GitHub 上找到 spending-record-finished.html

    嵌套表格

    在一个表格中嵌套另外一个表格是可能的,只要你包含完整的结构,包括 <table> 元素。这样通常是不建议的,因为这种做法会使标记看上去很难理解,对使用屏幕阅读的用户来说,无障碍性也降低了。以及在很多情况下,也许你只需要插入额外的单元格、行和列到已有的表格中。然而有时候是必要的,比如你想要从其他资源中更简单地导入内容。

    下面的代码演示了一个简单的嵌套表格:

    <table id="table1">
      <tr>
        <th>标题 1</th>
        <th>标题 2</th>
        <th>标题 3</th>
      </tr>
      <tr>
        <td id="nested">
          <table id="table2">
            <tr>
              <td>单元格 1</td>
              <td>单元格 2</td>
              <td>单元格 3</td>
            </tr>
          </table>
        </td>
        <td>单元格 2</td>
        <td>单元格 3</td>
      </tr>
      <tr>
        <td>单元格 4</td>
        <td>单元格 5</td>
        <td>单元格 6</td>
      </tr>
    </table>
    

    输出看起来是这样的:

    对于视力受损的用户的表格

    让我们简要回顾一下如何使用数据表。一个表格可以是一个便利的工具,或者让我们快速访问数据,并允许我们查找不同的值。比如,你只需要稍微看一眼下列的表格,你就能得知 2016 年 8 月份在根特出售了多少个戒指。为了理解信息,我们让数据与列标题或行标题之间建立视觉联系。

     但假设你无法通过视觉关联这些数据呢?那么你应该如何阅读上述的表格?视力受损的用户经常使用一个屏幕阅读设备来为他们读出网页上的信息。对于盲人来说,阅读简单的文字没有什么问题,但是要理解一张表格的内容,这就有一些难度了。然而,通过适当的标记,我们可以用程序化的关联来取代视觉关联。

    备注: 根据世界卫生组织 2017 年的数据,大约有 2.53 亿人患有视觉障碍。 

    本篇文章提供了更一步的技术来使表格的无障碍性尽可能地提高。

    使用列和行的标题

    屏幕阅读设备会识别所有的标题,然后在它们和它们所关联的单元格之间产生程序关联。列和行标题的组合将标识和解释每个单元格中的数据,以便屏幕阅读器用户可以类似于视力正常的用户的操作来理解表格。

    我们之前的文章就提到过这一点,可见使用 <th> 元素添加标题

    scope 属性

    本篇文章的一个新话题是 scope 属性,可以添加在 <th> 元素中,以告诉屏幕阅读器该表头的类型——它是所在行的表头,还是所在列的表头。回想一下我们前面的消费记录例子,你可以像这样明确地把表头定义为所在列的头部:

    <thead>
      <tr>
        <th scope="col">购买</th>
        <th scope="col">位置</th>
        <th scope="col">时间</th>
        <th scope="col">评价</th>
        <th scope="col">成本 (€)</th>
      </tr>
    </thead>
    

    而每一行都可以有一个像这样定义的标题(如果我们把行的标题和列的标题都加上):

    <tr>
      <th scope="row">理发</th>
      <td>理发店</td>
      <td>12/09</td>
      <td>好主意</td>
      <td>30</td>
    </tr>
    

    屏幕阅读器会识别这种结构化的标记,并一次读出整列或整行。

    scope 还有两个可选的值:colgroup 和 rowgroup。这些用于位于多个列或行的顶部的标题。如果你回顾这部分文章开始部分的“2016 年 8 月出售的物品”表格,你会看到“衣物”单元格在“长裤”、“裙子”和“连衣裙”单元格的上面。这几个单元格都应该被标记为标题(<th>),但是“衣物”是一个位于顶部且定义了其他三个子标题的标题。因此“衣物”应该有一个 scope="colgroup" 属性,而另外三个子标题应该有 scope="col" 属性:

    <thead>
      <tr>
        <th colspan="3" scope="colgroup">衣物</th>
      </tr>
      <tr>
        <th scope="col">长裤</th>
        <th scope="col">裙子</th>
        <th scope="col">连衣裙</th>
      </tr>
    </thead>
    

     这同样适用于多个分组行的标题。再看看“2016 年 8 月出售的物品”表格,这次注意有“阿姆斯特丹”和“乌特勒支”标题(<th>)的行。可以看到“荷兰”标题,标记为 <th> 元素,跨越了两行,是其他两个子标题的标题。因此,应在此标题单元格中指定 scope="rowgroup",以帮助屏幕阅读器创建正确的关联:

    <tr>
      <th rowspan="2" scope="rowgroup">荷兰</th>
      <th scope="row">阿姆斯特丹</th>
      <td>89</td>
      <td>34</td>
      <td>69</td>
    </tr>
    <tr>
      <th scope="row">乌特勒支</th>
      <td>80</td>
      <td>12</td>
      <td>43</td>
    </tr>
    

    id 和 headers 属性

    如果要替代 scope 属性,可以使用 id 和 headers 属性来创建标题与单元格之间的联系。

    headers 属性包含一个空格分隔的无序字符串列表,每个字符串对应 <th> 元素的唯一 id,这些 <th> 元素为数据单元格(<td> 元素)或另一个标题单元格(<th> 元素)提供标题。

    这样,HTML 表格就明确定义了表格中每个单元格的位置,这些单元格由其所属的每列和每行的标题定义,有点像电子表格。为使其运行良好,表格确实需要列标题和行标题。

    回到“2016 年 8 月出售的物品”示例,可以这样使用 id 和 headers 属性:

    1. 为每个 <th> 元素添加一个唯一的 id
    2. 为每个作为子标题(即在其上方有一个标题元素)的 <th> 元素添加一个 headers 属性。其值是位于顶部并定义子标题的标题 id,在我们的示例中,列标题为“衣物”,行标题为“比利时”。
    3. 为每个 <td> 元素添加一个 headers 属性,并以空格分隔的列表形式添加相关联的 <th> 元素的 id。像在电子表格中一样进行操作:找到数据单元格,然后搜索行和列的相应标题。指定 id 的顺序并不重要,但应保持一致,使其井井有条。
    <thead>
      <tr>
        <th id="clothes" colspan="3">衣物</th>
      </tr>
      <tr>
        <th id="trousers" headers="clothes">长裤</th>
        <th id="skirts" headers="clothes">裙子</th>
        <th id="dresses" headers="clothes">连衣裙</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th id="belgium" rowspan="3">比利时</th>
        <th id="antwerp" headers="belgium">安特卫普</th>
        <td headers="antwerp belgium clothes trousers">56</td>
        <td headers="antwerp belgium clothes skirts">22</td>
        <td headers="antwerp belgium clothes dresses">43</td>
      </tr>
    </tbody>
    

     备注: 这种方法在标题和数据单元格之间建立了非常精确的关联,但是它使用了非常多的标记,而且没有留下任何错误的空间。对于大多数表格来说,scope 方法通常就足够了。

    动手练习:使用 scope 和 headers

    1. 对于这个最后的练习,首先把 items-sold.html 和 minimal-table.css 复制到你的本地环境。
    2. 现在尝试添加适当的 scope 属性来让表格变得更加易于访问。
    3. 最后,尝试把未添加 scope 属性的源文件再复制一份。这次使用 id 和 headers 属性创建精确、明确的关联,使表格变得更加易于访问。

    备注: 你可以根据我们完成的例子检查你的工作,请看 items-sold-scope.html([查看在线运行版本)和 items-sold-headers.html查看在线运行版本)。

    总结

    关于 HTML 表格你还可以学习其他一些东西,但是我们目前已经把大部分你需要知道的内容都告诉你了。接下来,你可以在 HTML 表格测评中测试自己的水平了,祝你玩得开心!

    如果你已经在学习 CSS,并且在评估中表现良好,你就可以继续学习 HTML 表格的样式,参见样式化表格

    如果你想要入门 CSS,请前往 CSS 学习区

    HTML 中的表单和按钮

    HTML 表单和按钮是与网站用户交互的强大工具。它们通常为用户提供控件,以便在需要时操作用户界面 (UI) 或输入数据。

    本文将介绍表单和按钮的基础知识。虽然还有很多内容需要了解——很多输入类型和表单功能并未提及——但本文将为您打下坚实的基础,助您应对大多数情况。您可以根据需要学习高级或专业的用法,这将成为您职业生涯中持续学习的一部分。

    先决条件: 熟悉基本的 HTML,如 基本 HTML 语法中所述。文本级语义,如标题、段落列表结构化 HTML
    学习成果:
    • 认识到表格和按钮以及链接是用户与网站互动的主要工具。
    • 不同的按钮类型。
    • 常见<input>类型。
    • 常见属性如namevalue
    • 元素<form>以及表单提交的基础知识。
    • 通过标签和正确的语义使表单易于访问。
    • 其他控制类型:<textarea>、、<select><option>
    • 客户端验证基础知识。

    与用户互动

    到目前为止,在本课程中,您已经了解了用户与 Web 交互的几种方式:

    • 链接可用于导航到同一页面或不同页面上的不同内容部分。
    • <video>元素<audio>通常具有播放/暂停、快进、快退等控制功能,使用户可以按照自己的意愿消费媒体内容。

    然而,这些功能往往助长了单向互动,用户被动地消费内容。这当然没问题,但网络是一种双向体验。网站用户可以根据自己的偏好来选择内容和服务的体验方式。他们叫出租车,并要求回电;他们提供反馈和投诉;他们购买产品,并要求送货上门。

    为了提供这种双向体验,您需要使用按钮和表格。

    按钮通常使用 HTML<button>元素创建(有时也会使用<input>元素属性设置为或type等值来创建)。这些按钮用途广泛——您可以连接它们来触发任何您想要的功能,唯一的限制就是您的想象力和编程技能。buttonsubmit

    表单使用诸如<form><label><input>和 等元素创建<select>。表单元素可用于创建比简单按钮更复杂的控件,例如包含多个选项的下拉菜单,可让您为用户界面元素选择不同的主题。

    然而,至关重要的是,它们也可以用来创建表单,供用户在需要向网站服务器提交信息时填写。想想电子商务网站——当你想搜索要购买的商品时,你会使用表单输入搜索词。当你想支付某些商品并完成配送时,你会使用一个表单输入你的邮政地址,并使用另一个表单输入你的信用卡信息。

    本文将主要讨论这种更传统的表单元素用法。需要注意的是,按钮在表单内部也常用来将输入的数据提交到服务器。

    了解了这个重要理论后,让我们继续探索代码并了解按钮和表单是如何实现的。

    按钮

    如上所述,按钮在 Web 上有几个主要用途。首先,它们用于触发功能,这在创建 UI 控件时非常有用。最简单的按钮使用以下代码实现:

    <button>Press me</button>
    

    呈现如下:

     

     标签之间的文本<button></button>会渲染到按钮内部,浏览器会为其添加一些基本样式,使其默认的外观和行为与按钮类似。目前为止,一切顺利。然而,这里有一个问题——我们这个单独的按钮本身并不能执行任何有用的操作。为了让它执行一些有用的操作,你需要将它放入表单中(我们稍后会介绍),或者添加一些 JavaScript。

    例如,如果您将以下 JavaScript 应用于上述按钮: 

    const btn = document.querySelector("button");
    btn.addEventListener("click", () => {
      btn.textContent = "YOU CLICKED ME!! ❤️";
      setTimeout(() => {
        btn.textContent = "Press me";
      }, 1000);
    });
    

     它会给你以下输出——尝试点击它:

     

    你暂时不需要理解 JavaScript 的工作原理。你将在课程的后续部分学到更多。

    在下一节中,您将看到按钮的第二个主要用途的演示——提交表单。

    表单的解剖

    基本形式包含三件事:

    • 一个<form>元素,包裹着所有其他表单内容。<form></form>标签内的所有表单控件都属于同一表单,提交表单时会包含这些控件的数据。
    • 一个或多个由一个<label>元素和一个表单控制元素组成的对(通常是一个<input>元素,但也有其他类型,例如<select>):
      • 表单控制元素允许用户选择或输入一些数据,这些数据将在表单提交时发送到服务器。
      • <label>元素提供与表单控件相关的标识标签,描述应输入到其中的数据。
    • 一个<button>元素,用于提交表单。

    让我们看一个包含上述三项的基本示例。此表单可用于询问用户的姓名和电子邮件,以便他们注册新闻通讯(不用担心 - 它没有连接到任何服务器,因此目前不会执行任何操作)。

     

    <form action="./submit_page" method="get">
      <h2>Subscribe to our newsletter</h2>
      <p>
        <label for="name">Name (required):</label>
        <input type="text" name="name" id="name" required />
      </p>
      <p>
        <label for="email">Email (required):</label>
        <input type="email" name="email" id="email" required />
      </p>
      <p>
        <button>Sign me up!</button>
      </p>
    </form>
    

    呈现如下:

     

    元素<form>​

    正如我们之前所说,<form>元素充当表单的外部包装器,将所有表单控件组合在一起。当<button>按下 时,表单控件所表示的所有数据都将提交到服务器。<form>元素可以采用许多属性,但我们在此列出的是最重要的两个属性:

    • action:包含我们要将提交的表单数据发送到哪个页面进行处理的路径。稍后,提交表单后,您将/submit_page在 URL 中看到 。您还会收到404错误响应,因为该页面实际上并不存在,但目前这样就没问题了。
    • method:指定要用于将表单数据发送到服务器的数据传输方法get。目前无需过多担心;该值会将数据作为参数附加到 URL 末尾发送。

     

    结构化形式

    您可以在元素内包含任何您喜欢的 HTML 元素<form>来构造表单元素本身,并提供容器以便使用 CSS 进行样式设置等。

    在我们的示例中,我们包含了标题元素<h2>)来描述表单的用途。

    我们还将每个输入/标签对以及提交按钮放在单独的 中<p>,以便它们各自出现在单独的行上。这些元素默认都是内联的,这意味着如果我们不这样做,它们就会全部位于同一行。

    这是表单结构的常见模式。有些人使用<p>元素 来分隔表单元素,有些人使用<div><section>或 even元素。这没什么大不了的,只要使用的元素语义合理即可。例如,将表单元素组划分为单独的段落或内容部分,甚至是列表中的项目都是有意义的。将它们表示为块引用旁白地址 则<li>不太合理。

    有一个专门用于将表单元素分组的元素,称为。这在某些情况下非常有用,例如在复杂的表单中,以及将多个复选框和单选按钮分组在一起时。我们稍后<fieldset>会看几个示例。<fieldset>

     

    <input>元素

    元素<input>代表了表单中输入的不同数据项。让我们来研究一下基本表单中的一个示例:

    <input type="text" name="name" id="name" required />
    

     

    属性如下:

    • type:指定要创建的表单控件的类型。表单控件有很多不同的类型,从不同类型的简单文本字段到单选按钮、复选框等等。Typetext会渲染一个可以接受任意值的基本文本字段。
    • name:指定数据项的名称。提交表单时,数据将以“名称/值”对的形式发送。在每种情况下,名称都等于此name属性值,值则等于在文本字段中输入的文本。
    • id:指定可用于标识元素的 ID。在本例中,它用于将表单控件与其关联起来<label>
    • required:指定必须在表单元素中输入值才能提交表单。该属性仅应在必填字段上设置,不应在可选字段上设置。

    您应该注意,某些输入类型通常不会从字段中输入的文本获取值。例如,<input type="color">渲染一个颜色选择器控件供您选择颜色,而<input type="radio">渲染一个单选按钮控件供您选择或不选择。

    对于单选按钮,通常需要在特定value属性中提供选中时提交的值。请注意,您可以value在输入类型(例如text和)上指定属性color——其效果是,该值会在表单字段首次渲染时预先填充到表单字段中。

     

    专用文本字段输入

    上面的第二个练习提出了一个有趣的观点。第二个输入字段明确要求输入电子邮件地址,并以此方式验证输入的值。如果你再次查看表单代码,你就会明白为什么——第二个输入字段<input>有一个typeemail有几种专门的文本字段输入类型,旨在处理特定类型的数据—— <input type="number"><input type="password"><input type="tel">等等。

     

    <label>元素

    正如我们上面所说,<label>元素提供与表单控件关联的标识标签,用于描述应输入的数据。您可以在<label>元素中放置任何文本内容,但它们应该准确描述关联的表单控件所需的数据。创建关联的方法是:为表单控件指定一个id属性,然后为<label>元素指定一个for与该控件的属性值相同的属性id

    例如:

    <label for="name">Name (required):</label>
    <input type="text" name="name" id="name" required />
    

    <label>元素之所以重要有几个原因,其中最显著的是:

    • 当视障用户使用屏幕阅读器来阅读和与网页内容交互时,屏幕阅读器会在遇到每个控件时读出相关的标签文本。这使得用户更容易理解应该在每个控件中输入什么内容。
    • 它们允许您通过点击标签文本和控件来聚焦表单元素。这对于手机用户尤其有用,因为在触摸屏上用手指准确选择表单元素可能比较困难。在这种情况下,增大点击区域会很有用。
    显式和隐式表单标签

    上面看到的表单标签样式称为显式表单标签——控件和标签之间的关联是通过id和属性显式建立的。你还可以通过将控件嵌套在标签中来for实现隐式表单标签,如下所示:

    <label>
      Name (required):
      <input type="text" name="name" required />
    </label>
    

    嵌套在控件和标签之间建立了隐式关联,您不再需要idfor属性。

    两种方法都可以,但我们建议使用显式标记方法。这是因为显式关联通常更容易识别和理解,尤其是在 HTML 代码越来越复杂的情况下。此外,屏幕阅读器(和其他辅助技术)并不总是能正确处理隐式标签。

    元素<button>​

    当一个<button>元素被包含在其他<form>元素中时,它的默认行为是提交表单,前提是不存在导致提交被客户端表单验证阻止的无效数据。您在使用上面的基本表单示例时已经看到过这种行为。

    还有其他按钮行为可以通过<button>元素的type属性指定:

    • <button type="submit">明确声明按钮的行为应类似于提交按钮。您实际上无需声明这一点,除非出于某种原因,您在 中包含了其他按钮<form>,并且您想明确指出哪个按钮是提交按钮。这种情况非常罕见。
    • <button type="reset">创建一个重置按钮——这会立即删除表单中的所有数据,并将其重置为初始状态。不要使用重置按钮——它们在网络早期曾很流行,但通常弊大于利。大多数人都有过这样的经历:填写一份很长的表单时,不小心点到了重置按钮而不是提交按钮,这意味着他们不得不重新开始。
    • <button type="button">创建一个按钮,其行为与元素外部指定的按钮相同<form>。正如我们之前所见,它们默认不执行任何操作,需要 JavaScript 来赋予它们功能。

     注意:<input>您也可以使用指定相同值的元素type<input type="submit"><input type="reset">和) 来创建上述按钮类型。<input type="button">但是,与<button>对应的元素相比,这些按钮类型有许多缺点。您应该使用<button>

    关于可访问性

    我们已经讨论过表单标签对于可访问性的重要性,但我们也想补充一些关于使用正确的语义元素创建表单的重要性(例如,使用<button>提交表单,而不是使用<div>使其行为类似于<button>)。完全可以结合使用 CSS 和 JavaScript,使几乎任何 HTML 元素的外观和行为都像表单元素。开发人员通常出于设计原因这样做——某些表单控件的样式难以设置。

    然而,这样做会给自己和用户带来更多麻烦。浏览器<button>默认提供了一些表单控制功能,无需 JavaScript 或其他额外代码,从而提升所有用户的表单可用性。

    例如:

    • 语义元素可以通过屏幕阅读器等辅助技术理解,并将其含义传达给无法看到它们的用户。
    • Tab表单控件和按钮默认可通过键盘访问。在上例中,尝试使用和Shift+ Tab(称为“Tab 键”)在表单元素之间前后移动。
    • 另请注意,在表单元素之间按 Tab 键会导致焦点元素以蓝色轮廓(称为焦点轮廓)突出显示。这对于键盘用户了解其当前在表单中的位置至关重要。

    如果你没有使用正确的语义元素来实现表单,你就必须重新实现所有这些功能,否则你的表单元素将无法按照用户预期的方式运行,从而导致表单看起来不完整。所有这些问题都会导致表单无法正常工作。

     

    其他控制类型

    您可以使用许多其他控件类型来收集表单中的数据。让我们看一个稍微复杂一点的示例,然后进行探讨和解释。

    注意: 在此示例中,我们假设用户已经注册并登录,因此不需要收集姓名和电子邮件等详细信息。

    <form action="./payment_page" method="get">
      <h2>Register for the meetup</h2>
      <fieldset>
        <legend>Choose hotel room type (required):</legend>
        <div>
          <input
            type="radio"
            id="hotelChoice1"
            name="hotel"
            value="economy"
            checked />
          <label for="hotelChoice1">Economy (+$0)</label>
    
          <input type="radio" id="hotelChoice2" name="hotel" value="superior" />
          <label for="hotelChoice2">Superior (+$50)</label>
    
          <input
            type="radio"
            id="hotelChoice3"
            name="hotel"
            value="penthouse"
            disabled />
          <label for="hotelChoice3">Penthouse (+$150)</label>
        </div>
      </fieldset>
      <fieldset>
        <legend>Choose classes to attend:</legend>
        <div>
          <input type="checkbox" id="yoga" name="yoga" />
          <label for="yoga">Yoga (+$10)</label>
    
          <input type="checkbox" id="coffee" name="coffee" />
          <label for="coffee">Coffee roasting (+$20)</label>
    
          <input type="checkbox" id="balloon" name="balloon" />
          <label for="balloon">Balloon animal art (+$5)</label>
        </div>
      </fieldset>
      <p>
        <label for="transport">How are you getting here:</label>
        <select name="transport" id="transport">
          <option value="">--Please choose an option--</option>
          <option value="plane">Plane</option>
          <option value="bike">Bike</option>
          <option value="walk">Walk</option>
          <option value="bus">Bus</option>
          <option value="train">Train</option>
          <option value="jetPack">Jet pack</option>
        </select>
      </p>
      <p>
        <label for="comments">Any other comments:</label>
        <textarea id="comments" name="comments" rows="5" cols="33"></textarea>
      </p>
      <p>
        <button>Continue to payment</button>
      </p>
    </form>
    

    呈现如下: 

     

    我们建议您在单独的浏览器标签页中打开此示例,以便学习接下来的几个部分,我们将依次介绍每种控件类型。为此,请使用代码编辑器将代码复制到 HTML 文件中,然后在浏览器标签页中打开它。 

     

    单选按钮

    “选择酒店房间类型”按钮是通过<input type="radio">控件实现的。这些控件呈现为一组按钮控件,每次只能选择一个——您不能同时选择多个。它们的名字来源于老式收音机上的按钮,按下一个按钮后,之前选择的按钮会再次弹出。

    我们的示例代码如下所示:

    <fieldset>
      <legend>Choose hotel room type (required):</legend>
      <div>
        <input
          type="radio"
          id="hotelChoice1"
          name="hotel"
          value="economy"
          checked />
        <label for="hotelChoice1">Economy (+$0)</label>
    
        <input type="radio" id="hotelChoice2" name="hotel" value="superior" />
        <label for="hotelChoice2">Superior (+$50)</label>
    
        <input
          type="radio"
          id="hotelChoice3"
          name="hotel"
          value="penthouse"
          disabled />
        <label for="hotelChoice3">Penthouse (+$150)</label>
      </div>
    </fieldset>
    

     

    radio输入类型的工作方式与输入类型基本相同text,但有一些区别:

    • name每组单选按钮的属性必须包含相同的值,才能将它们关联为一个集合。如果它们包含不同的值,则它们实际上将是独立的集合,提交时将具有不同的值。
    • 您必须value为每个单选按钮添加一个包含要提交值的属性。提交的值将是一个名称/值对,但名称始终相同,例如hotel=economyhotel=superior
    • 每个单选按钮<label>的 应该描述该特定值的选择,而不是您选择的整体值。提供整体值选择的描述的首选方式是将它们包装在 中<fieldset>,该 元素将一个<legend>包含描述的元素作为子元素。

    注意: 除了构造和标记表单之外,字段集还有其他用途,例如将一整组控件作为一个单元禁用。 

    禁用表单控件

    在单选按钮示例中,您会注意到第三个单选按钮disabled设置了该属性。这会导致渲染的控件变灰且不可选择。这在很多情况下非常有用,因为某些选项通常可用,只是现在不可用。例如,某个产品可能缺货,或者像我们示例中的情况一样,顶层套房已被全部预订!

    disabled您可以在任何表单控件(包括元素)上设置属性<button><fieldset>元素也可以接受该disabled属性 - 这会导致字段集内的每个表单控件都被禁用。

     

    复选框

    我们的“待选课程”选择器使用控件实现<input type="checkbox">。这些控件呈现为一组开启/关闭状态的复选框。与单选按钮不同,您可以一次选择多个复选框。

    <fieldset>
      <legend>Choose classes to attend:</legend>
      <div>
        <input type="checkbox" id="yoga" name="yoga" />
        <label for="yoga">Yoga (+$10)</label>
    
        <input type="checkbox" id="coffee" name="coffee" />
        <label for="coffee">Coffee roasting (+$20)</label>
    
        <input type="checkbox" id="balloon" name="balloon" />
        <label for="balloon">Balloon animal art (+$5)</label>
      </div>
    </fieldset>
    

    从代码片段中可以看出,单选按钮和复选框的实现方式非常相似(它们也可以使用checked属性,以便在页面加载时将其呈现为预选状态)。它们的行为方式也相当相似,只是单选按钮允许您从多个选项中选择零个或一个,而复选框允许您从多个选项中选择零个或多个。

    主要区别(除了type值!)在于每个复选框都有不同的name值,而且它们通常没有属性。从行为上讲,这意味着它们代表不同的数据值,而单选按钮集只代表一个值。提交时,如果复选框被选中,value则每个值都会提交一个值—— 、等等。onyoga=onballoon=on

     注意: 可以通过为复选框添加value属性来更改其提交的值,例如:选中<input type="checkbox" id="yoga" name="yoga" value="yes" />时将yoga=yes提交。但是,这样做意义不大。复选框要么在选中时提交单个值,要么根本不提交。发送到服务器的值实际上并不重要。

     

    下拉菜单,例如我们示例中的“您如何到达这里”选择控件,不是通过<input>类型实现的,而是通过<select><option>元素实现的

    <label for="transport">How are you getting here:</label>
    <select name="transport" id="transport">
      <option value="">--Please choose an option--</option>
      <option value="plane">Plane</option>
      <option value="bike">Bike</option>
      <option value="walk">Walk</option>
      <option value="bus">Bus</option>
      <option value="train">Train</option>
      <option value="jetPack">Jet pack</option>
    </select>
    

     

    <select>元素包含所有不同的值选项。您可以在这里设置将id控件与其标签关联的属性,以及name设置要提交的数据项名称的属性。

    数据项的每个可能值都由一个元素表示<option>,该元素嵌套在<select>元素内部。每个<option>元素都可以带有一个value属性,该属性指定在下拉列表中选择该选项时要提交的值。如果您未指定value,则将使用标签内的文本<option></option>作为值。

     注意: 如果您希望在页面加载时选择特定选项,您可以selected向相关<option>元素添加属性。

    多行文本输入字段

    使用元素创建多行文本输入字段<textarea>

     

    <label for="comments">Any other comments:</label>
    <textarea id="comments" name="comments" rows="5" cols="33"></textarea>
    

    它们的行为与元素相同<input type="text">,只是允许输入多行文本。rows属性指定文本区域默认的行数,cols属性指定文本区域默认的列数。如果未指定,则使用cols="20"和 的值rows="2"

    表单验证

    之前,我们了解了浏览器提供的一些基本的客户端表单验证。该required属性用于指定在提交表单之前必须填写的字段;它还会检查输入的特定值类型(例如电子邮件地址、URL、数字等)是否正确。验证之所以重要,主要有两个原因:

    • 确保数据以正确的格式提交,以免导致应用程序出现错误。
    • 确保数据不会造成安全问题。不法分子知道如何提交特殊格式的数据,以便在不安全的应用程序上执行删除数据库或控制系统的命令。

    表单验证是一个很大的话题,超出了本文的讨论范围,所以我们暂时就不展开了。只需记住,表单验证有两种类型:

    • 客户端验证发生在浏览器中,使用表单验证属性(例如required)和 JavaScript 的组合实现。客户端验证在用户输入错误数据时能够立即提示用户,但在阻止恶意数据入侵方面效果不佳。关闭 JavaScript 或修改客户端代码很容易导致验证失效。
    • 服务器端验证,在服务器上进行,使用服务器所使用的任何语言实现。格式错误的消息可能会被有意或无意地发送到服务器。传统做法是确保服务器不信任客户端发送的任何内容,以避免格式错误的消息导致错误或安全问题。服务器端验证非常适合阻止恶意消息,因为它更难篡改服务器上运行的代码。服务器端验证不太擅长向用户提示数据错误,因为数据必须发送到服务器进行验证,然后将结果返回客户端才能通知用户。

    简而言之,无需在客户端验证和服务器端验证之间犹豫不决——两者皆需。您需要客户端验证来为用户提供输入反馈,而服务器端验证则用于确保消息采用服务器能够安全处理的格式。如果您想进一步了解验证,那么客户端表单验证是一个不错的起点。

     

    概括

    暂时就这些。关于表格还有很多知识需要了解,但目前我们已经让你对它有了足够的了解,可以继续学习了。


    网站公告

    今日签到

    点亮在社区的每一天
    去签到