网络版报告二之HTML

HTML 基础学习。

HTML 基础语法

在本文中,我们将介绍最基础的 HTML 知识。为了让你快速入门,本文将定义元素、属性以及你可能听过的所有其他重要术语,并解释它们在 HTML 中的作用。你将学习 HTML 元素的结构、一个典型 HTML 页面的结构,以及其他重要的基本语言特性。在此过程中,你也将有机会动手玩转 HTML!

什么是 HTML?

HTML 由一系列元素组成。元素由一个开始标签(如 <p>),中间的文本内容和一个结束标签(如 </p>)构成。

剖析元素

元素的结构图如下

元素之间可以嵌套,也就是一个元素可以放置在别的元素内部,如下

1
<p>我们的小猫脾气<strong></strong>暴躁。</p>

并非所有元素都遵循开始标签、内容和结束标签的模式。有些元素只包含一个标签,通常用于在文档中插入/嵌入某些东西。这类元素被称为空元素。例如,<img> 元素可以插入一个图像文件。

1
2
3
<img
src="https://raw.githubusercontent.com/mdn/beginner-html-site/gh-pages/images/firefox-icon.png"
alt="Firefox 图标" />

属性

属性包含关于元素的额外信息,这些信息不会出现在内容中。

一个属性应该有:

  • 一个在它和元素名之间的空格。(对于拥有多个属性的元素,属性之间也应该用空格分隔。)
  • 属性名,后跟一个等号。
  • 一个属性值,用开始和结束的引号包裹。

现在又轮到你了。在这一节中,我们将让你向 <img> 元素添加属性,以便在页面上显示一张图片。<img> 元素可以接受多个属性,包括:

  • src:一个必需的属性,指定图像的位置。例如:src="https://raw.githubusercontent.com/mdn/beginner-html-site/gh-pages/images/firefox-icon.png"
  • alt:图像的文本描述。例如:alt="Firefox 图标"
  • width:图像的宽度,单位为像素。例如:width="300"
  • height:图像的高度,单位为像素。例如:height="300"

布尔属性

有时你会看到没有值的属性。这是完全可以接受的。这些被称为布尔属性

布尔属性是靠属性名在不在标签里来工作的:

  • 属性在 → 功能开启(True)
  • 属性不在 → 功能关闭(False)

不管你给它写什么值,甚至写 false,只要它出现在标签里,布尔属性总是被设置为 true。

规范要求该属性的值要么是空字符串(包括属性没有明确指定值时),要么与属性的名称相同。

例如,考虑 disabled 属性,你可以把它赋给表单输入元素。(你可以用它来禁用表单输入元素,这样用户就不能输入内容了。被禁用的元素通常呈现为灰色。)例如:

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

作为简写可以这样写

1
<input type="text" disabled />

不要省略属性值周围的引号

HTML 语法其实很“宽容”,允许属性值可以不加引号,但是这种做法并不规范,容易引起问题。

比如,下面代码片段中的 <a> 元素被称为锚点。锚点包裹文本,并将其变成链接。href 属性指定了链接指向的网址。你可以只用 href 属性写出这个基本版本,像这样:

1
<a href=https://www.mozilla.org/>最喜欢的网站</a>

锚点也可以有一个 title 属性,用来描述链接的页面。然而,一旦我们像 href 属性一样添加 title,问题就来了:

1
<a href=https://www.mozilla.org/ title=The Mozilla homepage>最喜欢的网站</a>

如上所示,浏览器会误解标记,将 title 属性误认为三个属性:一个值为 Thetitle 属性,以及两个布尔属性 Mozillahomepage。显然,这不是我们想要的!它会导致错误或意想不到的行为,正如你在下面的实时示例中看到的那样。试着将鼠标悬停在链接上查看标题文本,显示只有“The”。

在本文中,你会注意到属性都是用双引号包裹的。然而,你可能在某些 HTML 代码中看到单引号。这是一个风格问题。你可以随意选择你喜欢的一种。下面这两行是等效的:

1
2
3
<a href='https://www.example.com'>一个指向示例的链接。</a>

<a href="https://www.example.com">一个指向示例的链接。</a>

但是,如果你使用一种类型的引号,你可以在属性值内部包含另一种类型的引号(下面的单引号是会出现在内容中的):

1
2
3
<a href="https://www.example.com" title="你觉得'好玩吗'?">
一个指向示例的链接。
</a>

如果要在相同类型的引号内使用引号(单引号或双引号),请使用字符引用。例如,这样做会出错:

1
<a href="https://www.example.com" title="一个"有趣"的引用">一个指向示例的链接。</a>

相反,你应该这样做:

1
<a href="https://www.example.com" title="一个&quot;有趣&quot;的引用">一个指向示例的链接。</a>

剖析HTML文档

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

1
2
3
4
5
6
7
8
9
10
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>我的测试页面</title>
</head>
<body>
<p>这是我的页面</p>
</body>
</html>

这里我们有:

  1. <!doctype html>:文档类型声明(doctype)。在 HTML 早期(1991-1992 年),doctype 旨在作为一套规则的链接,HTML 页面必须遵循这些规则才能被认为是好的 HTML。过去的 doctype 看起来像这样:

    html复制

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

    最近,doctype 成为了一个历史遗留物,为了让其他一切正常工作而必须包含它。<!doctype html> 是算作有效 doctype 的最短字符序列。你只需要知道这些!

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

  3. <head></head><head>元素。这个元素充当一个容器,用于存放你想包含在 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 中的空白

在上面的例子中,你可能注意到代码中包含了很多空白。这是可选的。这两个代码片段是等效的:

1
2
3
4
5
<p id="noWhitespace">狗狗很 呆 萌。</p>

<p id="whitespace">狗狗很

萌。</p>

无论你在 HTML 元素内容中使用了多少空白(可以包括一个或多个空格字符,也包括换行),HTML 解析器在渲染代码时都会将每个空白序列减少为单个空格。那么为什么要使用这么多空白呢?答案是可读性。

如果你的代码格式整齐,就更容易理解代码中发生了什么。在我们的 HTML 中,每个嵌套的元素都比它所在的元素多缩进两个空格。选择什么样的格式化风格(例如,每个缩进级别使用多少空格)由你决定,但你应该考虑格式化它。

让我们看看浏览器如何渲染上面带有和不带空白的两个段落:

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

在 HTML 中,字符 <>"'& 是特殊字符。它们是 HTML 语法本身的一部分。那么你如何在文本中包含这些特殊字符之一呢?例如,如果你想使用一个与号或小于号,而不是让它被解释为代码。

你需要使用字符引用,这些是代表字符的特殊代码,用于在这些确切的情况下使用。每个字符引用都以一个与号(&)开始,并以一个分号(;)结束。

字符 具名参考 英文解析与记忆法 Unicode 码位
& &amp; AMPersand (和号) 记忆:AMP 代表 And U+00026
< &lt; Less Than (小于) 记忆:L 代表 Less U+0003C
> &gt; Greater Than (大于) 记忆:G 代表 Greater U+0003E
" &quot; QUOTation mark (双引号) 记忆:QUOT 取自 Quotation U+00022
' &apos; APOStrophe (单引号) 词源:指示所有格的符号 U+00027
``(空格) &nbsp; Non-BreaKing Space (不间断空格) 记忆:NBKSP U+000A0
&ndash; Number Dash (短横线/半角破折号) 用途:表示数字范围,如 1–5 U+02013
&mdash; MuDdle Dash (长破折号/全角破折号) 记忆:MDASH 中间有 D U+02014
© &copy; COPYright (版权) 记忆:直接取 COPY U+000A9
® &reg; REGistered (注册商标) 记忆:REG 代表 Registered U+000AE
&trade; TRADE mark (商标) 记忆:TRADE 代表商标交易 U+02122
&asymp; ASYMPtotically equal (约等于) 记忆:ASYMP 代表渐近等于 U+02248
&ne; Not Equal (不等于) 记忆:NE 代表 Not Equal U+02260
£ &pound; POUND Sterling (英镑) 记忆:POUND 本身就是英镑 U+000A3
&euro; EURO (欧元) 记忆:直接取 EURO U+020AC
° &deg; DEGree (度) 记忆:DEG 代表 Degree(度数) U+000B0

字符引用的等效项可以很容易记住,因为它使用的文本可以看作是 &lt; 对应“less than(小于)”,&quot; 对应“quotation(引语)”,其他类似。

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

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

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

在下面的实时输出中,你可以看到第一段出错了。浏览器将第二个 <p> 实例解释为开始一个新段落。第二段看起来很好,因为它用字符引用替换了尖括号。

备注:只有前5个字符 <>"'& 是必须用字符引用来写的,其他符号只要你的 HTML 字符编码设置为 UTF-8 ,理论上像 ©½这些符号,你直接敲键盘或者用输入法打出来,浏览器都能正常显示

HTML 注释

要编写 HTML 注释,请将其包裹在特殊标记 <!----> 中。例如:

1
2
3
<p>我不在注释里</p>

<!-- <p>但我在注释里</p> -->

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

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

什么是 HTML 头部

我们先回顾上一章的 HTML 文档

1
2
3
4
5
6
7
8
9
10
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>我的测试页面</title>
</head>
<body>
<p>这是我的页面</p>
</body>
</html>

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

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

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

添加标题

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

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

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

代码如下

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>&lt;title&gt; element</title>
</head>
<body>
<h1>&lt;h1&gt; element</h1>
</body>
</html>

显示效果如下,现在很明显的可以看到 <h1><title> 出现的地方!

<title> 元素也被以其他的方式使用着。比如说,如果你尝试为某个页面添加书签,你会看到 <title> 的内容被作为建议的书签名。

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

元数据:<meta> 元素

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

指定字符编码

在上面的示例中,这行是被包含的:设定字符编码为 UTF-8

1
<meta charset="utf-8" />

添加作者和描述

许多 <meta> 元素包含了 namecontent 属性:

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

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

1
2
3
4
5
6
<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." />

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

指定一个包括与你的页面内容有关的关键词的描述是有用的,因为它有可能使你的页面在搜索引擎进行的相关搜索中出现得更多.

**备注:**在谷歌搜索里,在主页面链接下面,你将看到一些相关子页面——这些是站点链接

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

其他类型的元数据

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

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

1
2
3
4
5
6
7
8
9
<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 上时,它具有相似的效果。例如下面:

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

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

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

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

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

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

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 含有高分辨率 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" />

在 HTML 中应用 CSS 和 JavaScript

CSS 解释样式问题,而 JavaScript 让网页有交互功能,比如视频播放器、地图、游戏以及更多功能。

这些应用在网页中很常见,它们分别使用 <link> 元素以及 <script>元素。

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

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

(上面说放到在正文底部——就在结束标签 </body> 之前,这样就不用 defer属性了;但是还是放在头部最好,加载速度更快,并且代码结构更加整洁,这是最佳实践 )

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

为文档设定主语言

最后,值得一提的是可以(而且有必要)为站点设定语言,这个可以通过添加 lang 属性到 HTML 开始的标签中来实现

1
2
3
<html lang="zh-CN">

</html>

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

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

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

HTML 的标题和段落

HTML 的主要工作之一是赋予文本结构,使浏览器能够按照开发者的意图显示 HTML 文档。

标题和段落

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

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

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

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

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

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

一共有 h1 - h6 共六级标题。

实现结构层级

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<h1>三国演义</h1>

<p>罗贯中</p>

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

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

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

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

<h3>却说张飞</h3>

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

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

  • 最好只对每个页面使用一次 <h1>——这是顶级标题,所有其他标题位于层次结构中的下方。
  • 在现有的六个标题层次中,除非觉得有必要,否则应该争取每页使用不超过三个。有很多层次的文件(例如,深层次的标题层次)会变得笨重,难以浏览。在这种情况下,如果可能的话,建议将内容分散到多个页面。

为什么我们需要结构化

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

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

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

  • 用户在阅读网页时,往往会快速浏览以查找相关内容,经常只是阅读开头的标题。如果用户不能在几秒内看到一些有用的内容,他们很可能会感到沮丧并离开。
  • 对网页建立索引的搜索引擎将标题的内容视为影响网页搜索排名的重要关键字。没有标题,你的网页在搜索引擎优化方面效果不佳。
  • 使用 CSS 样式化内容,或者使用 JavaScript 做一些有趣的事情,你需要包含相关内容的元素,使得 CSS / JavaScript 可以有效地定位它。

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

为什么我们需要语义?

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

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

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

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

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

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

强调与重要性

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

什么是强调和着重强调

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

强调

正常字体与斜体如下

我很庆幸你没有迟到。

我很庆幸你没有迟到

我们使用 <em> (emphasis,强调的意思,中文其实没有斜体的概念,因为方块字斜着不好看;英文才有斜体)元素来表示强调,方式是斜体。

但你不应该纯粹为了获得斜体风格而使用这个标签。如果仅仅为了获得斜体样式而不增加语义辅助,你应该使用 <span>元素和一些 CSS,或者是 <i>元素(见下文)。

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

着重强调

在 HTML 中我们用<strong >(strong importance)元素用粗体来表示着重强调。

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

1
2
3
<p>这杯液体<strong>毒性很大</strong></p>

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

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

1
2
3
<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 将默认的下划线改为在网页中更合适的东西。下面的例子说明了如何做到这一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 学名 -->
<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 有一套方便的元素,可以让我们定义不同类型的列表,这一点你可能不会感到惊讶。在 Web 中,我们有三种类型的列表:无序列表、有序列表和描述列表。本课将向你展示如何使用不同类型的列表。

无序列表

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

无序列表从 <ul>元素开始,然后使用 <li> (list item, 列表项)元素把每个列出的项目单独包裹起来

1
2
3
4
5
6
<ul>
<li>豆浆</li>
<li>油条</li>
<li>豆汁</li>
<li>焦圈</li>
</ul>

有序列表

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

有序列表从 <ol>元素开始,然后使用 <li> (list item, 列表项)元素把每个列出的项目单独包裹起来

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

嵌套列表

将一个列表嵌入到另一个列表是完全可以的。你可能想让一些子项目列在一级项目之下。

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

1
2
3
4
5
6
7
<li>
在锅里留下约两大匙油,烧热后将切好的干辣椒下锅,用小火炒香后,再放入花椒粒和葱段一起爆香。随后鸡丁重新下锅,用大火快炒片刻后,再倒入“综合调味料”继续快炒。
<ul>
<li>如果你采用正宗川菜做法,最后只需加入花生米,炒拌几下就可以起锅了。</li>
<li>如果你在北方,可加入黄瓜丁、胡萝卜丁和花生米,翻炒后起锅。</li>
</ul>
</li>

描述列表

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

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

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

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

单个术语的多个描述

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

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

构建文档

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

文档的基本组成部分

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

  • 页眉

    通常是一个横跨顶部的大条带,上面有一个大标题、徽标,或许还有一个标语。这通常在网站的各个页面上保持不变。

  • 导航栏

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

  • 主内容

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

  • 侧边栏

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

  • 页脚

    横跨页面底部的条带,通常包含细小文字、版权声明或联系信息。它是放置常用信息(如页眉)的地方,但通常这些信息对网站本身并不重要。页脚有时也用于 SEO,提供快速访问热门内容的链接。

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

用于构建内容的HTML

以上简单示例不是很精美,但是足够说明网站的典型布局方式了。一些站点拥有更多列,其中一些远比这复杂,但一切在你掌握之中。通过使用正确的 CSS,你可以使用几乎任何元素来环绕不同的部分,并获得你想要的外观,但正如之前所讨论的,我们需要尊重语义,使用正确的元素来完成正确的工作

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

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

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

  • 页眉<header>
  • 导航栏<nav>
  • 主内容<main>。主内容中还可以有各种子内容区段,可用 <article><section><div> 等元素表示。
  • 侧边栏<aside> 。经常放置在 <main> 中。
  • 页脚<footer>

HTML布局元素细节

学习 CSS 布局(CSS 主题的一部分)时再讨论。

HTML 布局元素细节

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

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

通过点击上述每个元素,可在“HTML 元素参考”部分阅读相应的文章,了解每个元素的更多细节。

无语义包装器

有时你会发现,对于一些要组织的项目或要包装的内容,现有的语义元素均不能很好对应。有时候你可能只想将一组元素组合在一起,用 CSS 或 JavaScript 将它们作为一个整体加以影响。为了应对这种情况,HTML 提供了 <div><span>元素。应配合使用 class 属性提供一些标签,使这些元素能易于定位。

<span>是一个行级无语义元素(行级就是说它不会换行,和前面或后面的内容还在同一行里),最好只用于无法找到更好的语义元素来包含内容时,或者不想增加特定的含义时。例如:

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

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

<div> (Division,分区/分割)是一个块级无语义元素(块级就是说会出现在新行上),应仅用于找不到更好的块级元素时,或者不想增加特定的意义时。例如,一个电子商务网站页面上有一个一直显示的购物车组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="shopping-cart">
<h2>购物车</h2>
<ul>
<li>
<p>
<a href=""><strong>银耳环</strong></a
>:$99.95
</p>
<img src="../products/3333-0985/" alt="银耳环" />
</li>
<li>……</li>
</ul>
<p>总消费:$237.89</p>
</div>

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

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

换行与水平分割线

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

<br>:换行元素

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

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

没有 <br> 元素,这段会直接显示在长长的一行中(如前文所讲,HTML 会忽略大部分空格)。

<hr>:主题性中断元素

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

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

规划一个简单的网站

在规划好单个网页的结构后,下一阶段就是规划整个多页面网站的结构,包括如何排列和相互链接,以获得最佳的用户体验。这些工作称为信息架构。

在大型、复杂的网站中,大多数规划工作都可以归结于此,而对于一个只有几个页面的简单网站,规划设计过程可以更简单,更有趣!

过程大概是这样的:

  1. 时刻记住,大多数(不是全部)页面会使用一些相同的元素,例如导航菜单以及页脚内容。若网站为商业站点,不妨在所有页面的页脚都加上联系方式。请记录这些对所有页面都通用的内容,例如:

    • 页眉
      • 标题和徽标
      • 站点语言选择器
    • 导航栏
    • 页脚
      • 版权声明
      • 至条款、联系方式和无障碍政策的链接
  2. 接下来,可为页面结构绘制草图(这里与前文那个站点页面的截图类似)。记录每一块的作用:

  3. 对页面内容进行头脑风暴

  4. 对内容进行分组,这样可以让你了解哪些内容可以放在同一个页面。

  5. 可以尝试绘制一个粗略的网站地图——为网站上的每个页面划一个框,并画线表示页面之间的典型工作流程。主页可能位于顶部或中心位置,并链接到大多数页面(如果不是所有页面的话)。小型网站中的大多数页面都应该可以从主导航中找到,但也有例外。你可能还需要说明如何展示网站内容。

创建超链接

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

什么是超链接?

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

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

链接的解析

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

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

块级链接

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

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

它将标题转化为了链接。

图片链接

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

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

它将 MDN 徽标转化为了链接

使用 title 属性添加支持信息

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

1
2
3
4
5
6
7
8
<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/

路径快速入门:

  • 当前目录:直接写文件名

  • 子目录:举例 projects/index.html ,则超链接如下

    1
    <p>请访问我的<a href="projects/index.html">项目主页</a></p>
  • 上层目录 : 举例 ../pdfs/project-brief.pdf ,则超链接如下

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

文档片段

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

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

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

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

你甚至可以在同一份文档下,通过链接文档片段,来链接到当前文档的另一部分:(注:“链接的地方”(目标)和“超链接”(入口)在文档的位置不需要满足上下关系,二者是完全独立的,只要 idhref的名字对得上,就能成功跳转。)

1
<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 访问

不管绝对 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 文件而突然发生变化——这将使你的链接指向错误的位置,因此如果单击它,它将无法工作。你得小心点!

链接最佳实践

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

使用清晰的链接措辞

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

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

下面是一个具体的例子:

好的链接文本

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

不好的链接文本

1
2
3
<p>
<a href="https://www.mozilla.org/zh-CN/firefox/">点击这里 </a>下载 Firefox
</p>

其他提示:

  • 不要在链接文本中说“链接”或“链接到”——它只是无用的内容。屏幕阅读器告诉人们有一个链接。可视化用户也会知道有一个链接,因为链接通常是用不同的颜色设计的,并且存在下划线(这个惯例一般不应该被打破,因为用户习惯了它)。
  • 保持你的链接标签尽可能短——这非常重要,因为屏幕阅读器需要解释整个链接文本。
  • 尽量减少相同文本的多个副本链接到不同地方的情况。如果存在标记为“单击此处”、“单击此处”、“单击此处”这样脱离上下文的链接文本,容易对使用屏幕阅读器的用户带来问题。

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

当链接到一个需要下载的资源(如 PDF 或 Word 文档)或流媒体(如视频或音频)或有另一个潜在的意想不到的效果(打开一个弹出窗口),你应该添加明确的措辞,以减少混乱。

如下的例子会让人反感:

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

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

1
2
3
4
5
6
7
8
9
10
11
<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属性

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

1
2
3
4
5
<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>

电子邮件链接

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

其最基本和最常用的使用形式为一个指明收件人电子邮件地址的 mailto: 链接。例如:

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

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

指定详细信息

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

下面是一个包含 cc、bcc、主题和主体的示例

1
2
3
4
<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 查询标记方法是更常用的。

作业:构建网页内容

需要做的事情是修改 HTML 文件,包括:

你应该为以下内容添加合适的标签:

  • 页眉
  • 导航菜单
  • 主要内容
  • 欢迎语
  • 图片侧边栏
  • 页脚

还应:

  • 添加一个 <link>元素把现成的 CSS 文件引入页面。

修改后的 index.html 如下,这里引入了2个样式表,第一个是谷歌字体,引入龙藏体( family=Long+Cang 毛笔书法字体)和思源黑体(Noto+Sans+SC:300 ,字重 300);第二个是你自己写的CSS文件,里面会引用这两个字体。(注意顺序,因为浏览器会按顺序加载并执行,因此必须先加载字体,这可能需要点时间,再加载 style.css )。

我感觉这种从网址加载字体不好,缺点

  1. 需要网络,不能随时打开
  2. 加载需要时间
  3. 网址可能会崩,造成字体打不开(虽然概率很低)
  4. 谷歌好像会获取IP地址

实在要用,还是要下载下来(但是我看还是挺大的,几十MB)。

正文部分就是按照之前的文档结构设置的,只是这里正文部分必须加一个 <article> 元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>观鸟网</title>
<link href="https://fonts.googleapis.com/css?family=Long+Cang|Noto+Sans+SC:300" rel="stylesheet">
<link href="style.css" rel="stylesheet">

<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>

<body>
<header>
<h1>观鸟网</h1>
<img src="dove.png" alt="一张鸽子剪影图片">
<nav>
<ul>
<li><span>主页</span></li>
<li><a href="#">开始</a></li>
<li><a href="#">图片</a></li>
<li><a href="#">设备</a></li>
<li><a href="#">论坛</a></li>
</ul>
</nav>
</header>


<main>
<article>
<h2>欢迎</h2>

<p>欢迎访问观鸟网虚拟站点。如果这是一个真实的网站,那么它就是观鸟爱好者的理想聚集地。无论你是一名期望学习观鸟知识的新手,还是一位希望分享体会、经验和图片的观鸟老手。</p>
<p>时不我待!赶快带齐装备,关上电脑,去拥抱美丽的大自然吧!</p>
</article>
<aside>
<h2>收藏照片</h2>

<a href="favorite-1.jpg"><img src="favorite-1_th.jpg" alt="一只体型小巧的鸟,羽毛蓝绿色,爪黑白相间,黑色的喙细且锋利。点击缩略图查看完整照片。"></a>
<a href="favorite-2.jpg"><img src="favorite-2_th.jpg" alt="一只美丽的孔雀的上半身图片,它的颈上覆盖蓝色的羽毛,有浅色的喙和蓝色的冠。点击缩略图查看完整照片。"></a>
<a href="favorite-3.jpg"><img src="favorite-3_th.jpg" alt="一只大鸟的上半身图片,羽毛白色,浅色的喙细长而弯曲。点击缩略图查看完整照片。"></a>
<a href="favorite-4.jpg"><img src="favorite-4_th.jpg" alt="一只成年鹈鹕,羽毛大多为白色,背部和腹部有少许黑色羽毛,又长又直的喙呈黄色,喙的下方有一个喉囊可以暂时储存食物。点击缩略图查看完整照片。"></a>
</aside>

</main>


<footer>
<p>本虚拟站点遵守 CC0 协议,所有内容均可任意修改和复用。原始版本由 Chris Mills 于 2016 年编写。Roy Tian 于 2019 年汉化。</p>
<p><a href="http://game-icons.net/lorc/originals/dove.html">鸽子图标</a> 由 Lorc 绘制。</p>
</footer>
</body>
</html>

HTML 中的图片

最初,web 仅有文字,非常乏味。幸运的是,不久之后,我们就能在网页中嵌入图片和其他更有趣的内容类型了。尽管有多种多媒体类型需要考虑,但是从在网页中嵌入简单图片的 <img>元素开始更加合理。

怎样将图片放到网页上?

<img>元素是一个空元素,需要两个属性,src 属性和 alt 属性。

  • src 属性包含一个 URL,该 URL 指向要嵌入页面的图像。src 属性可以是相对 URL 或绝对 URL,这与 <a> 元素的 href 属性类似。

  • alt 属性是图片的文本描述,用于在图片无法显示或者因为网速慢而加载缓慢的情况下使用。

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

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

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

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

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

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

**警告:*未经许可,*绝不要将 src 属性指向其他网站上的图像。这被称为“热链接(hotlinking)”。大多数人认为这是不道德的,因为这会导致每当有人访问你的页面,都会有另一些不知情的人为图像交付带宽费用。这也导致你无法掌控图像,图像有可能在你不知情的情况下,被删除或替换为尴尬的内容。

解释一下,原因如下

  1. 偷用别人的带宽,每次有人访问你的网页,浏览器都要去别人的服务器把图片下载下来。结果:别人的服务器会产生流量费用(电费、服务器租金),而你却一分钱不付。
  2. 失去控制权,图片不在你手里,在别人手里。别人可以随时删掉图片,或者把图片换成别的内容。

备选文本

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

1
2
3
4
<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 属性里,随你喜欢(我看之前代码都是放在图片的 alt 属性里)。
  • 文本:你不应该将文本放到图像里。例如,如果你的主标题需要有阴影,你可以用 CSS来达到这个目的,而不是把文本放到图片里。如果真的必须这么做,那就把文本也放到 alt 里。

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

宽度和高度

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

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

1
2
3
4
5
6
<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,并在图片接收到后立即更新页面。

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

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

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

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

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

图像标题

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

1
2
3
4
5
6
7
<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 有很多无障碍问题,这些问题主要是基于这样一个事实,即屏幕阅读器的支持并不完善,除此之外大多数浏览器都不会显示它,除非你将鼠标悬停在上面(例如:无法使用键盘的用户)。

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

媒体资源和许可

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

了解许可类型

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

版权所有

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

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

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

自由许可

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

例如,你可能需要:

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

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

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

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

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

公共领域/CC0

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

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

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

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

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

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

某些搜索引擎会提供工具,帮助你查找具有自由许可的图像。例如,使用 Google 时,转到“图片”选项卡搜索图像,然后单击“工具”。在结果工具栏中有一个“使用权限”下拉菜单,你可以选择专门搜索根据创作共用许可授权的图像(这也不能随便用,有的可能标注了**“NC”(Non-Commercial,非商业性使用)**,而且 CC 协议大部分都要求必须标明原作者和出处)。

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

以下是目前最靠谱的无版权图库,全部可以放心用在商业报告中(AI 说 Pixabay 最放心 ):

图库 网址 授权协议 特点
Pixabay pixabay.com Pixabay License(类CC0) 550万+图片,含矢量图、插画、视频
Unsplash unsplash.com Unsplash License 高质量摄影作品,适合商业报告配图

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

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

1
2
3
4
5
6
7
8
9
10
<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> 元素,它正是为此而被创造出来的:为图片提供一个语义容器,在说明文字和图片之间建立清晰的关联。我们之前的例子可以重写为:

1
2
3
4
5
6
7
8
9
10
11
12
<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-* 属性是用来控制背景图片的。比如,要想为页面中的每个段落设置一个背景图片,你可以这样做:

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

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

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

网页上的其他图形

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

略。

视频和音频内容

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

web 中的音频和视频

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

<video> 元素

<video> 元素用于嵌入视频,举例如下

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

值得注意的特性有:

  • src : 视频资源的路径

  • controls : 用户应当能够控制视频和音频的播放。你必须使用 controls 属性来让视频或音频包含浏览器自带的控制界面,或者使用适当的 JavaScript API 构建自己的界面。至少,界面必须包括启动和停止媒体以及调整音量的方法。

  • <video> 元素内的段落

    这个叫做后备内容,当浏览器不支持

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

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

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

更新后的例子如下

1
2
3
4
5
<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 属性,浏览器会尝试加载每一个文件,直到找到一个能正确播放的格式,但是这样会消耗掉大量的时间和资源。

其他特性省略。

<audio> 元素

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

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

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

因为音频播放器没有视觉部件,它所占用的空间比视频播放器要小(你只需要显示出能控制音频播放的控件),除了没有视觉部件的属性外,<audio> 元素支持所有 <video> 元素的特性

显示视频文本

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

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

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

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

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

  • subtitles

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

  • captions

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

  • 定时描述

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

一个典型的 WebVTT 文件如下:

1
2
3
4
5
6
7
8
9
10
11
WEBVTT

1
00:00:22.230 --> 00:00:24.606
第一段字幕

2
00:00:30.739 --> 00:00:34.074
第二段


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

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

如下是例子:

1
2
3
4
5
<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 表格基础

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

什么是表格?

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

创建表格的过程如下

  1. 每个表格的内容均包含在这两个标签中:<table></table>
  2. 在表格中,最小的内容容器是单元格,是通过 <td> 元素创建的(其中“td”代表“table data”)。多个 <td> 元素组成了一行。
  3. 每一行的单元格采用 <tr> 元素(其中“tr”代表“table row”)

示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<table>
<tr>
<td>1r1c</td>
<td>1r2c</td>
<td>1r3c</td>
<td>1r4c</td>
</tr>
<tr>
<td>2r1c</td>
<td>2r2c</td>
<td>2r3c</td>
<td>2r4c</td>
</tr>
</table>

使用 <th> 元素添加标题

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<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>

显示的效果如下

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

使用 <th> 元素指定标题(其中“th”代表“table header”),这样在视觉上和语义上都能被识别为标题,用法和 <td>是一样的,除了它表示为标题,不是普通的单元格以外。

修改后的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<table>
<tr>
<th>&nbsp;</th>
<th>诺基</th>
<th>弗洛尔</th>
<th>艾拉</th>
<th>胡安</th>
</tr>
<tr>
<th>品种</th>
<td>杰克罗斯犬</td>
<td>贵宾犬</td>
<td>流浪犬</td>
<td>可卡犬</td>
</tr>
<tr>
<th>年龄</th>
<td>16</td>
<td>9</td>
<td>10</td>
<td>5</td>
</tr>
<tr>
<th>主人</th>
<td>岳母</td>
<td></td>
<td></td>
<td>嫂子</td>
</tr>
<tr>
<th>饮食习惯</th>
<td>吃掉所有人的剩菜</td>
<td>啃咬食物</td>
<td>吃得多</td>
<td>吃到爆炸为止</td>
</tr>
</table>

展示效果如下

为什么标题是有用的?

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

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

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

允许单元格跨越多行和列

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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>

显示效果如下

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

让我们使用 colspanrowspan 来改进现有的表格。

  1. 接着,使用 colspan 让“动物”、“河马”和“鳄鱼”横跨两列。
  2. 最后,使用 rowspan 让“马”和“鸡”竖跨两行。
  3. 保存后,用浏览器打开你写的 HTML 文件,看看改进的地方。

改后的代码如 <th colspan=2>动物</th> ,效果如下

为表格中的列提供共同的样式

不使用 <col> 应用样式

在继续阅读之前,我们将在本文介绍最后一个特性。HTML 有一种为整列数据的定义样式信息的方法:就是 <col><colgroup> 元素。它们存在是因为如果你想让一列中的每个数据的样式都一样,那么你就要为每个数据都添加一个样式,这样的做法是令人厌烦和低效的。你通常需要在列中的每个 <td><th> 上定义样式,或者使用一个复杂的选择器,比如:nth-child()

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

下面是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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> 容器内指定。可以通过如下方式指定表格,来创建与上述相同的效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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> 元素即可,就像这样:

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

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

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

所以如果有样式表的情况下,列背景不会显示为黄色。原因是列样式(<col>)先渲染,然后是样式表中的单元格(<th>/<td> )样式,因此样式表中的颜色盖住了列样式的颜色。

HTML 表格进阶特性与无障碍

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

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

使用 <caption> 为你的表格增加一个标题,要放在 <table> 开始标签的下面。

1
2
3
4
5
6
7
<table>
<caption>
侏罗纪时期的恐龙
</caption>


</table>

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

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

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

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

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

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

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

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

举例如下

1
2
3
4
5
6
<tfoot>
<tr>
<td colspan=4>SUM</td>
<td>118</td>
</tr>
</tfoot>

嵌套表格

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

用不上,表格没法嵌套的,看上去很难看,pass

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

不涉及这一块,没必要弄复杂,pass

表单和按钮

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

本文将介绍表单和按钮的基础知识。实际上还有很多内容值得了解——比如各种输入类型和表单特性在此尚未提及,但本文将为你打下应对大多数场景的坚实基础。你可以根据需要逐步学习更高级或更特定的用法,这也是你在职业生涯中持续学习的一部分。

用户交互

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

  • 链接
  • 视频/音频

然而,这些功能通常更偏向于单向交互,让用户被动地消费内容。虽然这没问题,但 Web 是一种双向体验。网站用户会根据自己的喜好调整内容和服务的使用方式。他们可能会叫车、申请回电、提交反馈、进行投诉、网购商品并送货到家。

要实现这种双向交互体验,你需要使用按钮和表单。

按钮通常是通过 HTML 的 <button> 元素创建的(有时也使用 <input>元素并将其 type 属性设置为 buttonsubmit 值)。这些按钮用途广泛——你可以将它们与任意功能关联,实现什么功能只取决于你的想象力和编码能力。

表单是通过 <form><label><input><select>等元素创建的。与简单的按钮相比,表单元素可以创建更复杂的控件——例如包含多个选项的下拉菜单,允许用户在不同的用户界面主题之间进行选择。

更重要的是,它们还可以用于创建表单,供用户在需要向网站服务器提交信息时填写。以电商网站为例——当你想搜索需要购买的商品时,会使用表单输入关键词;当你想付款并确认收货地址时,会使用表单填写邮寄地址,再用另外一个表单填写你的信用卡信息。

本文将主要探讨表单元素的传统用法。需要注意的是,按钮也常用于表单中,用于向网站服务器提交用户填写的数据。

讲完这些重要的理论,我们接下来将通过代码来探索按钮和表单是如何实现的。

按钮

正如上文所提到的,按钮在网页上有几种用途。首先,它们可用于触发某些功能,这在创建用户界面(UI)控件时非常有用。最简单的按钮可以通过以下代码实现如下:

1
<button>点击这里</button>

呈现出来的效果如下:

出现在 <button></button> 标签的文字会显示在按钮内部,并且浏览器会为其应用一些基础样式,使它默认看起来和表现得像一个按钮。到目前为止,一切正常。不过,这里有一个问题。这个孤零零的按钮本身不会执行有用的任何操作。为了让这个按钮变得实用起来,你需要将它放入表单中(我们稍后将会讲解),或者为它添加一些 JavaScript。

例如,如果你将下面的 JavaScript 代码添加到上述按钮中:

1
2
3
4
5
6
7
const btn = document.querySelector("button");
btn.addEventListener("click", () => {
btn.textContent = "你点击了这个按钮!! ❤️";
setTimeout(() => {
btn.textContent = "点击这里";
}, 1000);
});

点击后会弹出文字"你点击了这个按钮!! ❤️"

你现在不需要去理解这段 JavaScript 是如何工作,你将在本课程的后续内容中学习到更多知识。

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

表单的结构

一个基础的表单包含以下三个部分:

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

我们来看一个包含上述三项内容的基本示例。这个表单将用于收集用户的姓名和电子邮件地址,以便订阅新闻简报(不必担心——它目前尚未连接任何服务器,因此不会真正执行任何操作)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>第一个表单</title>
</head>
<body>
<form action="./submit_page" method="get">
<h2>订阅我们的新闻简报</h2>
<p>
<label for="name">姓名(必填):</label>
<input type="text" name="name" id="name" required />
</p>
<p>
<label for="email">邮箱(必填):</label>
<input type="email" name="email" id="email" required />
</p>
<p>
<button>订阅新闻简报!</button>
</p>
</form>
</body>
</html>

呈现出来的效果如下:

如果你立刻点击“订阅新闻简报”按钮,会看见一个验证错误,因为没有填写任何数据。如果你填写了姓名和邮箱地址后再点击该按钮,则会看到一个 404 错误页面。

以下是图片中的文字内容:

<form>元素

正如前面提到的,<form>元素作为表单的外层容器,用于将所有的表单控件组织到一起。当点击 <button>按钮时,所有在表单控件中填写的数据将会被提交到服务器。<form>元素可以包含多个属性,我们在示例中使用的两个最重要的属性是:

  • action:包含一个路径,用于指定提交的表单数据将发送到哪个页面进行处理。稍后,当你提交表单时,你会在 URL 中看到 /submit_page。你还会收到一个 404 错误响应,因为处理数据的页面实际上并不存在,但目前这样做是没有问题的。
  • method:指定将表单数据发送到服务器时使用的数据传输方法。现在你不必太过担心这个属性;当值为 get时,数据会作为参数附加在 URL 的末尾进行发送。

检查提交的数据

  1. 在单独的浏览器标签页打开示例,尝试输入姓名“Bob”,电子邮件地址为“bob@bob.com”。
  2. 点击 <button>

actionmethod属性会使表单数据以下列 URL 形式提交:

1
/some/url/submit_page?name=Bob&email=bob%40bob.com

以下是图片中的文字内容:

结构化表单

你可以在 <form>元素中包含任意的 HTML 元素,用于组织表单控件本身,并为 CSS 样式提供可定位的容器,以便进行样式设置等操作。

在示例中,我们使用了一个标题元素(<h2>)来描述该表单的用途。

我们还将每一对输入框/标签和提交按钮分别放在一个单独的 <p> 元素中,这样每一组控件就会独占一行上。这些元素默认是行内(inline)的,这意味着如果我们不这么做,所有的控件将会处于同一行上。

这是表单结构化的常见形式。一些人使用 <p> 元素来分割表单控件,一些人使用 <div><section>甚至是 <li>元素。只要使用的元素在语义上合理,这些其实并没有太大区别。例如,将表单项分组放在不同的段落或者内容区块中,或者作为列表项是合乎语义的。但使用块级引用元素、侧边栏元素或者是联系人地址元素来表示就不太合适。

还有一个专门用来对表单控件进行分组的元素:<fieldset>。当表单较复杂,或需要把多个复选框、单选按钮归为一组时,它就非常有用。稍后我们会给出几个 <fieldset>的示例。

以下是图片中的文字内容:

<input>元素

<input>元素表示用户在表单中输入的各种数据项。让我们来看一个基础表单中的例子:

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

这些属性的含义如下:

  • type:指定要创建的表单控件类型。表单控件类型有很多,从各种简单的文本字段,到单选按钮、复选框等。当值为 text 时,会渲染一个可接受任意文本的基本文本框。
  • name:为该数据项指定一个名称。当表单提交时,数据会以名值对(name/value pairs)的形式发送。一般来说,name 属性的值就是这个数据项的“名称”,而用户在文本框输入的数据就是这个数据项的“值”。
  • id:指定一个用于标识该元素的 ID。在这里,它用于将该表单控件与对应的 <label>标签关联起来。
  • required:指定该表单控件在提交表单前必须填写。这应仅用于必填字段,而不应设置在可选字段上。

你需要知道的是,有些输入类型的值并不是用户直接在字段中输入的。例如 <input type="color">会显示一个取色器,你可以从中选择颜色;<input type="radio">会显示一个单选按钮,可以被选中也可以不被选中。

对于单选按钮,一般需要在 value 属性中指定一个具体的值,表示当该按钮被选中时,提交到服务器的实际内容。注意,你可以在 text 和 color 等输入类型上也设置 value 属性,其效果是:表单控件在初次渲染完成时就预先填充这个值。

required 和 value 属性的实际效果

  1. 再次打开你之前在单独的浏览器标签页上加载的示例,尝试在两个字段都未填写任何内容的情况下提交表单。你会在“Name”字段旁看到一条错误提示,例如“请填写此字段”(不同浏览器的提示内容可能会有所不同)。这就是 required 属性和浏览器默认的客户端表单验证机制在起作用。
  2. 接着,尝试在第一个字段中输入一个有效的名字,但在第二个字段中输入一个无效的邮箱地址(例如 “aaaa”)。这时你会在“Email”字段旁看到另一条错误提示,例如“请输入邮箱地址”。
  3. 现在尝试修改表单,在第一个 <input> 中加入 value="Bob"。当你重新加载页面时,会看到第一个输入框中默认填入了“Bob”。

特定类型的文本输入框

上面的第二个练习引出了一个有趣的问题。第二个输入字段特别要求输入一个邮箱地址,并会对填写的内容进行邮件格式的验证。如果你再次查看表单代码,就能发现原因——第二个 <input> 元素的 typeemail。实际上,有许多专门用于处理特定类型数据的文本字段输入类型,例如:<input type="number"><input type="password"><input type="tel"> 等等。

<label> 元素

如上所述,<label> 元素为表单控件提供了标识性标签,用于描述应该在控件中输入的数据。你可以在 <label> 元素中放置任意文本内容,但这些内容应准确描述关联表单控件所期望的数据类型。标签与控件之间的关联方式是:给表单控件设置一个 id 属性,然后给 <label> 设置 for 属性,其值与该控件的 id 相同。

例如:

1
2
<label for="name">姓名(必填):</label>
<input type="text" name="name" id="name" required />

<label> 元素的重要性体现在多个方面,尤其包括以下几点:

  • 当视力障碍用户使用屏幕阅读器浏览和操作网页内容时,屏幕阅读器在遇到每个控件时,会朗读与之关联的标签文本。这能让用户更容易理解每个控件需要输入什么内容。
  • 它们允许用户不仅可以点击控件本身,还可以点击标签文本来聚焦表单控件。这对移动设备用户尤其有用,因为在触摸屏上用手指精确选择表单控件可能比较困难。在这种情况下,扩大 可点击区域 会非常有帮助。

显式与隐式表单标签

你在上文中看到的标签样式被称为显式表单标签——控件与标签之间的关联是通过 idfor 属性显式建立的。你也可以通过将控件嵌套在标签内的方式实现 隐式表单标签,如下所示:

1
2
3
4
<label>
姓名(必填):
<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>元素。

关于无障碍的小提示

我们之前已经提到过表单标签在无障碍性方面的重要性,但我们还想补充一些关于正确使用语义化 HTML 元素创建表单的重要性。(例如,使用 <button> 提交表单,而不是使用一个借助 CSS 和 JavaScript 模拟出来的 <div> 元素)。你确实可以利用 CSS 和 JavaScript 把几乎任何 HTML 元素“伪装成”表单控件,看起来像是一个按钮、输入框、下拉菜单等。开发者这么做通常是出于设计上的考虑——某些原生表单控件确实比较难自定义样式。

然而,这么做反而会增加你和用户的负担。事实上,浏览器已经默认为 <button> 和其他表单控件提供了许多便利功能,无需额外的 JavaScript 或代码,就能让表单更易于使用。

例如:

  • 语义化元素可以被屏幕阅读器等辅助技术识别,并将内容传递给视觉障碍的用户。
  • 表单控件和按钮默认支持键盘访问。在先前的示例中,你可以尝试使用 Tab 和 Shift + Tab 切换表单元素(这种操作被称为“Tab 键导航”)。
  • 你还会注意到,当你使用 Tab 在表单元素间进行切换时,当前聚焦的元素会被蓝色轮廓标记出来(称为焦点轮廓)。这对于使用键盘进行操作的用户来说非常重要,因为它帮助用户知道自己目前操作的是哪一项。

如果你使用错误的语义化元素来构建表单,你就得自己手动实现这些功能,否则这些表单元素就无法按照用户预期的方式工作,甚至会被认为是“坏掉了”。所有这些细节都会影响用户体验。

其他控件类型

单选按钮、复选框、下拉菜单等等

先pass,用到再补上。

表单验证

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

  • 确保提交的数据格式正确,从而避免在应用程序中引发错误。
  • 防止数据引发安全问题。恶意用户可能会提交特意构造的数据,在不安全的应用中,这些数据可能会执行删除数据库或控制系统等命令。

表单验证是一个非常庞大的话题,超出了本文的范围,因此我们不会详细展开,只做简单介绍。需要注意的是,表单验证主要有两种类型:

  • 客户端验证:在浏览器端进行,通常通过表单验证属性(如 required)和 JavaScript 结合实现。客户端验证可以即时提示用户输入有误,但它并不可靠,不能有效阻止恶意数据。因为用户可以关闭 JavaScript 或修改客户端代码,从而绕过验证。
  • 服务器端验证:在服务器上进行,使用服务器端所采用的任意语言实现。错误格式的数据可以是意外发送的,也可以是有意而为之。经验法则是:服务器永远不要信任客户端发送的任何数据,以避免由于格式错误的消息而引发漏洞或安全问题。服务器端验证更适合阻止恶意消息,因为服务器端代码更难被篡改。但它无法像客户端验证那样及时给用户反馈,因为数据必须先发送到服务器验证,服务器再把结果返回给用户。

简而言之,不要只选择客户端验证或服务器端验证——你需要两者结合。你需要客户端验证来为用户的输入提供即时反馈;同时也需要服务器端验证,来确保发送到服务器的消息格式是安全、可处理的。

HTML调试

HTML 并不像 Rust 那么难以理解,浏览器并不会将 HTML 编译成其他形式,而是直接解析并显示结果(称之为解释,而非编译)。可以说 HTML 的 元素 语法比 Rust、JavaScript 或 Python 这样“真正的编程语言”更容易理解。浏览器解析 HTML 的过程比编程语言的编译运行的过程要宽松得多,但这是一把双刃剑。

宽松的代码

宽松是什么意思呢?通常写错代码会带来以下两种主要类型的错误:

  • 语法错误:由于拼写错误导致程序无法运行,就像上面的 Rust 示例。通常熟悉语法并理解错误信息后很容易修复。
  • 逻辑错误:不存在语法错误,但代码无法按预期运行。通常逻辑错误比语法错误更难修复,因为无法得到指向错误源头的信息。

HTML 本身不容易出现语法错误,因为浏览器是以宽松模式运行的,这意味着即使出现语法错误浏览器依然会继续运行。浏览器通常都有内建规则来解析书写错误的标记,所以即使与预期不符,页面仍可显示出来。当然,是存在隐患的。

**备注:**HTML 之所以以宽松的方式进行解析,是因为 Web 创建的初心就是:人人可发布内容,不去纠结代码语法。如果 Web 以严格的风格起步,也许就不会像今天这样流行了。

HTML 验证

阅读以上示例后,你发现保持良好 HTML 格式的重要性。那么应该如何做呢?以上示例规模较小,查找错误还不难,但是一个非常庞大、复杂的 HTML 文档呢?

最好的方法就是让你的 HTML 页面通过 Markup Validation Service。由 W3C(制定 HTML、CSS 和其他网络技术标准的组织)创立并维护的标记验证服务。把一个 HTML 文档加载至本网页并运行,网页会返回一个错误报告。

网页可以接受网址、上传一个 HTML 文档,或者直接输入一些 HTML 代码。

如果你不能一次弄懂所有的错误,别着急,可以试试先修复那些已经弄懂的,再申请验证,看看剩下哪些错误。有时候先修复的错误可能让你摆脱后面一系列的错误,因为一个小问题可能引发一连串错误,就像多米诺骨牌。

所有错误都修复之后会得到以下输出:

参考文献

  1. https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Structuring_content
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2019-2026 Vincere Zhou
  • 访问人数: | 浏览次数:

请我喝杯茶吧~

支付宝
微信