什么是无障碍？ - 学习 Web 开发

什么是无障碍？
=======

* Overview: Accessibility
* 下一页

本文作为本模块的开篇阐述了究竟什么是“无障碍” — 主要包括哪些用户群体是我们所需要和为什么需要考虑的，不同用户使用哪些工具与网页交互，以及我们在网站开发流程中如何构建无障碍。

|  |  |
| --- | --- |
| 前提： | 基本的计算机知识，对 HTML 和 CSS 的基本理解。 |
| 目标： | 熟悉无障碍，包括它是什么，以及它对 web 开发人员的影响。 |

什么是无障碍？
-------

无障碍是一种让尽可能多的用户可以使用你的网站的做法。传统上我们认为这只与残疾人士有关，但提升网站的无障碍也可以让其他用户群体受益。比如使用移动设备的人群，那些使用低速网络连接的人群。

你也可以把无障碍看成是同等地对待每一个人，给他们平等的机会，无论他们的能力或所处的环境如何。就像不能让坐轮椅的人可以进入大楼是错误的 (现代公共建筑通常有轮椅坡道或电梯)；不能让视觉有障碍的人士可以浏览我们的网站同样不正确。我们都是不同的，但我们都是人，因此享有同等的人权。

使网站具备无障碍才是正确的做法。它也是一些国家法律的一部分，它打开了一些重要的市场，否则那些市场的用户无法使用你的服务或者购买你的产品。

建立可访问的网站能让每个人都受益：

* 使用原语 HTML(译注：仅使用非样式标记而样式用 CSS 定义的 HTML 称为原语 HTML。那些描述内容呈现效果的标记如<b>标记是样式标记，这些样式标记在 HTML5 中已经废弃），不仅提升了无障碍，也增强了搜索引擎优化，使你的网站更容易被找到。
* 关心无障碍表露出良好的道德品质，它提升了你的公众形象。
* 其他一些改善无障碍的做法也会让你的网站更容易被其他群体使用，比如手机用户，低速网络环境的用户等等。事实上，每个人都可以从这此改善中受益。
* 我们是否也曾提到过到这也是某些地方的法律规定？
我们应关注的残疾都有哪些种类？
---------------

残疾人士和正常人一样是多样化的，他们身患的残疾也多种多样。此处课题的关键是抛开思考你自己的电脑和你自己使用网页的方式，而是要开始了解别人如何使用网页——你不是你的用户。接下来会讲解需要考虑的主要残疾类型，以及他们访问网页内容时用到的一些特殊工具 (被称为辅助技术或 ATs)。

**备注：** 世界卫生组织的“残疾和健康”状况说明书指出：“超过 10 亿人，约占世界总人口的 15%，患有某种形式的残疾”，而且“有 1.1 亿至 1.9 亿之间的成年人在身体功能上存在重大困难。”

### 有视觉障碍的人

有视觉障碍的人包括盲人、视力水平低下者、色盲。许多视觉障碍人士使用屏幕放大镜，要么是物理放大镜或是软件缩放功能。现今大多数浏览器和操作系统都具备缩放功能。某些用户使用屏幕阅读器，这是一种可以大声朗读数字文本的软件。一些屏幕阅读器的示例如下：

* 有些是付费产品，比如 JAWS (Windows) 和 Window Eyes (Windows).
* 有些是免费产品，比如 NVDA (Windows)， ChromeVox (Chrome, Windows 和 Mac OS X)，和 Orca (Linux).
* 有些内置在操作系统中，比如 VoiceOver (Mac OS X and iOS)， Narrator (Microsoft Windows)， ChromeVox (on ChromeOS)，和 TalkBack (Android).

让自己熟悉屏幕阅读器是个好主意；你还应该设置一个屏幕阅读器并充分的使用它（盘它），以了解它是如何工作的。请参阅我们的跨浏览器屏幕阅读器测试向导，以了解更多使用它们的细节。下面的视频还提供了一个简单的例子说明了体验是怎样的。

据统计，世界卫生组织估计“全球有 2.85 亿人视力受损：3900 万人失明，2.46 亿人视力低下。”(参见视力障碍和失明)。这是一个庞大而重要的用户群却仅因为你的网站没有合理的设计代码而流失——几乎相当于美国的人口总数。

### 有听觉障碍的人

也被称为有听力障碍的人或聋子，这群人要么听力水平较低要么或者完全听不到。这些人使用辅助技术（请参考 听力、语音、说话或语言障碍患者的辅助设备），但是并没有专用于计算机/网页的辅助技术。

但是，现在有专门的技术用于将文本转换成音频内容，范围从转换简单的文本文字到转换与视频一起显示的字幕。稍后，有文章将讨论这些技术。

听力受损的人也代表着一个重要的用户群体——“全世界有 4.66 亿人患有听力障碍”，世界卫生组织的耳聋和听力受损状况报告如此宣称。

### 行动障碍的人

这些人在行动方面存在着残疾，可能是因为纯粹的身体问题（例如肢体丧失或瘫痪），或导致肢体无力或失去控制的神经系统/遗传疾病。有些人可能难以做出使用鼠标所需的精准手部动作，而另一些人则可能受到的影响更为严重，可能会严重瘫痪到需要使用头部指针与计算机进行交互的地步。

这种残疾也可能是由于年老体衰导致，而不是任何特定的创伤或状况造成，也可能是由于硬件限制所致——有些用户可能没有鼠标。

这些残疾通常影响 Web 开发工作的方式是要求通过键盘就可以访问控件——我们将在本模块的后续文章中讨论键盘无障碍，但最好是仅通过使用键盘来尝试访问一些网站，看看你能够做些什么。例如，你可以使用 Tab 键在 Web 表单的不同控件之间移动吗？你可以在我们的“跨浏览器测试使用本机键盘的无障碍”章节中找到有关键盘控制的更多详细信息。

据统计，有相当多的人患有行动障碍症。美国疾病控制与防御中心的“残疾与机能（18 岁及以上的非住院成年人）”报道称美国有 15.1% 的成年人都患有身体功能疾病。

### 有认知障碍的人

认知障碍涵盖了一类范围广泛的残疾，从能力最受限的智障人士到随着年龄增长而导致思考和记忆困难的所有人。该范围包括了患有精神疾病的人，例如抑郁症和精神分裂症患者。还包括有学习障碍的人，例如阅读障碍患者和有注意力缺陷的多动症患者。重要的是，尽管认知障碍的临床定义存在很多差异，但与之相关的人们会遇到同一类功能问题。这类问题包括很难理解页面内容，难以记住如何完成任务，以及因不一致的网页布局而产生困惑。

对认识障碍人士来说一个好的无障碍机制包括：

* 使用多种方式传达内容，比如从文本到语音或是视频；
* 更易理解的内容，例如使用更通俗的语言书写的文本；
* 将注意力集中在重要内容上；
* 尽量减少干扰，例如不必要的内容或广告；
* 一致的网页布局和导航；
* 相似的元素，比如未访问的下划线链接使用蓝色而访问过的使用紫色；
* 将过程划分为更有逻辑的，必要的步骤并附上进度指示器；
* 在不影响安全性的情况下尽可能让网站认证更简单；并且
* 使表单容易完成，例如带有清晰的错误消息和简单的错误恢复。
### 注意

* 具有认知无障碍 (en-US)的设计将导致良好的设计实践。他们将使所有人受益。
* 许多有认知障碍的人也可能患有身体残疾。网站必须遵循 W3C 的“网页内容无障碍指南”包括认知无障碍指南 (en-US)。
* W3C 的“认知和学习残疾无障碍专案组”为认知障碍人士制作了 web 无障碍指南。
* WebAIM 有一个认知网页提供了相关的信息和资源。
* 美国疾病控制中心估计，截至 2018 年，美国四分之一的公民有残疾，其中认知障碍是年轻人最常见的疾病。
* 在美国，“智力障碍”是“智力低下”的新术语。在英国，“智力障碍”通常是指“学习障碍”或“学习困难”。
在你的项目中实现无障碍
-----------

一个流行的关于无障碍的传言认为：无障碍是实施在项目上的昂贵“附加功能”。这个传言确实可能成立，只要遇到以下任一情况：

* 你正在试图为一个现有存在重大无障碍问题的网站“改造”无障碍。
* 你只是在项目后期才开始考虑无障碍和此时才暴露的相关问题。

然而如果你能在项目的开始阶段就考虑到无障碍的话，使大多数内容无障碍化的代价就会相当微小。

在规划项目时，将无障碍测试纳入测试体系，就像对其他任何重要目标受众群体（例如台式机或移动浏览器的目标用户）进行测试一样。尽早和经常进行测试，理想情况下运行自动化测试找出程序化方式可检测到的缺失功能（例如，缺少图像替代文本或不良链接文字——请参阅元素关系与上下文），并对残疾人士的用户群进行一些测试，以查看更复杂的网站功能是否对他们可用。例如：

* 我的日期选择器小部件是否可供使用屏幕阅读器的人使用？
* 如果内容动态更新，视力受损的人知道吗？
* 我的 UI 按钮是否可以使用键盘和触碰界面进行访问？

你可以并且应该在内容中记下潜在的问题区域，这些地方需要进行一些工作才能使其变得可访问，确保对其进行了彻底的测试并考虑解决方案/替代方法。文本内容（如你将在下一篇文章中看到的）相对容易，但是多媒体内容和时髦的 3D 图形又如何呢？你应该查看项目预算，并考虑可以使用哪些解决方案来实现这类内容的无障碍。转录所有多媒体内容是一种选择，当然成本可能很高。

还有，现实一点。“100% 的无障碍”是一个无法实现的理想——你总是会遇到某种边缘情况，导致某个用户发现某些内容难以使用——但你应该尽你所能去做。如果你计划包含一个使用 WebGL 呈现的时髦三维饼图，你可能希望也包含一个数据表，作为数据的可访问的替代表示。或者，你可能只需要包含表而去除 3D 饼图——这样每个人都可以访问该表，编写起来也更快，还能减少运行时的 CPU 耗费，维护也更容易。

另一方面，如果你正在一个画廊网站上展示有趣的 3D 艺术，期望每件艺术品都能被视觉障碍人士完美的访问是不合理的，毕竟它是一种完全的视觉媒体。

为了表明你关心并考虑了无障碍，请在你的网站上发布无障碍声明，其中详细说明你对无障碍的政策以及为使该站点可访问而采取的步骤。如果有人确实反映你的网站存在无障碍问题，请与他们展开对话，保持同情心，并采取合理的步骤尝试解决问题。

**备注：** 我们的“处理常见的无障碍问题”一文涵盖了应更详细地测试的无障碍细节。

总结：

* 从项目一开始就考虑无障碍，并尽早进行测试。就像任何其他 bug 一样，越晚发现无障碍问题，修复它的代价会更高。
* 请记住，许多无障碍的最佳实践对每个人都有好处，而不仅仅局限于残疾人士。例如，原语标记不仅对屏幕阅读器有好处，而且使加载速度和性能也更快，因此对每个人来说都更有益，尤其是那些使用移动设备和/或慢速网络连接环境的人。
* 在你的站点上发布无障碍声明，并与遇到问题的人接触。
无障碍指南和法律
--------

有许多可用于基于无障碍测试的检查列表和指南集，乍一看，这些准则可能会让人望而却步。我们的建议是让自己熟悉你需要注意的基本领域，以及理解与你最相关的指导方针的高层结构。

* 首先，W3C 发布了一个庞大而详细的文档，其中包含了非常精确的、与技术无关的无障碍一致性标准。这些被称为 Web 内容无障碍指南 (WCAG)，它们绝不是短读的。这些标准分为四大类，它们指定如何使实现具有可感知性、可操作性、可理解性和鲁棒性。最好的地方得到一个简单的介绍和开始学习是一目了然。没有必要用心学习 WCAG——注意主要关注的领域，并使用各种技术和工具来突出任何不符合 WCAG 标准的区域 (更多信息见下文)。
* 贵国还可能有具体立法，规定为其人口提供服务的网站必须能够访问 - 例如，美国“康复法”第 508 条、德国关于无障碍信息技术的联邦法令、联合王国的“平等法”、意大利的“无障碍法”、澳大利亚的“残疾歧视法”等。

因此，虽然 WCAG 是一套指导方针，但你的国家可能会有关于网络无障碍的法律，或者至少是对公众提供的服务的无障碍 (包括网站、电视、物理空间等)。找出你的法律是个好主意。如果你不努力检查你的内容是否可访问，你可能会陷入法律的麻烦，如果有二重性的人抱怨它。

这听起来很严肃，但正如上文所述，你只需要将无障碍视为 Web 开发实践的主要优先事项。如果有疑问，请咨询合格的律师。我们不会提供比这更多的建议，因为我们不是律师。

无障碍 API
-------

Web 浏览器使用特殊的无障碍 API(由底层操作系统提供)，这些 API 公开对辅助技术 (ATS) 有用的信息-ATS 大多倾向于使用原语信息，因此这些信息不包括样式信息或 javascript 之类的内容。此信息是在一个称为无障碍树的信息树中构造的。

不同的操作系统有不同的无障碍 API：

* Windows: MSAA/IAccessible, UIAExpress, IAccessible2
* Mac OS X: NSAccessibility
* Linux: AT-SPI
* Android: Accessibility framework
* iOS: UIAccessibility

如果 Web 应用中的 HTML 元素提供的本机语义信息失效，则可以使用 WAI-ARIA specification 的功能来补充该信息，这些功能向辅助功能树添加语义信息以提高无障碍。在 WAI-ARIA basics 文章中了解有关 WAI-ARIA 的更多详细信息。

摘要
--

本文应该给你提供一个有用的无障碍的高级概述，向你展示为什么它是重要的，并研究如何将它融入你的工作流程。现在，你还应该渴望了解可以使站点可访问的实现细节，我们将在下一节中开始，了解为什么 HTML 是无障碍的良好基础。

* Overview: Accessibility
* 下一页
本章目录
----

* 什么是无障碍？
* HTML：无障碍的良好基础
* CSS 和 JavaScript 无障碍最佳实践
* WAI-ARIA 基础
* 多媒体无障碍
* 移动端无障碍
* 无障碍疑难解答
参见
--

* WCAG (en-US)
    + Perceivable (en-US)
    + Operable (en-US)
    + Understandable (en-US)
    + Robust (en-US)


HTML：无障碍的良好基础 - 学习 Web 开发

HTML：无障碍的良好基础
=============

* 上一页
* Overview: Accessibility
* 下一页

在网页开发的过程中，用正确的 HTML 标签来表达正确的意图，可以提升网页的无障碍。这篇文章将会详细介绍如何最大化地提升网页的无障碍。

|  |  |
| --- | --- |
| 前提： |
 有一定的 HTML 基础（可参阅
 HTML 入门），理解什么是无障碍。
  |
| 目标： | 了解无障碍为网页带来的好处和如何在网页中进行实现。 |

HTML 和无障碍
---------

在学习 HTML 的过程当中，经常可以看到这样一个主题：HTML 语义化的重要性。意思是指我们应尽可能地用正确的 HTML 标签来表达正确的意图。

你可能在想，为什么语义化对于一个网页来说如此重要。总的来说，正确的语义化可使 CSS 和 JavaScript 更为便利地操作网页的样式和行为。例如，一个用来操作视频播放的按钮可以写成这样一种形式：

```html
<div>Play video</div>
```

接下来你将看到一种更好的写法，它使用了正确的 HTML 标签，看上去更加合理：

```html
<button>Play video</button>
```

`<button>`标签不仅提供了按钮的样式（虽然有时会重新编写样式），还提供了键盘的无障碍，如：使用 tab 键更换按钮，使用回车键点击按钮。

如果你在项目的一开始就使用 HTML 语义化，不仅不会花更多的时间，而且又有以下的无障碍优点：

1. **更便于开发** — 如上所述，你可以使 HTML 更易于理解，并且可以毫不费力的获得一些功能。
2. **更适配移动端** — 语义化的 HTML 文件比非语义化的 HTML 文件更加轻便，并且更易于响应式开发。
3. **更便于 SEO 优化** — 比起使用非语义化的<div>标签，搜索引擎更加重视在“标题、链接等”里面的关键字，使用语义化可使网页更容易被用户搜索到。

让我们来继续学习 HTML 语义化实现细则。

**备注：** 在本地计算机上设置屏幕阅读器是一个不错的主意，因此你可以对下面显示的示例进行一些测试。更多内容请查阅 Screenreaders guide。

良好的语义
-----

上面我们讨论了语义化的重要性以及为什么我们要使用正确的 HTML 标签来表达正确的意图。语义化是我们不可忽视的一部分，因为它往往决定了网页的无障碍。

在网络上，事实上人们用 HTML 标签做一些非常奇怪的事情。人们滥用一些即将废弃或已经废弃的标签。不管在什么情况下，我们都应该将这些错误的代码改正过来。

话虽如此，但是有些情况我们往往不能摆脱错误的标签，例如一个网页是从服务端的框架生成的，或者网页上存在第三方的内容（如广告），这些都是我们所不能控制的。

我们的目标并不是“全有或全无”，实际上，你所做的每一个改进都可以提升网页的无障碍。

### 文本内容

对于屏幕阅读器用户来讲，最佳辅助功能之一是拥有标题，段落，列表等内容的良好结构。一个好的语义示例可能如下所示：

```html
<h1>My heading</h1>

<p>This is the first section of my document.</p>

<p>I'll add another paragraph here too.</p>

<ol>
  <li>Here is</li>
  <li>a list for</li>
  <li>you to read</li>
</ol>

<h2>My subheading</h2>

<p>
  This is the first subsection of my document. I'd love people to be able to
  find this content!
</p>

<h2>My 2nd subheading</h2>

<p>
  This is the second subsection of my content. I think is more interesting than
  the last one.
</p>
```

我们已经准备了一个更长的文本版本，供你试用于屏幕阅读器（请查看 good-semantics.html）。如果你尝试在此过程中导航，你将看到这非常容易导航：

1. 屏幕阅读器会在你浏览内容时读取每个标题，通知你标题是什么，段落是什么等。
2. 它在每个元素之后停止，让你以任何适合你的速度前进。
3. 你可以在许多屏幕阅读器中跳到下一个/上一个标题。
4. 你还可以在许多屏幕阅读器中显示所有标题的列表，使你可以像使用便利的目录一样使用它们以查找特定内容。

人们有时会使用表现性 HTML 和换行符来编写标题，段落等，如下所示：

```html
<font size="7">My heading</font> <br /><br />
This is the first section of my document.
<br /><br />
I'll add another paragraph here too.
<br /><br />
1. Here is
<br /><br />
2. a list for
<br /><br />
3. you to read
<br /><br />
<font size="5">My subheading</font>
<br /><br />
This is the first subsection of my document. I'd love people to be able to find
this content!
<br /><br />
<font size="5">My 2nd subheading</font>
<br /><br />
This is the second subsection of my content. I think is more interesting than
the last one.
```

如果你使用屏幕阅读器试用更长内容的版本（请查阅 bad-semantics.html），你不会有一个很好的经验 — 屏幕阅读器没有任何东西可以用作路标，所以你无法检索有用的目录，整个页面被看作一个巨大的块，所以它只是一次读出所有的内容。

除了无障碍之外，还有其他一些问题 - 使用 CSS 设计内容的风格更难，或者使用 JavaScript 来操作它比较困难，因为没有可用作选择器的元素。

#### 使用通俗易懂的语言

你使用的语言也会影响无障碍。一般来说，你应该使用不太复杂的清晰语言，不要使用不必要的行话或俚语。这不仅有利于有认知或其他残疾的人；它有利于那些没有用母语写作的读者，年轻人...事实上是每个人！除此之外，你应该尽量避免使用没有被屏幕阅读器清楚读出的语言和字符。例如：

* 如果可以避免的话，不要用破折号。写 5 到 7，来替代 5-7。
* 展开缩写 — 写 January，来替代 Jan。
* 展开首字母缩略词，至少一次或两次。例如写明“超文本标记语言”（Hypertext Markup Language），而不是直接用缩写 HTML。
### 页面布局

在旧时代，人们曾经使用 HTML 表格创建页面布局 - 使用不同的表格单元格来包含页眉，页脚，边栏，主要内容栏等。这不是一个好主意，因为屏幕阅读器可能会读出给人造成困惑的结果，特别是如果布局复杂，并且有许多嵌套表格的话。

试试我们的例子table-layout.html，它看起来像这样：

```html
<table width="1200">
  <!-- main heading row -->
  <tr id="heading">
    <td colspan="6">
      <h1 align="center">Header</h1>
    </td>
  </tr>
  <!-- nav menu row -->
  <tr id="nav" bgcolor="#ffffff">
    <td width="200">
      <a href="#" align="center">Home</a>
    </td>
    <td width="200">
      <a href="#" align="center">Our team</a>
    </td>
    <td width="200">
      <a href="#" align="center">Projects</a>
    </td>
    <td width="200">
      <a href="#" align="center">Contact</a>
    </td>
    <td width="300">
      <form width="300">
        <input type="search" name="q" placeholder="Search query" width="300" />
      </form>
    </td>
    <td width="100">
      <button width="100">Go!</button>
    </td>
  </tr>
  <!-- spacer row -->
  <tr id="spacer" height="10">
    <td></td>
  </tr>
  <!-- main content and aside row -->
  <tr id="main">
    <td id="content" colspan="4" bgcolor="#ffffff">
      <!-- main content goes here -->
    </td>
    <td id="aside" colspan="2" bgcolor="#ff80ff" valign="top">
      <h2>Related</h2>

      <!-- aside content goes here -->
    </td>
  </tr>
  <!-- spacer row -->
  <tr id="spacer" height="10">
    <td></td>
  </tr>
  <!-- footer row -->
  <tr id="footer" bgcolor="#ffffff">
    <td colspan="6">
      <p>©Copyright 2050 by nobody. All rights reversed.</p>
    </td>
  </tr>
</table>
```

如果你尝试使用屏幕阅读器浏览此内容，它可能会告诉你需要查看一个表格（尽管某些屏幕阅读器可以猜测表格布局和数据表格之间的区别）。然后，你可能（取决于你使用的屏幕阅读器）必须需要进入到表格对象中，并单独地查看表格的内容，然后再次离开表格，以继续浏览其他内容。

用表格布局网页是过去旧时代的遗迹 - 在“CSS”在浏览器中并不普遍被支持时，它们是有意义的，但是它们会为屏幕阅读器用户造成混淆，并且由于许多其他原因变得很糟糕（滥用表格，可能因此需要更多的标记，使设计更不灵活）。不要这样做！

你可以通过将你之前的体验与 更现代的网站结构示例 进行比较，来验证这些声明，该示例如下所示：

```html
<header>
  <h1>Header</h1>
</header>

<nav>
  <!-- main navigation in here -->
</nav>

<!-- Here is our page's main content -->
<main>
  <!-- It contains an article -->
  <article>
    <h2>Article heading</h2>

    <!-- article content in here -->
  </article>

  <aside>
    <h2>Related</h2>

    <!-- aside content in here -->
  </aside>
</main>

<!-- And here is our main footer that is used across all the pages of our website -->

<footer>
  <!-- footer content in here -->
</footer>
```

如果你使用屏幕阅读器阅读更现代的结构示例，则会看到布局标记不再会妨碍内容的读取。它在代码大小方面也更加精简和小巧，这意味着代码更容易维护，并且用户下载的带宽更少（特别适合慢速连接的用户）。

创建布局时的另一个考虑因素是使用 HTML5 语义元素，如上例所示（请参阅此内容部分）——你只能使用嵌套的 `<div>` 元素创建布局，但最好使用适当的分段元素包裹你的主导航（`<nav>`），`footer`（`<footer>`），重复内容单元（`<article>`）等。这些为屏幕阅读器（和其他工具）提供额外的语义，为用户提供有关他们正在浏览的内容的额外信息（请参阅屏幕阅读器支持的新的 HTML5 章节元素，了解屏幕阅读器的支持是什么样的原理）。

**备注：** 除了你的内容具有良好的语义和有吸引力的布局之外，它的源代码顺序应该是合理的 - 你可以随时将它放在你想要使用 CSS 的位置，但是你应该先从源代码开始，如此这样，屏幕阅读器读取给他们的内容将会非常便于理解。

### UI 控制

通过 UI 控件，我们指的是与用户交互的 Web 文档的主要部分 - 通常是按钮，链接和表单控件。在本节中，我们将介绍创建此类控件时要注意的基本无障碍问题。稍后关于 WAI-ARIA 和多媒体的文章将着眼于 UI 无障碍的其他方面。

UI 控件无障碍的一个关键方面是，默认情况下，浏览器允许用户通过键盘操作它们。你可以使用我们的 native-keyboard-accessibility.html 示例（请参阅 源代码 ）。尝试此操作 - 在新选项卡中打开此项，然后尝试按 Tab 键; 几次按下后，你应该看到标签焦点开始移动到不同的元素; 在每个浏览器中，获得焦点元素都会有一个“突出显示“的默认样式（它在不同浏览器之间略有不同），以便你可以确定当前哪些元素获得焦点。

![](/zh-CN/docs/Learn/Accessibility/HTML/button-focused-unfocused.png)

接着你可以按 Enter / Return 来追踪当前获得焦点的链接，或者按按钮来实现（我们已经使用 JavaScript 使按钮同时显示提示消息），或者开始在文本输入中输入文本（其他表单元素具有不同的控件，例如 `<select>` 元素拥有自己的显示选项，可以使用向上和向下箭头键进行循环）。

**备注：** 不同的浏览器可能有不同的键盘控制选项。请参阅使用本机键盘辅助功能获取更多详细信息。

实际上，你只需使用适当的元素即可免费获得此功能，例如，

```html
<h1>Links</h1>

<p>This is a link to <a href="https://www.mozilla.org">Mozilla</a>.</p>

<p>
  Another link, to the
  <a href="https://developer.mozilla.org">Mozilla Developer Network</a>.
</p>

<h2>Buttons</h2>

<p>
  <button data-message="This is from the first button">Click me!</button>
  <button data-message="This is from the second button">Click me too!</button>
  <button data-message="This is from the third button">And me!</button>
</p>

<h2>Form</h2>

<form>
  <div>
    <label for="name">Fill in your name:</label>
    <input type="text" id="name" name="name" />
  </div>
  <div>
    <label for="age">Enter your age:</label>
    <input type="text" id="age" name="age" />
  </div>
  <div>
    <label for="mood">Choose your mood:</label>
    <select id="mood" name="mood">
      <option>Happy</option>
      <option>Sad</option>
      <option>Angry</option>
      <option>Worried</option>
    </select>
  </div>
</form>
```

这意味着适当地使用链接，按钮，表单元素和标签（包括表单控件的 ``<label>`` 元素）。

然而，人们有时候会用 HTML 做奇怪的事情。例如，你有时会看到使用 ``<div>`` 标记的按钮，例如：

```html
<div data-message="This is from the first button">Click me!</div>
<div data-message="This is from the second button">Click me too!</div>
<div data-message="This is from the third button">And me!</div>
```

但是不建议使用这样的代码 - 你会立即失去本机键盘的无障碍。但如果你使用了``<button>`` 元素，你将可以通过键盘控制。此外你也将不会获得任何的按钮默认拥有的 CSS 样式。

#### 重新建立键盘的无障碍

重新添加这些优点需要一些工作（你可以在我们的 fake-div-buttons.html 示例中使用示例代码 - 另请参阅 源代码 ）。在这里，我们通过赋予每个 `<div>` 按钮属性`tabindex =“0”` 来使它能够被聚焦（包括通过选项卡）：

```html
<div data-message="This is from the first button" tabindex="0">Click me!</div>
<div data-message="This is from the second button" tabindex="0">
  Click me too!
</div>
<div data-message="This is from the third button" tabindex="0">And me!</div>
```

基本上，`tabindex` 属性主要用于允许 tabbable 元素具有自定义 Tab 键顺序（以正数顺序指定），而不是仅按其默认源顺序进行标记。这几乎总是一个糟糕的主意，因为它可能会造成重大混乱。例如，如果布局以与源代码非常不同的视觉顺序显示事物，而且你想让事情更符合逻辑。这里 `tabindex` 有另外两个选项：

* `tabindex="0"` — 如上所述，该值允许 通常不可放置的元素（tabbable elements）变为可放置的。这是 tabindex 最有用的的地方。
* `tabindex="-1"` — 这允许 通常不可放置的元素（tabbable elements）以编程的方式接收焦点，例如，通过 JavaScript，或作为链接的目标。

虽然上面的添加允许我们用 `tab` 选择按钮，但它不允许我们通过 `Enter / Return` 键来激活它们。要做到这一点，我们必须添加下面的 JS 小绝招（JavaScript trickery）：

```js
document.onkeydown = function (e) {
  if (e.keyCode === 13) {
    // The Enter/Return key
    document.activeElement.onclick(e);
  }
};
```

在这里，我们向文档对象 `document` 添加一个侦听器，以检测什么时候键盘上按下按钮 我们通过事件对象 `event object` 的 `keyCode` 属性，检查用户按下了哪个按钮; 如果它是与 `Return / Enter` 匹配的关键代码，我们通过按钮的 onclick 函数，即 `document.activeElement.onclick()` 。`activeElement` 提供给我们页面当前被 focused 的元素。

我们使用`document.activeElement.onclick（）`运行存储在按钮的 onclick 处理函数中的函数。 `activeElement` 为我们提供了当前关注页面的元素。

**备注：** 你应该记住，只有通过事件处理程序属性（例如 onclick）设置原始事件处理程序，此技巧才会起作用。 `addEventListener` 将不起作用。

这对于重新构建功能而言是一个额外的麻烦。而且这肯定会带来其他问题。使用正确的元素处理正确的工作是非常重要的。

#### 有意义的文字标签

用户界面控件的 文本标签 对所有用户都非常有用，但是对于残疾用户来说，让他们正确使用尤其重要。

你应该确保你的按钮和链接文本标签是可以理解和独特的。不要使用“点击这里”（"Click here"）此类的标签，因为屏幕阅读器用户有时会列出按钮和表格控件列表。以下屏幕截图显示了我们的控件在 Mac 上由 VoiceOver 列出。

![](/zh-CN/docs/Learn/Accessibility/HTML/voiceover-formcontrols.png)

确保你的标签在上下文中有意义，可以单独阅读，也可以在他们所在的段落的上下文中进行阅读。例如，下面显示了良好链接文本的示例：

```html
<p>
  Whales are really awesome creatures.
  <a href="whales.html">Find out more about whales</a>.
</p>
```

但这是不好的链接文字：

```html
<p>
  Whales are really awesome creatures. To find more out about whales,
  <a href="whales.html">click here</a>.
</p>
```

**备注：** 你可以在我们的创建超链接文章中找到更多关于链接实现和最佳实践的信息。你还可以在 good-links.html 和 bad-links.html 中看到一些好的和不好的例子。

表单标签也很重要，可以让你了解你需要输入每个表单输入的内容。以下似乎是一个足够合理的例子：

```html
Fill in your name: <input type="text" id="name" name="name" />
```

但是，这对于残疾用户来说并不是那么有用。在上面的示例中，没有任何内容将标签与表单输入明确关联。因此如果看不到它，请让用户明确该如何填写。如果你使用某些屏幕阅读器访问该屏幕，则只能按照“编辑文本”（“edit text”）的方式给出说明。

以下是一个更好的例子：

```html
<div>
  <label for="name">Fill in your name:</label>
  <input type="text" id="name" name="name" />
</div>
```

通过这样的代码，标签将清晰地与输入相关联; 描述将更像如下这种形式：“填写你的姓名：编辑文本”。

![](/zh-CN/docs/Learn/Accessibility/HTML/voiceover-good-form-label.png)

作为额外的好处，在大多数将标签与表单输入相关联的浏览器中，你可以单击标签来 选择/激活 表单元素。这给输入一个更大的可选中区域，使其更容易选择。

**备注：** 你可以在 good-form.html 和 bad-form.html 中看到一些好的和不好的表单示例。

可访问的表格
------

基本的表格（译者注：“data table”被翻译成“表格”）可以用非常简单的标记来编写，例如：

```html
<table>
  <tr>
    <td>Name</td>
    <td>Age</td>
    <td>Gender</td>
  </tr>
  <tr>
    <td>Gabriel</td>
    <td>13</td>
    <td>Male</td>
  </tr>
  <tr>
    <td>Elva</td>
    <td>8</td>
    <td>Female</td>
  </tr>
  <tr>
    <td>Freida</td>
    <td>5</td>
    <td>Female</td>
  </tr>
</table>
```

但是这有问题 - 屏幕阅读器用户无法将行或列作为数据分组关联在一起。要做到这一点，你需要知道标题行是什么，以及它们是否在行，列等标题上。这只能在上面的表中以可视化方式完成（参见 bad-table.html ，并自己尝试这个例子）。

现在看看我们的 punk bands table example - 你可以在这里看到一些辅助工具（accessibility aids）：

* 表头使用 ``<th>`` 元素定义 - 你还可以使用 `scope` 属性指定它们是行还是列的标题。这提供给了屏幕阅读器可以理解的完整数据组。
* ``<caption>`` 元素和 `<table>` `summary` 属性都执行类似的工作 - 它们充当表格的替代文本，为屏幕阅读器用户提供有用的表格内容快速摘要。 `<caption>` 通常是首选，因为它使内容可供视力良好的用户访问，而且他们也可能会发现它很有用。你并不需要两者都使用！。

**备注：** 有关可访问数据表的更多详细信息，请参阅我们的 HTML 表格高级功能和无障碍 文章。

替代文本
----

尽管文本内容本身是可访问的，但对于多媒体内容而言也不一定是这样 - 图像/视频内容不能被视觉障碍人士看到，并且听觉障碍人士不能听到音频内容。稍后我们将在可访问多媒体文章中详细介绍视频和音频内容，但对于本文，我们将探讨低微（humble）的 ``<img>`` 元素的无障碍。

我们编写了一个简单的例子， accessible-image.html ，它具有相同图像的四个副本：

```html
<img src="dinosaur.png" />

<img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />

<img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth."
 title="The Mozilla red dinosaur" />

<img src="dinosaur.png" aria-labelledby="dino-label" />

<p id="dino-label">
  The Mozilla red Tyrannosaurus Rex: A two legged dinosaur standing upright like
  a human, with small arms, and a large head with lots of sharp teeth.
</p>
```

第一张图片，当用屏幕阅读器查看时，并不真正为用户提供很多帮助 - 例如 VoiceOver 会读出“/dinosaur.png，image” 。它读出文件名以尝试提供一些帮助。在这个例子中，用户至少知道它是某种恐龙，但通常文件可以用机器生成的文件名（例如来自数码相机）上传，这些文件名可能不会提供图像内容的信息。

**备注：** 这就是为什么你不应该在图像中包含文本内容 - 屏幕阅读器根本无法访问它。还有其他的缺点 - 你不能选择它并复制/粘贴它。不要这样做！

当屏幕阅读器遇到第二张图像时，它会读出完整的 `alt` 属性 - “红色霸王龙雷克斯：一只像人一样直立的双腿恐龙，手臂小，头部大而锋利。”

这突出了不仅在所谓的替代文本不可用的情况下使用有意义的文件名的重要性，而且还确保尽可能地在替换属性 `alt` 中提供替代文本。请注意，`alt` 属性的内容应始终提供图像的直接表示以及它在视觉上传达的内容。任何个人知识或额外描述都不应该包含在这里，因为它对以前没有碰到过这个图像的人没有用处。

需要考虑的一件事是，你的图片是否在你的内容中有意义，或者它们纯粹是为了视觉装饰，所以没有意义。如果它们是装饰性的，最好将它们包含在页面中作为 CSS 背景图像。

**备注：** 请阅读 HTML 中的图片 和 响应式图片 以获得更多关于图片实施和最佳做法的信息。

如果你确实想要提供额外的上下文信息，则应该将其放在图像周围的文本中，或放置在“标题” `title` 属性中，如上所示。在这种情况下，大多数屏幕阅读器会读出替代文本，标题属性和文件名。此外，鼠标滑过时，浏览器会将 `title` 的内容作为工具提示的形式显示出来。

![](/zh-CN/docs/Learn/Accessibility/HTML/title-attribute.png)

我们再来看看第四种方法：

```html
<img src="dinosaur.png" aria-labelledby="dino-label" />

<p id="dino-label">The Mozilla red Tyrannosaurus ...</p>
```

在这种情况下，我们不使用“alt”属性——相反，我们已经将图像的描述作为常规文本段落给出，并给出它的“id”，然后使用“`aria-labelledby`”属性并链接到对应“`id`”，它使屏幕阅读器将该段落用作该图像的替代文本/标签。如果你想将相同的文本用作多个图像的标签，这是特别有用的——这是使用“`alt`”不可能实现的。

**备注：** “`aria-labelledby`”是 WAI-ARIA 规范的一部分，它允许开发人员在其标记中添加额外的语义，以提高屏幕阅读器的无障碍。要了解更多关于它是如何工作的，请阅读我们的 WAI-ARIA Basics 文章。

### 其他文字替代机制

图像还有其他机制可用于提供描述性文字。例如，有一个 `longdesc` 属性用于指向包含图像的扩展描述的单独 Web 文档，例如：

```html
<img src="dinosaur.png" longdesc="dino-info.html" />
```

这听起来像个好主意，尤其是对于像大图表这样的信息图，其中有很多信息可能可以表示为可访问的数据表（请参阅上一部分）。但是，屏幕阅读器不支持`longdesc`，非屏幕阅读器用户完全无法访问内容。将长描述包含在与图像相同的页面中，或者通过常规链接链接到它可能会更好。

HTML5 包含两个新元素 - ``<figure>`` 和``<figcaption>`` ，它们应该将某种形象（可以是任何东西，不一定是图像）与数字标题相关联：

```html
<figure>
  <img src="dinosaur.png" alt="The Mozilla Tyrannosaurus" />
  <figcaption>
    A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a
    human, with small arms, and a large head with lots of sharp teeth.
  </figcaption>
</figure>
```

不幸的是，大多数屏幕阅读器似乎并没有将图形标题与他们的图形相关联，但是元素结构对 CSS 样式非常有用，并且它提供了一种方法在源代码中将图像放置在旁边。

### 空 alt 属性

```html
<h3>
  <img src="article-icon.png" alt="" />
  Tyrannosaurus Rex: the king of the dinosaurs
</h3>
```

可能有时候图像被包含在页面的设计中，但其主要目的是用于视觉装饰。在上面的代码示例中，你会注意到图像的“alt”属性为空 - 这是为了让屏幕阅读器识别图像，但不试图描述图像（阅读器只是说“图像”等类似的语句）。

使用空白“alt”而不包含它的原因是因为如果没有提供“alt”，许多屏幕阅读器会公布整个图像 URL。在上面的示例中，图像充当与其关联的标题的视觉装饰。在这种情况下，以及在图像只是装饰并且没有内容值的情况下，你应该在图像上放置一个空白的“alt”。另一种选择是使用 aria role 属性 `role =“presentation”` - 这也会阻止屏幕阅读器读出替代文本。

**备注：** 如果可能的话，你应该使用 CSS 来显示只有装饰的图像。

总结
--

你现在应该精通编写大多数场合可访问的 HTML。我们的 WAI-ARIA 基础知识文章也将填补这些知识中的一些空白，但本文已经关注了此基础知识。接下来，我们将探索 CSS 和 JavaScript，以及无障碍如何受其好坏影响。

* 上一页
* Overview: Accessibility
* 下一页


多媒体无障碍 - 学习 Web 开发

多媒体无障碍
======

* 上一页
* Overview: Accessibility
* 下一页

可能导致无障碍（accessibility）问题的另一类内容是多媒体——视频、音频和图像内容需要提供适当的文本替代方式，以便辅助技术及其用户能够理解它们。本文展示了具体内容。

|  |  |
| --- | --- |
| 先决条件： |
 基本的计算机素养，对 HTML，CSS 和 JavaScript 的基本理解，对无障碍
 的理解。
  |
| 目标： | 了解多媒体背后的无障碍问题，以及如何克服这些问题。 |

多媒体和无障碍
-------

到目前为止，在这个模块中，我们已经查看了各种内容以及需要做些什么来确保其无障碍，从简单的文本内容到数据表，图像，本机控件（如表单元素和按钮）以及更复杂的标记结构（具有WAI-ARIA属性）。

另一方面，这篇文章着眼于另一个一般的内容类别，可以说它不容易确保对多媒体的无障碍。图像，视频，`<canvas>`元素，Flash 电影等不易被屏幕阅读器理解或被键盘导航，我们需要帮助他们。

但不要绝望 - 在这里我们将帮助你浏览可用于使多媒体更容易访问的技术。

简单图像
----

我们已经介绍了 HTML 图像的简单文本替代HTML: A good basis for accessibility –– 你可以参考其中了解详细信息。简而言之，应确保在可能的情况下，视觉内容具有替代文本，供屏幕阅读器拾取和读取给其用户。

示例：

```html
<img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />
```

可访问的音频和视频控件
-----------

基于 Web 的音频/视频执行控件不应该成为问题，对吗？让我们来调查一下。

### 本地 HTML5 控件的问题

HTML5 视频和音频实例甚至附带一组内置控件，允许你直接在盒子控制媒体。例如 (请参阅本地控件.html 源代码和实时演示):

```html
<audio controls>
  <source src="viper.mp3" type="audio/mp3" />
  <source src="viper.ogg" type="audio/ogg" />
  <p>
    Your browser doesn't support HTML5 audio. Here is a
    <a href="viper.mp3">link to the audio</a> instead.
  </p>
</audio>

<br />

<video controls>
  <source src="rabbit320.mp4" type="video/mp4" />
  <source src="rabbit320.webm" type="video/webm" />
  <p>
    Your browser doesn't support HTML5 video. Here is a
    <a href="rabbit320.mp4">link to the video</a> instead.
  </p>
</video>
```

控件属性提供播放/暂停按钮、搜索栏等 - 你期望从媒体播放器获得的基本控件。它看起来像在 Firefox 和 Chrome:

![Screenshot of Video Controls in Firefox](/zh-CN/docs/Learn/Accessibility/Multimedia/native-controls-firefox.png)

![Screenshot of Video Controls in Chrome](/zh-CN/docs/Learn/Accessibility/Multimedia/native-controls-chrome.png)

但是，这些控件存在问题：

* 在除 Opera 以外任何浏览器中，它们不可通过键盘访问。
* 不同的浏览器为原生控件提供了不同的样式和功能，且不可赋予它们样式，这意味着它们难以遵从网站样式指南。

为了解决这个问题，我们可以创建自己的自定义控件。让我们来看看如何。

### 创建自定义音频和视频控件

HTML5 视频和音频共享 API — HTML Media Element — 允许你将自定义功能映射到按钮和其他控件––这两个控件都是你自己定义的。

让我们从上面获取视频示例，并向其添加自定义控件。

#### 基本设置

首先，获取我们的custom-controls-start.html、custom-controls.css、 rabbit320.mp4 和 rabbit320.webm文件的副本，并将它们保存在硬盘上的新目录中。

创建一个名为 main.js 的新文件并将其保存在同一目录中。

首先，让我们在 HTML 中查看视频播放器的 HTML:

```html
<section class="player">
  <video controls>
    <source src="rabbit320.mp4" type="video/mp4" />
    <source src="rabbit320.webm" type="video/webm" />
    <p>
      Your browser doesn't support HTML5 video. Here is a
      <a href="rabbit320.mp4">link to the video</a> instead.
    </p>
  </video>

  <div class="controls">
    <button class="playpause">Play</button>
    <button class="stop">Stop</button>
    <button class="rwd">Rwd</button>
    <button class="fwd">Fwd</button>
    <div class="time">00:00</div>
  </div>
</section>
```

#### JavaScript 基本设置

我们在视频下方插入了一些简单的控制按钮。当然，这些控件在默认情况下不会执行任何操作。要添加功能，我们将使用 JavaScript。

我们首先需要存储对每个控件的引用––将以下内容添加到 JavaScript 文件的顶部：

```js
const playPauseBtn = document.querySelector(".playpause");
const stopBtn = document.querySelector(".stop");
const rwdBtn = document.querySelector(".rwd");
const fwdBtn = document.querySelector(".fwd");
const timeLabel = document.querySelector(".time");
```

接下来，我们需要获取对视频/音频播放器本身的引用––在前面的代码行下方添加此行代码：

```js
const player = document.querySelector("video");
```

这包含对`HTMLMediaElement`对象的引用，该对象具有几个有用的属性和方法，可用于将功能连接到我们的按钮。

在开始创建按钮功能之前，让我们删除本地控件，以免它们妨碍我们的自定义控件。在 JavaScript 的底部再次添加以下内容：

```js
player.removeAttribute("controls");
```

这样做，而不是仅仅不包括控件属性摆在首位有一个优势，如果我们的 JavaScript 失败，用户仍然有一些控件可用。

#### 连接按钮

首先，让我们设置播放/暂停按钮。我们可以使用一个简单的条件函数在播放和暂停之间切换，如下所示。将其添加到代码底部：

```js
playPauseBtn.onclick = () => {
  if (player.paused) {
    player.play();
    playPauseBtn.textContent = "Pause";
  } else {
    player.pause();
    playPauseBtn.textContent = "Play";
  }
};
```

接下来，将此代码添加到底部，该代码控制停止按钮：

```js
stopBtn.onclick = () => {
  player.pause();
  player.currentTime = 0;
  playPauseBtn.textContent = "Play";
};
```

在 `HTMLMediaElement` 上没有可用的 `stop()` 函数，因此我们改为`pause()`它，同时将当前时间设置为 0。

接下来，我们的快退和快进按钮–– 将以下块添加到代码的底部：

```js
rwdBtn.onclick = () => {
  player.currentTime -= 3;
};

fwdBtn.onclick = () => {
  player.currentTime += 3;
  if (player.currentTime >= player.duration || player.paused) {
    player.pause();
    player.currentTime = 0;
    playPauseBtn.textContent = "Play";
  }
};
```

这些非常简单，每次单击它们时，只需将 3 秒添加到`currentTime`。在真正的视频播放器中，你可能想要一个更精细的查找栏或类似功能。

请注意，当按下 Fwd 按钮时，我们还会检查`currentTime`是否超过总媒体的`duration`,或者媒体是否未播放。如果任一条件为 true，我们只需停止视频，以避免用户界面出错，如果他们试图在视频未播放时快进，或快进通过视频结束。

最后，将以下内容添加到代码末尾，以控制显示的时间：

```js
player.ontimeupdate = () => {
  const minutes = Math.floor(player.currentTime / 60);
  const seconds = Math.floor(player.currentTime - minutes \* 60);
  const minuteValue = minutes < 10 ? `0${minutes}` : minutes;
  const secondValue = seconds < 10 ? `0${seconds}` : seconds;

  const mediaTime = `${minuteValue}:${secondValue}`;
  timeLabel.textContent = mediaTime;
};
```

每次更新时间 (每秒一次) 时，我们都会触发此功能。它算出给定的当前时间值 (以秒为单位) 的分钟和秒数，如果分钟或秒值小于 10，则添加前导 0，然后创建显示读出并将其添加到时间标签。

#### 阅读延伸

这为你提供了如何向视频/音频播放器实例添加自定义播放器功能的基本想法。有关如何向视频/音频播放器添加更复杂的功能（包括旧版浏览器的 Flash 回退）的详细信息，请参阅：

* Audio and video delivery (en-US)
* Video player styling basics (en-US)
* Creating a cross-browser video player (en-US)

我们还创建了一个高级示例，以演示如何创建面向对象的系统，该系统可查找页面上的每个视频和音频播放器 (无论有多少个视频和音频播放器),并将自定义控件添加到其中。请参阅 custom-controls-oojs（查看其源码）。

音频脚本
----

要为聋人提供访问音频内容的机会，你确实需要创建文本脚本。这些可以以某种方式与音频一样包含在与音频相同的页面上，也可以包含在单独的页面上并链接到

在实际创建脚本方面，你的选项包括：

* 商业服务––你可以向专业人士支付报酬进行转录，例如 Scribie、Casting Words或Rev公司。询问并征求意见，以确保你找到一家信誉良好的公司，你可以有效地合作。
* 社区/草根/自我转录 – 如果你是工作场所中活跃社区或团队的一员，你可以请求他们帮助翻译。你甚至可以自己去做。
* 自动服务 – 提供自动服务，例如，当你将视频上传到 YouTube 时，你可以选择生成自动字幕/脚本。根据语音音频的清晰程度，生成的脚本质量将有很大差异。

和生活中的大多数事情一样，你倾向于得到你所付出的;不同的服务在准确性和制作成绩单所花时间方面会有所不同。如果你支付一个有信誉的公司做转录，你可能会得到它迅速和高质量的。如果你不想付钱，你很可能会以较低的质量完成，并且/或缓慢完成。

发布音频资源是不行的，但承诺稍后会发布脚本 - 此类承诺通常不会兑现，这将削弱你和你的用户之间的信任。如果你演示的音频类似于面对面会议或现场演讲表演，则可以在演出期间做笔记，与音频一起完整发布笔记，然后寻求帮助，以便稍后清理笔记。

### 脚本示例

如果使用自动服务，则可能需要使用该工具提供的用户界面。例如，查看Audio Transcription Sample 1并选择" *More > Transcript*"。

如果要创建自己的用户界面来显示音频和相关脚本，你可以随心所欲地执行此操作，但将其包含在可显示/可隐藏面板中可能有意义;请参阅我们的audio-transcript-ui 示例（另请参阅其源码）。

### 音频描述

在音频附带视频的情况下，你需要提供某种音频说明来描述该额外内容。

在许多情况下，这只会采取视频的形式，在这种情况下，你可以使用本文下一节中介绍的技术实现字幕。

但是，有一些边缘情况。例如，你可能有一个会议的音频录制，该录音引用了附带的资源，如电子表格或图表。在这种情况下，应确保资源与音频和脚本一起提供，并在成绩单中提及它们的位置专门链接到这些资源。这当然会帮助所有用户，而不仅仅是聋人。

**备注：** 音频脚本通常有助于多个用户组。除了让聋人用户访问音频中包含的信息外，还考虑一个带宽连接较低的用户，他们会发现下载音频不方便。还要考虑在嘈杂的环境中 (如酒吧或酒吧) 中的用户，他们试图访问信息，但无法通过噪音听到信息。

视频文本轨道
------

要使聋人、盲人甚至其他用户组 (如低带宽用户或不理解视频录制的语言的用户) 可以访问视频，你需要在视频内容中包括文本轨道。

**备注：** 文本轨道对于潜在的任何用户也很有用，而不仅仅是那些残障用户。例如，有些用户可能无法听到音频，因为他们处于嘈杂的环境中 (如显示体育游戏时的拥挤的酒吧),或者如果其他人在安静的地方 (如图书馆),则可能不想打扰其他人。

这不是一个新概念 ––电视服务已经关闭了字幕相当长的时间了：

![Frame from an old-timey cartoon with closed captioning "Good work, Goldie. Keep it up!"](/zh-CN/docs/Learn/Accessibility/Multimedia/closed-captions.png)

许多国家/地区提供以英语为母语的字幕的英语电影，例如，DVD 上通常提供不同的语言字幕

![An English film with German subtitles "Emo, warum erkennst du nicht die Schonheit dieses Ortes?"](/zh-CN/docs/Learn/Accessibility/Multimedia/subtitles_german.png)

不同类型的文本轨道具有不同的目的。你遇到的主要情况是：

* 标题 ––对于听不到音轨 (包括所讲的单词，还有环境信息，如说话、以及用来营造喜怒气氛的音乐等) 的聋人用户而言是有利的。
* 字幕––为不懂所讲语言的用户提供音频对话框的翻译。
* 说明–– 这些描述包括无法观看视频的盲人的描述，例如场景的外观。
* 章节标题––旨在帮助用户导航媒体资源的章节标记
### 实现 HTML5 视频文本轨道

使用 HTML5 视频显示的文本轨道需要用 WebVTT 编写，WebVTT 是一种文本格式，其中包含多个文本字符串以及元数据，例如你希望在视频中显示每个文本字符串的时间，甚至限制样式/定位信息。这些文本字符串称为提示。

典型的 WebVTT 文件如下所示：
```

WEBVTT

1
00:00:22.230 --> 00:00:24.606
This is the first subtitle.

2
00:00:30.739 --> 00:00:34.074
This is the second.

  ...
```

要将此信息与 HTML 媒体播放一起显示，你需要：

* 将其保存为 .vtt 文件，放在一个合理的地方。
* 使用 `<track>` 元素链接到 .vtt 文件。`<track>` 应放在 `<audio>` 或 `<video>` 内，但在 `<source>` 元素之后。使用 `kind` 属性指定提示是字幕、标题还是说明。此外，使用 `srclang` 告诉浏览器编写字幕所用的语言。

下面是一个示例：

```html
<video controls>
  <source src="example.mp4" type="video/mp4" />
  <source src="example.webm" type="video/webm" />
  <track kind="subtitles" src="subtitles\_en.vtt" srclang="en" />
</video>
```

这将产生显示字幕的视频，如下所示：

![Video player with standard controls such as play, stop, volume, and captions on and off. The video playing shows a scene of a man holding a spear-like weapon, and a caption reads "Esta hoja tiene pasado oscuro."](/zh-CN/docs/Learn/Accessibility/Multimedia/video-player-with-captions.png)

有关详细信息，请阅读Adding captions and subtitles to HTML5 video (en-US)。你可以找到与本文一起使用本文的the example,本文由 Ian Devlin 编写 (请参阅source code)。此示例使用一些 JavaScript 允许用户在不同的字幕之间进行选择。请注意，要打开字幕，你需要按"CC"按钮并选择一个选项 - 英语、德语或西班牙语。

**备注：** 文本轨道和转录也可以帮助你使用SEO,因为搜索引擎在文本上尤其繁荣。文本轨道甚至允许搜索引擎通过视频直接链接到一个点部分。

其他多媒体内容
-------

以上各节未涵盖你可能要放在网页上的所有类型的多媒体内容。你可能还需要处理使用其他可用技术创建的游戏、动画、幻灯片、嵌入式视频和内容，例如：

* HTML5 canvas
* Flash
* Silverlight

对于此类内容，你需要根据案例处理辅助功能问题。在某些情况下，它不是那么糟糕，例如：

* 如果你使用 Flash 或 Silverlight 等插件技术嵌入音频内容，你可能只需以与上面在脚本示例部分中所示的相同方式提供音频脚本。
* 如果你使用 Flash 或 Silverlight 等插件技术嵌入视频内容，则可以利用这些技术可用的字幕/字幕技术。例如，参考 Flash captions、Using the Flash-Only Player API for Closed Captioning 或 Playing Subtitles with Videos in Silverlight.

然而，其他多媒体不是那么容易使访问。例如，如果你正在处理沉浸式 3D 游戏或虚拟现实应用，那么为此类体验提供文本替代方案确实非常困难，你可能会认为盲人用户实际上并不在此类应用的目标受众范围内。

但是，你可以确保此类应用具有足够的颜色对比度和清晰的显示，以便对视力低下/色盲的人来说可以感知，并且还可以使其键盘可访问。请记住，辅助功能就是尽可能多地做，而不是一直追求 100% 的无障碍，这通常是不可能的。

总结
--

本章概述了多媒体内容的无障碍问题，以及一些实用的解决方案。

* 上一页
* Overview: Accessibility
* 下一页


测验：无障碍疑难解答 - 学习 Web 开发

测验：无障碍疑难解答
==========

* 上一页
* Overview: Accessibility

在本模块的测验环节中，我们将呈现一个含有若干无障碍问题的简单网站，你需要对它进行诊断并修复这些问题。

|  |  |
| --- | --- |
| 先决条件： | 基础的计算机知识，对 HTML、CSS 和 JavaScript 有基础的理解，理解本课程的前期内容。 |
| 目标： | 测试对无障碍的基础知识的理解情况。 |

开始之前
----

在开始本测验之前，你需要在这里获取包含组成这个例子的 ZIP 压缩文件。将它们解压到一个本地的新文件夹中。

或者，你可以使用 JSBin 或 Glitch 完成你的测验。你可以将 HTML、CSS 和 JavaScript 代码粘贴到这些在线编辑器之一。如果你使用的在线编辑器没有分开的 CSS/JS 面板，则可将它们放置在适当的 `<style>`、`<script>` 元素之下。

最终完成的网页应该类似于这样：

![Screenshot of the finished assessment site with good color contrast. The search input has placeholder text and a submit button that reads go, but no visible label.](/zh-CN/docs/Learn/Accessibility/Accessibility_troubleshooting/assessment-site-finished.png)

你会看到评估的起始状态的显示有一些差异/问题——这主要是由于标记的不同，这反过来又导致一些样式问题，因为 CSS 没有被正确应用。不要担心——你将在接下来的章节中解决这些问题！

**备注：** 如果你卡住了，就可以寻求帮助——请参阅本页面底部的测验或进一步的帮助章节。

项目简要
----

在这个项目中，你会看到一个虚构的自然网站，展示一篇关于熊的“事实”文章。就目前的情况来看，它有一些无障碍的问题。你的任务是探索现有的网站，并尽可能解决这些问题，回答下面的问题。

### 颜色

目前的配色方案会导致文字难以阅读。你能不能对当前的颜色对比（文字或背景）做一个测试，报告测试结果，然后通过改变指定的颜色来解决这个问题？

### HTML 语义

1. 内容还不够无障碍——试试用屏幕阅读器阅读页面，看看会发生什么。
2. 你能不能更新文章的文字，让屏幕阅读器的使用者更容易浏览？
3. 网站的导航菜单部分（被包裹在 `<div class="nav"></div>` 中）可以通过把它放在一个适当的 HTML 语义元素中而变得更容易访问。它应该被更新为哪一个？请进行更新。

**备注：** 你需要更新 CSS 规则选择器，将标签的样式改为语义标题的适当等价表示形式。一旦添加了段落元素，就会注意到样式看起来好一些了。

### 图片

图片目前对屏幕阅读器用户不可访问，你能修复它吗？

### 音频播放器

1. `<audio>` 播放器对听障人士（聋人）不可访问，你能为这些用户添加无障碍替代品吗？
2. `<audio>` 播放器对不支持 HTML 音频的旧式浏览器不可访问，如何让这些浏览器用户也可以访问到音频资源？
### 表单

1. 顶部的搜索表单中的 `<input>` 元素可以做一个标签，但我们不想添加一个可见的文本标签，这有可能会破坏设计，而且视力正常的用户并不真正需要。怎样才能添加一个只有屏幕阅读器才能访问的标签呢？
2. 评论表单中的两个 `<input>` 元素有可见的文本标签，但它们没有明确地与它们的标签相关联，如何实现这一点？请注意，你也需要更新一些 CSS 规则。
### 显示/隐藏评论控制

显示/隐藏评论控制按钮目前不可由键盘访问。你能让它成为键盘可访问的吗，既可以用 Tab 键聚焦，也可以用回车键激活它？

### 表格

数据表目前还不是很方便——屏幕阅读器用户很难将数据行和列联系在一起，而且该表也没有任何类型的摘要，以使其明确所显示的内容。你能在你的 HTML 中添加一些功能来解决这个问题吗？

### 其他考虑

你能再列举两个能使网站无障碍体验更佳的改进意见吗？

测验或进一步的帮助
---------

如果你需要对你的工作进行评估，或遇见一些问题并想寻求帮助：

1. 将你的工作放置在可分享在线编辑器中，如 CodePen、jsFiddle 或 Glitch。
2. 在 MDN Discourse forum Learning 分类 中撰写帖子，寻求评估或/和帮助。你的帖子应该包含：
    * 一个描述性的标题，例如“Assessment wanted for Accessibility troubleshooting”。
    * 你已经尝试了哪些细节，想让我们做些什么（例如获取帮助，或寻求评估）。
    * 在一个在线可共享的编辑器（例如第 1 步中提到的那些）中，提供你想要评估或需要帮助的例子的链接。这是一个很好的做法，如果你不能看到他们的代码，就很难帮助别人解决编码问题。
    * 一个链接到实际任务或测验页面的链接，通过这个链接我们可以明白你寻求帮助的问题。
* 上一页
* Overview: Accessibility


CSS 和 JavaScript 无障碍最佳实践 - 学习 Web 开发

CSS 和 JavaScript 无障碍最佳实践
========================

* 上一页
* Overview: Accessibility
* 下一页

当 CSS 和 JavaScript 使用得当，很有可能改善 Web 访问体验，相反如果滥用的话，则会在极大程度上损害无障碍。本文概述了一些应该被考虑的 CSS 和 JavaScript 的最佳实践，这些实践保证了即使是复杂的内容也可以尽可能的容易被访问。

|  |  |
| --- | --- |
| 准备： | 基本的计算机读写能力，对 HTML、CSS 和 JavaScript 的基本理解，以及对无障碍的理解。 |
| 目标： | 熟悉在 Web 文档中适当地使用 CSS 和 JavaScript，以最大限度地提高无障碍，并且不损害它。 |

CSS 和 JavaScript 也是无障碍的吗？
-------------------------

CSS 和 JavaScript 对无障碍直接的重要性都不如 HTML，但是它们仍然能够帮助或破坏无障碍，这取决于它们是如何被使用的。换句话说，重要的是考虑一些最佳实践建议，以确保使用 CSS 和 JavaScript 不会破坏文档的无障碍。

CSS
---

让我们从 CSS 开始吧！

### 正确的语义和用户期望

可以使用 CSS 使任何 HTML 元素看起来像任何东西，但这并不意味着你应该这样做。正如我们经常提到的 HTML：辅助功能的良好基础，你应该尽可能为作业（job）使用适当的语义元素。如果不这样做，它可能会对每个人造成混乱和可用性问题，尤其是对残障用户。使用正确的语义与用户期望有很大的帮助——元素的外观和功能会根据它们的功能进行某些方式的显示，而且用户期望这些常见的约定。

例如，如果开发人员没有适当地使用标题元素标记内容，则屏幕阅读器用户无法通过标题元素导航页面。同样，如果对标题进行样式设置，则标题将失去其视觉目的，使其看起来不像标题。

经验法则是，你可以更新页面功能的样式以适应你的设计，但不要更改它太多，使其不再按预期的外观或活动。以下各节总结了要考虑的主要 HTML 功能。

#### “标准”的内容结构

标题、段落、列表和页面的核心文本内容：

```html
<h1>Heading</h1>

<p>Paragraph</p>

<ul>
  <li>My list</li>
  <li>has two items.</li>
</ul>
```

一些典型的 CSS 如下所示：

```css
h1 {
  font-size: 5rem;
}

p,
li {
  line-height: 1.5;
  font-size: 1.6rem;
}
```

你应该：

* 选择合理的字体大小、行高、字母间距等，使文本具有逻辑性、清晰性和阅读舒适性。
* 确保标题从正文文本中脱颖而出，通常像默认样式一样大而粗壮。你的列表应类似于列表。
* 文本颜色应与背景颜色形成良好对比。

有关详细信息，请参阅 HTML 文本基础知识和设置文本样式。

#### 强调的文本

内联标记，赋予其包裹的文本特别强调：

```html
<p>The water is <em>very hot</em>.</p>

<p>
  Water droplets collecting on surfaces is called <strong>condensation</strong>.
</p>
```

你可能希望向强调的文本添加一些简单的颜色：

```css
strong,
em {
  color: #a60000;
}
```

但是，你很少需要以任何显著的方式设置强调元素的样式。粗体和斜体文本的标准约定非常容易识别，更改样式可能会导致混淆。有关强调的更多信息，参见重点强调。

#### 缩写

允许缩写、首字母缩略词或初始化与其扩展关联的元素：

```html
<p>
  Web content is marked up using
  <abbr title="Hypertext Markup Language">HTML</abbr>.
</p>
```

同样，你可能希望以某种简单方式设置样式：

```css
abbr {
  color: #a60000;
}
```

缩写的公认样式约定是虚线下划线，偏离这一原则明显是不明智的。有关缩写的更多，参见缩略语。

#### 链接

超链接——你到达新网站的方式：

```html
<p>Visit the <a href="https://www.mozilla.org">Mozilla homepage</a>.</p>
```

一些非常简单的链接样式如下所示：

```css
a {
  color: #ff0000;
}

a:hover,
a:visited,
a:focus {
  color: #a60000;
  text-decoration: none;
}

a:active {
  color: #000000;
  background-color: #a60000;
}
```

标准链接约定为下划线，标准状态为不同颜色（默认：蓝色），以前访问过链接时另一种颜色变化（默认：紫色），以及激活链接时的另一种颜色（默认：红色）。此外，当链接被鼠标悬停时，鼠标指针将变为指针图标，并且链接在聚焦（例如通过 tabbing）或激活时变成高亮。下图显示了 Firefox（虚线轮廓）和 Chrome（蓝色轮廓）中的高光：

![](/zh-CN/docs/Learn/Accessibility/CSS_and_JavaScript/focus-highlight-firefox.png)

![](/zh-CN/docs/Learn/Accessibility/CSS_and_JavaScript/focus-highlight-chrome.png)

你可以使用链接样式进行创意，只要用户在与链接交互时不断提供反馈即可。当状态发生变化时，确实应该发生某些情况，并且不应删除指针光标或大纲——对于使用键盘控件的人来说，两者都是非常重要的辅助功能。

#### 表单元素

允许用户将数据输入到网站的元素：

```html
<div>
  <label for="name">Enter your name</label>
  <input type="text" id="name" name="name" />
</div>
```

你可以在我们的 form-css.html 示例中看到一些很好的示例 CSS（查看示例）。

你将为表单编写的大多数 CSS 将用于调整元素大小、排列标签和输入，以及让它们看起来整洁。

但是，你不应过多偏离元素在聚焦时接收的预期视觉反馈表单，这与链接基本相同（见上文）。你可以设置焦点/悬停状态样式，使这种行为在浏览器中更加一致，或者更适合你的页面设计，但不要完全摆脱它——同样，人们依靠这些线索来帮助他们了解发生了什么。

#### 表格

用于显示表格数据的表。

你可以在 table-css.html 示例中看到表 HTML 和 CSS 的一个很好的简单示例（查看示例）。

表的 CSS 通常使表更适合你的设计，看起来不那么难看。最好确保表标题醒目（通常使用粗体），并使用斑马条带化使不同的行更易于解析。

### 颜色和颜色对比度

为网站选择配色方案时，请确保文本（前景）颜色与背景颜色对比度良好。你的设计可能看起来很酷，但如果有视觉障碍（如色盲）的人无法阅读你的内容，则设计就无一好可做。

有一个简单的方法来检查你的对比度是否足够大，不会引起问题。有许多对比检查工具可以在线输入你的前景和背景颜色，以检查它们。例如，WebAIM 的颜色对比度检查器易于使用，并说明了你需要满足有关颜色对比度的 WCAG 标准的内容。

**备注：** 高对比度还允许任何使用带有光面屏幕的智能手机或平板电脑的人在明亮的环境中 (如阳光) 更好地阅读页面。

另一个提示是不要仅仅依靠颜色来提供路标/信息，因为对于那些看不到颜色的人来说，这没有什么用。例如，不要用红色标记所需的表单字段，而是用星号和红色标记它们。

### 隐藏的东西

在很多情况下，可视化设计需要并非同时显示所有内容。例如，在我们的 Tabbed info box 示例（参见源码），我们有三个信息面板，但我们将它们放在彼此之上，并提供可以单击以显示每个选项卡的选项卡（也可以使用键盘——你也可以使用 Tab 和 Enter/Return 以选择它们）。

![](/zh-CN/docs/Learn/Accessibility/CSS_and_JavaScript/tabbed-info-box.png)

屏幕阅读器用户并不关心这些内容 , 只要资源的顺序有意义，他们就对内容感到满意，并且他们可以获得所有内容。绝对定位（如本示例所示）通常被视为隐藏内容以进行视觉效果的最佳机制之一，因为它不会阻止屏幕阅读器访问它。

另一方面，不应使用 `visibility``:hidden` 或 `display``:none`，因为它们会隐藏屏幕阅读器中的内容。当然，除非你希望从屏幕阅读器中隐藏此内容，这是有充分理由的。

**备注：** 专为屏幕阅读器用户设计的不可见内容有围绕本主题的更多有用详细信息。

### 接受用户覆盖样式

#### 接受用户覆盖你的样式

用户可以使用自己的自定义样式覆盖样式，例如：

* 请参阅 Sarah Maddox 的如何在 Firefox 中使用自定义样式表（CSS）以获得有用的指南（介绍了如何在 Firefox 中手动执行此操作），以及 Adrian Gordon 的如何在 Internet Explorer 中使用自定义样式表（CSS）是介绍关于 IE 浏览器类似文章。
* 使用扩展程序可能更容易，例如，时尚扩展适用于 Firefox、Safari、Opera 和 Chrome。

用户可能出于各种原因执行此操作。视力受损的用户可能希望使其访问的所有网站上的文本变大，严重色缺乏（severe color difeciency）的用户可能希望将所有网站置于易于查看的高对比度颜色中。无论需要什么，你都应该对此感到满意，并使你的设计足够灵，以便此类更改在你的设计中起作用。例如，你可能希望确保主要内容区域可以处理较大的文本（可能它将开始滚动以允许查看所有文本），并且不会只是隐藏它，或者完全中断。

JavaScript
----------

JavaScript 还可能会中断无障碍，具体取决于其使用方式。

现代 JavaScript 是一种功能强大的语言，如今我们可以使用它，从简单的内容和 UI 更新到成熟的 2D 和 3D 游戏。没有任何规则规定所有内容都必须对所有人 100% 无障碍——你只需尽力而为，并使你的应用尽可能无障碍。

简单的内容和功能可以说是很容易使访问——例如文本，图像，表格，窗体和按钮，激活功能。正如我们在 HTML：辅助功能的良好基础一文中提到的，主要注意事项包括：

* 良好的语义：为正确的工作使用正确的元素。例如，确保你使用标题和段落，以及 `<button>` 和 `<a>` 元素
* 确保内容以文本形式提供，要么直接作为文本内容、表单元素的良好文本标签，也可以确保替代文本（例如图像的 alt 文本）。

我们还查看了如何使用 JavaScript 在缺少功能的地方构建的示例 , 参见重新建立键盘的无障碍。这不是理想的——实际上，你应该只使用正确的元素为正确的作业——但它表明在情况下它是可能的，由于某种原因，你不能控制使用的标记。提高非语义 JavaScript 支持的小部件的无障碍的另一种方法是使用 WAI-ARIA 为屏幕阅读器用户提供额外的语义。下一篇文章还将详细介绍这一点。

复杂的功能，如 3D 游戏是不容易提高无障碍的 ––使用 WebGL 创建的复杂 3D 游戏将在 `<canvas>` 元素上呈现，该元素目前没有提供文本替代或其他信息的功能视障用户使用。可以说，这样的游戏并没有真正有这群人作为它的主要目标观众的一部分，这将是不合理的，期望你使它 100% 访问盲人，但你可以实现键盘控制，所以它可以使用非鼠标用户，并使配色方案的对比度足以让有颜色缺陷的人使用。

### 太多 JavaScript 导致的问题

过于依赖 JavaScript 会导致许多问题。有时你会看到一个网站，其中一切都已经用 JavaScript 完成——JavaScript 生成 HTML，CSS 等等。随之而来的会是各种访问性问题，因此这样做是不建议的。

正确的工作需要使用正确的元素和技术！仔细考虑：消息框是否必须用 JavaScript 3D 实现，纯文本是否就刚好。仔细考虑是否需要复杂的非标准表单小部件，或者文本输入是否就行。如果可能，不要使用 JavaScript 生成所有 HTML 内容。

### 保持别抢眼

在创建内容时，应牢记**不唐突的（unobtrusive）JavaScript** 原则。不唐突的 JavaScript 的想法是，它应该尽可能用于增强功能，而不是完全构建它——基本功能最好在没有 JavaScript 的情况下正常工作，尽管人们认识到，这并不总是一个选项。但同样，它的大部分是尽可能使用内置的浏览器功能。

不唐突的 JavaScript 使用的良好示例包括：

* 提供客户端表单验证，它快速提醒用户表单条目出现的问题，而无需等待服务器检查数据。如果表单不可用，则窗口仍然有效，但验证速度可能较慢。
* 为 HTML5 `<video>` 提供自定义控件，这些控件仅供键盘用户访问，以及如果 JavaScript 不可用 (默认 `<video>` 浏览器控件在大多数浏览器中无法使用键盘访问)，就直接通过链接访问视频。

例如，我们编写了一个快速而糟糕的客户端客户端表单验证示例——参见form-validation.html（查看在线演示）。在示例中，你会看到一个简单的表格；当你尝试提交一个或两个字段为空的表单时，提交将失败，并且会出现一个错误消息框，告诉你出了什么问题。

这种表单验证并不引人注目——在 JavaScript 不可用的情况下，你仍然可以很好的使用表单，并且任何合理的表单实现都将激活服务器端验证，因为恶意用户很容易绕过客户端验证（例如，通过在浏览器中关闭 JavaScript）。客户端验证对于报告错误仍然非常有用——用户可以立即了解他们所犯的错误，而不必等待到服务器的往返和页面重新加载。这是一个明确的可用性优势。

**备注：** 此简单示例中尚未实现服务器端验证。

我们使此表单验证非常容易访问。我们使用 `<label>` 元素来确保表单标签明确链接到其输入，因此屏幕阅读器可以一起读取它们：

```html
<label for="name">Enter your name:</label>
<input type="text" name="name" id="name" />
```

我们仅在提交表单时执行验证。这样，我们就不会过于频繁地更新 UI，反之则可能混淆屏幕阅读器（可能还有其他）用户：

```js
form.onsubmit = validate;

function validate(e) {
  errorList.innerHTML = "";
  for (var i = 0; i < formItems.length; i++) {
    var testItem = formItems[i];
    if (testItem.input.value === "") {
      errorField.style.left = "360px";
      createLink(testItem);
    }
  }

  if (errorList.innerHTML !== "") {
    e.preventDefault();
  }
}
```

**备注：** 在此示例中，我们使用绝对定位而不是其他方法（如可见性或显示）隐藏和显示错误消息框，因为它不会干扰屏幕阅读器从中读取内容。

实际表单验证会比这复杂得多——你需要检查输入的名称实际上看起来像一个名称，输入的年龄实际上是一个数字，并且与真实情况符合（例如，不是负数或四位数字）。在这里，我们刚刚实现了一个简单的验证，是否将值填充到每个输入字段（`if(testItem.input.value === '')`）。

执行验证后，如果测试通过，则提交表单。如果存在错误（`if(errorList.innerHTML !== '')`），则我们停止表单提交（使用 `preventDefault()`），并显示已创建的任何错误消息（见下文）。此机制意味着只有存在错误时才会显示错误消息，这是一个明确的可用性优势。

对于提交表单时没有填写值的每个输入，我们创建一个包含链接的列表项，并将其插入到 `errorList` 中。

```js
function createLink(testItem) {
  var listItem = document.createElement("li");
  var anchor = document.createElement("a");
  anchor.textContent =
    testItem.input.name +
    " field is empty: fill in your " +
    testItem.input.name +
    ".";
  anchor.href = "#" + testItem.input.name;
  anchor.onclick = function () {
    testItem.input.focus();
  };
  listItem.appendChild(anchor);
  errorList.appendChild(listItem);
}
```

每个链接都有双重用途，即它不仅告诉你错误是什么，而且可以单击它或激活它直接跳转到有问题的输入元素，并且更正输入。

**备注：** 此示例的 `focus()` 部分有点棘手。Chrome 和 Edge（以及较新版本的 IE）将在单击链接时聚焦元素，而无需 `onclick`/`focus()` 代码块。Safari 只会突出显示表单元素，并自行显示链接，因此需要 `onclick/focus()` 代码块来实际聚焦它。Firefox 没有在上下文中正确的聚焦输入，因此 Firefox 用户目前无法利用这一点（尽管其他一切都正常）。Firefox 问题应该尽快会得到修复——现在的工作是使 Firefox 行为与其他浏览器的行为相同（参见 Firefox bug 277178）。

此外，`errorField` 被放置在源顺序的顶部（与 UI 中使用 CSS 时相比，位置不同），这意味着用户可以准确找出表单提交时的问题，并通过返回到页面的开头，来获悉有问题的输入元素。

最后，我们在演示中使用了一些 WAI-ARIA 属性，以帮助解决因为内容区域不断更新而未重新加载页面，导致的辅助功能问题（默认情况下，屏幕阅读器不会选取该属性或提醒用户）：

```html
<div class="errors" role="alert" aria-relevant="all">
  <ul></ul>
</div>
```

我们将在下一篇文章中解释这些属性，其中将更详细地介绍 WAI-ARIA。

**备注：** 一些人可能会考虑这样一个事实，即 HTML5 表单有内置的验证机制，如 `required`、`min`/`minlength` 和 `max`/`maxlength` 属性（详细信息，请参阅 `<input>`元素引用）。我们最终没有在演示中使用这些功能，因为不是所有的浏览器都支持（例如，仅 IE10 及以上版本支持，Safari 不支持）。

**备注：** WebAIM 的可用且无障碍的表单验证和错误恢复提供了一些有关无障碍表单验证的更多的有用信息。

### 其他 JavaScript 无障碍问题

在实现 JavaScript 和考虑无障碍时，还有其他需要注意的事项。一旦发现将会添加更多。

#### 鼠标特定事件

正如你所知，客户端 JavaScript 使用事件处理程序，实现大多数用户交互，它允许我们运行函数以响应某些事件的发生。某些事件可能有辅助功能问题。你将遇到的主要示例是鼠标特定的事件，如鼠标悬停（mouseover (en-US)）、鼠标划出（mouseout）、双击（dblclick）等。使用其他机制（如键盘控件）无法访问为这些事件而运行的功能。

为了缓解此类问题，你应该将这些事件与可以通过其他方式（所谓的设备独立事件处理程序）激活的类似事件相结合——focus 和 blur 将为键盘用户提供无障碍。

让我们看一个示例：突出显示了何时可能有用。我们想要实现一个缩略图：当鼠标悬停或聚焦在图像上，可以放大图像（正如电子商务产品目录所展示的）。

我们做了一个非常简单的示例，你可以在 mouse-and-keyboard-events.html 中找到（参见源码）。该代码具有显示和隐藏放大图像的两个函数。它由以下几行行实现，这些行将它们设置为事件处理程序：

```js
imgThumb.onmouseover = showImg;
imgThumb.onmouseout = hideImg;

imgThumb.onfocus = showImg;
imgThumb.onblur = hideImg;
```

当鼠标指针在缩略图上悬停或者移开，将分别调用前两行代码。此时不允许我们通过键盘访问缩略图——为了允许这一点，我们调用后两行代码，它们在图像聚焦和失焦时 (聚焦停止) 运行函数。这可以在图像加 tab 键实现，因为我们为图像的属性设置 `tabindex="0"`。

Click 事件很有趣——听起来它依赖于鼠标，但是大多数的浏览器，在有焦点的链接或者表单元素上，按下 enter/return 之后，或者在触屏设备上点击一个元素，都将会激活 onclick 事件处理程序。但是，当你允许非默认可聚焦事件使用 tabindex 进行焦点处理时，默认情况下不起作用，在这种情况下，你需要在按下确切键时进行专门检测（参见重新建立键盘的无障碍）。

总结
--

我们希望这篇文章在网页设计中关于 CSS 和 JavaScript 的无障碍问题提供了足够多的细节。

下一篇内容是，WAI-ARIA！

* 上一页
* Overview: Accessibility
* 下一页


移动端无障碍 - 学习 Web 开发

移动端无障碍
======

* 上一页
* Overview: Accessibility
* 下一页

随着通过手机设备访问 web 愈加常见，iOS 和 Android 等流行的平台都拥有了完善的无障碍工具，在这些平台上考虑 web 的无障碍是一件很重要事情。本文将着重介绍移动端无障碍的注意事项。

|  |  |
| --- | --- |
| 前提： |
 具备基本的计算机知识，对 HTML、CSS 和 JavaScript
 基本的了解，并理解之前课程中的文章。
  |
| 目标： | 了解移动设备上无障碍存在的问题，以及如何解决这些问题。 |

移动设备上的无障碍
---------

现代移动设备对无障碍和大多数 web 标准有很好的支持。那个因为移动设备和桌面设备使用了完全不同的技术而强制要求开发者使用浏览器嗅探并为它们提供不同网站的时代已经结束了（虽然现在还有许多公司仍然在检测用户移动设备的使用，并为这些设备提供一个独立的移动端域名）。

如今，移动设备一般都可以处理特性齐全的网站了，同时，为了能够让盲人成功的使用网站，主流平台甚至还内置了屏幕阅读器。移动设备也倾向于对“WAI-ARIA”有很好的支持。

你只要需要遵守良好的 web 设计规范和最佳的无障碍实践，就可以让你的网站在手机上无障碍地使用。

移动设备需要特别考虑一些例外情况；主要是：

* 控件交互——确保类似于按钮的 UI 控件可以在移动端（主要是触摸屏）和台式机/笔记本电脑（主要是鼠标/键盘）无障碍地使用
* 用户输入——在移动端尽可能的减少用户输入的要求（例如在表单中，尽量少打字）。
* 响应式设计——确保移动端布局正常的情况下，节省需要下载的图片大小，并考虑为高分辨率的屏幕提供图片。
Android 和 iOS 上的屏幕阅读器测试总结
-------------------------

最常见的移动端平台具有功能全面的屏幕阅读器。这些功能和桌面端屏幕阅读器大致相同，除了移动端屏幕阅读器大量的使用手势操作而不是按键组合操作。

让我们来看看最主要的两个：Android 上的 TalkBack 和 iOS 上的旁白（VoiceOver）。

### Android TalkBack

TalkBack 屏幕阅读器是内置于 Android 操作系统中的。

要启用它，请确定你的手机型号和 Android 版本，然后查找 TalkBack 菜单所在的位置。Android 版本之间，甚至不同的手机型号之间的差异通常很大。一些手机制造商（例如三星）在较新的手机中甚至没有 TalkBack，而是提供了自己的屏幕阅读器。

找到 TalkBack 菜单后，点击滑动开关启用 TalkBack。然后按照屏幕提示操作即可。

当启用 TalkBack 时，你的 Android 设备的基本操作将有所不同。举个例子：

1. 点击一个应用将会选择它，同时，你的设备将会告诉你这个应用程序是什么。
2. 在控制栏中左右滑动，将会在应用、按钮或控件之间切换。设备将会读出每一项。
3. 双击任何地方将会打开某个应用或者选择某个选项。
4. 你也可以“通过触摸来探索”——将手指按在屏幕上并拖拽，然后你的设备将会读出你移动经过的不同的应用或项目。

如果你想关闭 TalkBack：

1. 导航到 TalkBack 菜单屏幕（使用当前启用的不同手势）。
2. 导航到滑动开关，并激活它将其关闭。

**备注：** 你可以通过向左上方滑动返回桌面，如果你有多个桌面，你可以通过两个手指在屏幕上左右滑动来切换桌面。

关于 TalkBack 手势的完整列表，查看使用 TalkBack 手势。

#### 解锁手机

当 TalkBack 处于启用状态时，解锁手机有一点点不同。

你可以通过双根手指从底部向上滑动去锁定手机。如果你设置了密码或者手势，你将会进入相关的入口页去输入密码或手势。

你可以通过触摸屏幕的中下部去找到*解锁*按钮，然后双击它解锁手机。

#### 全局菜单和本地菜单

TalkBack 允许你使用全局和本地菜单，无论你已经导航到哪个位置。前者提供和设备相关的全局选项，后者提供和当前你所在的应用或屏幕相关的选项。

要进入这些菜单：

1. 快速向下然后向右滑动唤起全局菜单。
2. 快速向上然后向右滑动唤起本地菜单。
3. 向左右滑动可以选择不同的菜单。
4. 一旦你选择了你想要的选项，双击它可以直接选择。

想要查看全局和本地上下文菜单的详细选项，请查看使用全局和本地上下文菜单。

#### 浏览网页

你可以在浏览器中使用本地上下文菜单来查看仅使用标题、表单控件、链接，或逐行浏览等方式浏览网页。

例如，当 TalkBack 处于启用状态时：

1. 打开浏览器。
2. 激活地址栏。
3. 进入一个大量标题的网页，如 bbc.co.uk 的首页。输入网址的文字：
    * 通过左右滑动来找到地址栏，然后双击它。
    * 手指按在虚拟键盘上，选择你想要的字符，松开手指输入它，重复上述操作输入完所有的字符。
    * 输入完之后，找到 Enter 键并按下
4. 向左右滑动，以在页面上不同的项目之间切换。
5. 向上然后向右滑动进入本地内容菜单。
6. 向右滑动直到你找到“标题和标识”选项。
7. 双击选择它。现在你就可以通过左右滑动在标题和 ARIA 标识之间切换。
8. 向右向上滑动之后，进入本地上下文菜单，选择“默认”，就可以返回默认模式。

**备注：** 查看开始在 Android 设备上使用 TalkBack 以获取更完整的文档。

### iOS 旁白

iOS 操作系统内置了移动版旁白（VoiceOver）。

要打开它，请转到*设置*，然后选择*无障碍 > 旁白*。点按*旁白*的滑动开关去启用它（你还会在页面中看到很多和旁白相关的其他选项）。

**备注：** 一些较老的 iOS 设备的旁白菜单在*设置* > *通用* > *辅助功能* > *旁白*。

一旦启用旁白，iOS 的基本操作手势将有所不同：

1. 单击将会导致项目被选中，你的设备将会告诉你，你点击的是什么应用。
2. 你也可以通过向左右滑动屏幕来移动屏幕上的项目，或者在屏幕上滑动手指以移动项目（当你找到你想要的项目的时候，把手指离开屏幕来选中它）。
3. 双击屏幕上的任意位置，可以激活选中的项目（例如，打开选中的 App）。
4. 通过三根手指滑动浏览页面。
5. 用两个手指点击来执行上下文相关的操作，例如在相机里拍摄照片。

要再次将其关闭，你必须使用上述手势导航到*设置 > 常规 > 无障碍 > 旁白*，然后将旁白切换回关闭状态。

#### 解锁手机

你需要正常的按下 HOME 键（或划过）就可以解锁手机了。如果你设置了密码，你可以通过滑动来选择每一个数字，然后在找到合适的数字后双击输入每一个数字。

#### 使用转子

当旁白打开时，你可以使用一种名为“转子”（Rotor）的导航功能，该功能可让你快速从多种常用选项中进行选择。要使用它：

1. 像转动拨号盘一样在屏幕上扭动两根手指。当你扭动更多的时候，每个选项都会被朗读。你可以来回循环浏览选项。
2. 一旦你找到你想要的选项：
    * 松开手指来选择它。
    * 如果你可以调整其至的大小（例如音量或语速），则可以通过上下滑动来控制所选项的值。

转子上的提供的选项是上下文相关的，它们会根据你所在的应用程序或者视图的不同而不同（参见下面的示例）。

#### 浏览网页

让我们尝试使用旁白浏览网页：

1. 打开你的浏览器。
2. 激活地址栏。
3. 进入一个有大量标题的网站，就像 bbc.co.uk 的首页。输入网址：
    * 通过向左右滑动来选择地址栏，找到之后双击选择它。
    * 对于每一个字符，手指在虚拟键盘上长按，直到找到你想要的字符，然后释放手指来选择它。双击即可输入。
    * 完成后，找到 Enter 键并按下。
4. 向左右滑动来在页面上切换不同的项目。你可以通过双击来选择它（例如，跟随链接）。
5. 默认情况下，被选中的转子选项应该是语速，你可以通过上下滑动来增加或减少语速。
6. 现在像拨号盘一样围绕屏幕转动两根手指，以显示转子并在其选项之间移动。以下是可用选项的一些示例：
    * *语速*：改变语速。
    * *容器*：在页面不同语义的容器间切换。
    * *标题*：在页面上的标题之间切换。
    * *链接*：在页面上的链接之间切换。
    * *表单控件*：在页面上的表单控件之间切换。
    * *语言*：在不同的翻译之间切换，如果这些翻译可用。
7. 选择*标题*，现在你可以通过上下滑动在页面的不同标题中切换。

**备注：** 有关 iOS 上可用的旁白手势以及有关辅助功能的其他提示的更完整资料可以查看在你的设备上用旁白测试辅助功能。

控制机制
----

在我们的 CSS 和 JavaScript 无障碍文章中，我们研究了特定于某种控制机制的事件的概念（请参阅特定于鼠标的事件）。回顾一下，因为其他控制机制不能激活相关的功能，将会导致辅助功能的问题。

举例来说，点击事件在无障碍方面是良好的——通过点击处理器设置的元素，选中它并按下回车或返回，或者在触摸屏设备上点击它，可以调用关联的事件处理程序。试试我们的 simple-button-example.html 示例（查看实时示例）以理解我们的意思。

另一方面，像 mousedown 和 mouseup 这些特定的鼠标事件会产生一些问题——无法使用鼠标以外的控制设备调用这些事件处理器。

如果你尝试通过键盘或触摸来控制我们的 simple-box-drag.html 示例（查看实时示例），你将发现问题。它发生的原因是我们用了下面的代码：

```js
div.onmousedown = function () {
  initialBoxX = div.offsetLeft;
  initialBoxY = div.offsetTop;
  movePanel();
};

document.onmouseup = stopMove;
```

要启用其他形式的控制，你需要使用其他等效的事件代替，比如在触屏设备上用 touch 事件：

```js
div.ontouchstart = function (e) {
  initialBoxX = div.offsetLeft;
  initialBoxY = div.offsetTop;
  positionHandler(e);
  movePanel();
};

panel.ontouchend = stopMove;
```

我们提供了一个简单的示例来展示如何使用鼠标和触摸事件——multi-control-box-drag.html（查看实时示例）。

**备注：** 你可以看到一个功能完善的示例，展示如何在实现游戏控制机制中实现不同的控制机制。

响应式设计
-----

响应式设计是根据屏幕大小和分辨率等因素动态更改你的应用程序的布局和其他功能的做法，因此对于不同设备类型的用户来说，它们是可用且无障碍的。

特别是，移动端设备需要解决的最常见的问题是：

* 移动端设备布局的适用性。例如，在窄屏上多列布局不能很好的工作，需要增加文字大小以提高可读性。这些问题可以通过媒体查询、视口、弹性盒子来解决。
* 节省下载的图片大小。一般来说，小屏幕设备不需要与桌面设备一样大的图像，而且它们将更可能在慢速网络连接上。因此，适当地缩小屏幕设备以缩小图像是明智的。你可以使用响应式图像技术处理此问题。
* 考虑高分辨率。许多移动设备具有高分辨率屏幕，因此需要更高分辨率的图像，使得显示器可以继续看起来清晰和锐利。再次，你可以使用响应式图像技术来适当地提供图像。此外，使用 SVG 矢量图像格式可以满足许多图像要求，这些格式在目前的浏览器中得到了很好的支持。SVG 文件较小，且不论以何种大小显示，它都会保持清晰（请参阅向网页中添加矢量图形以了解更多的细节）。

**备注：** 我们不会在这里对响应式设计进行完整的讨论，因为它们在 MDN 其他地方都有涉及（参考上面的链接）。

### 具体的需要注意的点

这里有很多其他重要的需要考虑的点，它们可以让我们通过移动设备访问网站时更无障碍。我们在下面列出了一些，在我们想到更多内容时，我们将继续添加。

#### 不禁用缩放

使用视口可能会禁用缩放。要始终启用缩放，请在 `<head>` 中将宽度设置为设备宽度：

```html
<meta name="viewport" content="width=device-width; user-scalable=yes" />
```

如果可以的话，你绝不应该设置 `user-scalable=no`。很多人都会依靠缩放来看你网站的内容，所以禁用缩放这个功能是一个很糟糕的主意。在某些情况下缩放会破坏 UI；这种情况下，你觉得你需要禁用缩放，你可以提供一些别的近似的方法。例如增加一个控制文字大小的控件。

#### 保持菜单无障碍

因为移动设备上的屏幕非常窄，所以使用媒体查询和其他技术使得导航菜单缩小到显示屏顶部的一个小图标，只有在需要的时候才展示菜单，这种方式在移动设备上很常见的。这通常由“三横线”图标表示，并且设计模式因此被称为“汉堡菜单”。

在实现这样的菜单时，需要确保显示控件的控件可以通过适当的控制机制（移动端通常为触摸）进行访问，如上面的控制机制中所讨论的那样，并且在访问菜单时页面的其他部分以某种方式移开或隐藏，以避免与导航混淆。

让我们来看一个很好的“汉堡包菜单”的示例。

用户输入
----

在移动设备上，输入数据往往比在台式计算机上的同等体验更令用户恼火。使用桌面或笔记本电脑键盘输入文本到表单输入比触摸屏虚拟键盘或微小的移动物理键盘更方便。

出于这个原因，值得尽量减少所需的输入量。例如，与其让用户每次使用常规文本输入来填写他们的工作标题，而是可以提供一个 `<select>` 菜单，其中包含最常见的选项（这也有助于数据输入的一致性），并提供一个“其他”选项，显示一个文本字段来输入任何异常值。你可以在 common-job-types.html中看到这个想法的一个简单示例（查看常见任务实时示例）。

也值得考虑在移动平台上使用 HTML 格式输入类型（如日期），因为它们可以得到很好的处理。例如，Android 和 iOS 都会显示可用于设备体验的可用控件。有关示例，请参阅 html5-form-examples.html（请查看 HTML5 表单实时示例）——尝试加载这些内容并在移动设备上对其进行操作。例如：

* 在输入数字（`number`）、电话（`tel`）和邮件（`email`）时，展示合适的虚拟键盘来输入数字。
* 在输入时间（`time`）和日期（`date`）时展示合适的选择器来选择时间和日期。

如果你想为桌面端提供不同的解决方案，则可以使用特性检测为你的移动设备始终提供不同的标记。有关检测不同输入类型的原始信息，请参阅输入类型，还可以查看我们的特性检测文章获取更多信息。

总结
--

在本文中，我们向你提供了有关常见移动设备无障碍问题的一些细节以及如何克服这些问题。我们还通过使用最常用的屏幕阅读器来帮助你进行无障碍测试。

参见
--

* 移动 Web 开发指南——“Smashing”杂志的文章列表，涵盖移动网页设计的不同技术。
* 使你的网站在触摸设备上工作——有关使用触摸事件来获得在移动设备上进行交互的有用文章。
* 上一页
* Overview: Accessibility
* 下一页


WAI-ARIA 基础 - 学习 Web 开发

WAI-ARIA 基础
===========

* 上一页
* Overview: Accessibility
* 下一页

紧接上文继续，有时候，我们制作涉及非语义 HTML 和动态的 JavaScript 内容更新的复杂 UI 控件可能很困难。**WAI-ARIA** 是一项技术，它可以通过浏览器和一些辅助技术来帮助我们进一步地识别以及实现语义化，这样一来能帮助我们解决问题，也让用户可以了解发生了什么。接下来我们将展示如何运用它来优化无障碍体验：

|  |  |
| --- | --- |
| 前提要求： | 基础的电脑知识，对于 HTML，CSS，JavaScript 的了解，还有对于前文课程的了解。 |
| 目标： |
 进一步了解
 WAI-ARIA，明白他如何提供有效的语义，以便接下来在有需要的时候提供无障碍优化。
  |

何为 WAI-ARIA?
------------

让我们开始看看何为 WAI-ARIA，以及它能给我们什么用。

### 一堆新的问题

当 Web 应用开始变得越来越复杂和动态化，一堆全新的无障碍访问问题和特性接踵而至。

例如，HTML5 提出了几种语义化标签用于定义常规页面的特性 (例如 nav, footer 等等) 。在这些标签可用之前，我们一般简单地用 div 带上 ID 抑或是 class 来解决问题，例如：`<div class="nav">`。但是这种实践是问题丛生的，因为没有简单的方法可以轻松地用可编程的方法找到特定页面功能，例如主导航。

最早的解决方案是加一个或者多个隐藏的链接来跳转到我们想要的位置，例如（这里用导航举例）：

```html
<a href="#hidden" class="hidden">Skip to navigation</a>
```

但这仍然是不准确的，而且只能在屏幕阅读器开启页面顶部读取时使用。

另一个例子：应用开始支持一些复杂的类型输入，像是日期选择器可选择日期，抑或是范围选择器可以用滑块选择值，HTML5 提供了以下的类型：

```html
<input type="date" /> <input type="range" />
```

他对于跨浏览器的支持并不好，而且他的样式修改也很麻烦，这使得他在网页的集成设计上难以有所用途。所以我们常常会用 JavaScript 库来做这事，所以会用一系列嵌套的 div 或者带有 class 的 table 元素，然后用 CSS 来制定样式，JavaScript 来控制行为。

这样的问题是视觉上这样做事可行的，但屏幕阅读器对此会感到一无所知，他只能告诉用户她看到一堆复杂结构的元素，且毫无语义可言。

### 进入 WAI-ARIA

WAI-ARIA 是 W3C 编写的规范，定义了一组可用于其他元素的 HTML 特性，用于提供额外的语义化以及改善缺乏的无障碍。以下是规范中三个主要的特性：

* **角色** — 这定义了元素是干什么的。许多「标志性的角色」，其实重复了 HTML5 的结构元素的语义价值。例如 `role="navigation"` (`<nav>`) 或者 `role="complementary"` (`<aside>`)，这也有一些描述其他页面结构的（角色），例如 `role="banner"`, `role="search"`, `role="tabgroup"`, `role="tab"` 等等。我们通常能从 UI 层面找到它们。
* **属性** — 我们能通过定义一些属性给元素，让他们具备更多的语义。例如： `aria-required="true"` 意味着元素在表单上是必填的。然而 `aria-labelledby="label"` 允许你在元素上设置一个 ID，用于`labelledby`引用作为屏幕阅读器指定的 label 内容，多个也可以。当然，下面这个代码是不行的： `<label for="input">` 。举个例子：你可以用 `aria-labelledby` 指定包含在 a 标签中的 key 描述`<div>` 是多个 table 表格的 label，或者将它指定为 img 标签的 alt 内容 — 而无需重复在每一个 img 里头定义。如果迷糊了，你可以在这里看到例子： Text alternatives.
* **状态** —用于表达元素当前的条件的特殊属性，例如 `aria-disabled="true"`，屏幕阅读器就会这个表单禁止输入。状态和属性的差异之处就是：属性在应用的生命周期中不会改变，而状态可以，通常我们用编程的方法改变它，例如 Javascript。

关于 WAI-ARIA 属性重要的一点是它不会对 web 页面有任何影响，除了让更多的信息从浏览器暴露给 accessibility APIs (无障碍 API)，这也是屏幕阅读器这一类软件的信息源。WAI-ARIA 不会影响网页的结构，以及 DOM 等等，尽管这些属性可用于作为 css 选择器。

**备注：** 关于 ARIA 的角色和他的用法，如需了解更多信息，尽在 WAI-ARIA 规范，查看 角色定义

规范同时也包含了属性和状态的一个列表，链接有更多详尽信息：查看 属性和状态的定义（所有的 aria-\* 属性）

### 在哪里支持 WAI-ARIA？

这不是一个容易回答的问题。很难找到一个确定的资源，说明支持 WAI-ARIA 的哪些功能，以及在哪里，因为

1. WAI-ARIA 规范的特性太多了。
2. 操作系统、浏览器、屏幕阅读器三者相加的组合太多了，这些都需要考虑。

最后一个关键点——首先使用屏幕阅读器，你的操作系统需要运行具有必要的辅助功能 API 的浏览器，以便公开屏幕阅读器完成工作所需的信息。大部分流行的操作系统都有一到两个支持屏幕阅读器的浏览器。Paciello 组织有一个新的帖子，以供参考： Rough Guide: browsers, operating systems and screen reader support updated.

接下来，你需要考虑下有问题的浏览器是否支持无障碍特性以及提供他们 API 格式的信息暴露，并且屏幕阅读器是否识别信息并且正确地传达给用户。

1. 文章到现在，可以看得出浏览器端对于无障碍的支持做的很好。 caniuse.com 这一网站显示全球浏览器支持 WAI-ARIA 的比率达到了 88%。
2. 屏幕阅读器支持无障碍特性反而没达到这个水平，但是主流的屏幕阅读器做到了。你可以通过查看 Powermapper 来了解支持级别 WAI-ARIA Screen reader compatibility 。

我们目的不是详细介绍所有的 WAI-ARIA 特性，以及它大部分支持的细节。相反，介绍最主要的 WAI-ARIA 功能。我们没有提到的任何支持细节，你可以假定该特性得到了良好的支持。我们将清楚地介绍例外情况。

**备注：** 一些 JavaScript 库支持 WAI-ARIA，意味着生成 UI 界面时，例如复杂的表单控件，他们会添加 ARIA 属性来优化它的无障碍特性。如果你再找一些第三方 JavaScript 解决方案来进行快速的 UI 开发，当你做选择的时候，必须重视 UI 小部件的无障碍。一个良好的例子就是 jQuery UI (请看 About jQuery UI: Deep accessibility support), ExtJS 还有 Dojo/Dijit。

### 何时你应使用 WAI-ARIA?

我们过去讨论了一些促使 WAI-ARIA 诞生的问题。但基本上是以下四个主要领域：

1. **路标/地标**（**Signposts/Landmarks**）**：** ARIA 的 `角色` 属性值可以作为地标来复制 HTML5 元素的语义化（例如 nav tag）。或者超越 HTML5 的语义，给不同的功能块提供「路标」，例如 `search`, `tabgroup`, `tab`, `listbox` 等等。
2. **动态的内容更新：** 屏幕阅读器往往难以报告一直变化的内容，用无障碍特性我们能使用 `aria-live` 来通知屏幕阅读器某一部分的内容更新了。例如XMLHttpRequest 或者 DOM APIs。
3. **优化键盘的无障碍操作**: 默认的 HTML 元素是具有自带的键盘辅助功能的。当其他元素与 JavaScript 一起进行交互时，键盘的辅助功能和屏幕阅读器的报告会因此收到影响（例如你将会难以用 tab 到达理想的位置）。这是无法避免的，WAI-ARIA 提供了提供了一种允许其他元素获得焦点的方法（使用 `tabindex`）。
4. **非语义控件的无障碍**：当一系列嵌套的 `<div>` 与 CSS / JavaScript 一起用于创建复杂的 UI 功能，或者通过 JavaScript 大大地增强或者更改原生的控件，无障碍将会变得极其困难——屏幕阅读器将会难以找到语义内容线索。在这种情况下，AIRA 可以帮助提供缺少了的功能，例如 `button`, `listbox`，或者 `tabgroup`，另外和 aria-required 或 aria-posinset 这样的属性可以提供有关功能的更多线索。

注意：\*\*你只在需要的情况下使用无障碍特性！\*\*理想的情况下，你只要用原生的 HTML 来实现屏幕阅读器所需的语义化内容即可。有些时候这是不可能的，一来是你对于代码的整体的控制是有限的，另一方面是总会有复杂到原生 HTML 无法支持的功能需要你实现。在这个场景下，WAI-ARIA 将会变成有价值的可访问优化功能。

**但还是要重申：当你需要的时候再使用无障碍特性！**

**备注：** 另外，请尝试确保你的真实用户来测试你的网站：普通人，使用屏幕阅读器的用户，使用键盘导航的人。他们会提供你更多的见解。

实用的 WAI-ARIA 实现
---------------

在下一节中，我们将更详细地研究这四个方，并提供一些实例。继续之前你最好安装一个屏幕阅读器，以便你测试接下来的用例。（接下来的屏幕阅读器默认为 Mac 的 VoiceOver，Windows 用户可以尝试 JAWS 或者 Window Eyes）

查看我们的 testing screenreaders 得到更多关于屏幕阅读器的信息。

### 路牌/地标（**Signposts/Landmarks**）

WAI-ARIA 给浏览器增加了 `role` 属性，这允许我们给站点中的元素增加我们想要的语义属性。第一个主要区域便是用于为屏幕阅读器提供信息，以便用户可以找到常见的页面元素。我们来举个例子，一个没有角色的站点的例子（在线演示）的页面结构：

```html
<header>
  <h1>...</h1>
  <nav>
    <ul>
      ...
    </ul>
    <form>
      <!-- search form -->
    </form>
  </nav>
</header>

<main>
  <article>...</article>
  <aside>...</aside>
</main>

<footer>...</footer>
```

如果你用现代浏览器打开，并用屏幕阅读器测试，你就已经得到你要的信息了。例如 VoiceOver 会给你以下信息（会以英文念出）：

* 在 `<header>` 元素 — "banner, 2 items" (它包含标题和 `<nav>`).
* 在 `<nav>` 元素 — "navigation 2 items" (它包含一个列表和一个表单).
* 在 `<main>` 元素 — "main 2 items" (它包含文章和侧边栏).
* 在 `<aside>` 元素 — "complementary 2 items" (它包含列表和标题。
* 在搜索表单输入 — "Search query, insertion at beginning of text".
* 在 `<footer>` 元素 — "footer 1 item".

如果你转到 VoiceOver 的地标菜单（使用 VoiceOver 绑定键（你可以在 VoiceOver Utility 中设置） + U 访问，然后使用光标或者键盘来选择菜单选项），你将看到大部分元素都已很好地列出，因此可以快速访问它们。

![](/zh-CN/docs/Learn/Accessibility/WAI-ARIA_basics/landmarks-list.png)

尽管如此，我们可以做的更好。这个搜索表单是一个人们愿意找到的重要的地标，我们可以设置 input 的类别为 search (`<input type="search">`)。另外，在一些老的浏览器（尤其是 IE8）是无法识别的这些 HTML5 的元素语义化的。

让我们来优化上文代码并且用上无障碍特性。首先我们给 HTML 的结构加上角色。你可以复制上文 demo 的 index.html 和 style.css 继续修改，或者看我们的网站无障碍角色版本例子（在线 demo），结构如下：

```html
<header>
  <h1>...</h1>
  <nav role="navigation">
    <ul>
      ...
    </ul>
    <form role="search">
      <!-- search form -->
    </form>
  </nav>
</header>

<main>
  <article role="article">...</article>
  <aside role="complementary">...</aside>
</main>

<footer>...</footer>
```

我们用了一个额外的功能：input 元素用了属性 `aria-label`, 它给它一个描述性标签，可以由屏幕阅读器读出，尽管我们没有 label 元素。在这些情况下，这非常有用——像这样的搜索表单是一个非常常见的，易于识别的功能，添加 label 会破坏页面设计。

```html
<input
 type="search"
 name="q"
 placeholder="Search query"
 aria-label="Search through site content" />
```

现在我们再用 VoiceOver，会得到以下改进：

* 搜索表单在浏览页面时和地标菜单中都作为单独的项目存在。
* 因为有 `aria-label` ，那么读取到这个 input 他的内容会被高亮念出。

除此之外，为了让 IE8 等旧版浏览器的用户更容易访问该网站，ARIA 角色的使用就很值得了。如果由于某种原因，你的网站仅使用<div> 构建，那么你肯定很需要用 ARIA 角色以提供所需的语义！

搜索表单的改进语义表明当超出 HTML5 中可用的语义时 ARIA 可以实现的功能。你接下来可以看到这些语义和 ARIA 属性的强大功能，尤其是 非语义控件的无障碍那一段。接下来我们将明白 ARIA 如何在进行动态内容更新时给我们帮助。

### 动态内容更新

使用屏幕阅读器可以轻松访问读取到 DOM 中的内容，从文本内容到附加到图像的 alt 文本。所以具有大量文本内容的传统静态网站易于为视碍人士提供信息。

问题在于现代 Web 应用程序通常不仅仅是静态文本——它们往往有很多动态更新内容，即通过 XMLHttpRequest，Fetch 或DOM API 等机制重新加载整个页面的内容。这些有时被称为**实时区域**。

我们来看一个小例子——aria-no-live.html（在线 demo）。在这个例子我们引用一个小的随机引用块：

```html
<section>
  <h1>Random quote</h1>
  <blockquote>
    <p></p>
  </blockquote>
</section>
```

我们的 JavaScript 从 `XMLHttpRequest` 加载一个 JSON 文件里头包含了一系列的名人名言，一旦完成我们就开始用一个 `setInterval()` (en-US) 循环以十秒一次的频率显示出来。

```js
var intervalID = window.setInterval(showQuote, 10000);
```

这当然是可行的，但是对于无障碍可不友善——这种内容变化是不会被屏幕阅读器察觉到的，所以用户不会发现发生了什么。这是一个简单的例子，但你可以想象一下：如果你开发的一个复杂 UI 而且内容频繁变化的应用，例如聊天室，或者一个策略游戏的界面，或者一个实时更新的购物车展示。如果没有某种方式提示用户有内容更新，那就不可能以任何有效的方式来使用应用。

幸运的是，WAI-ARIA 提供了一种有效的机制来发起提示——`aria-live`。将此应用于元素会让屏幕阅读器读出更新的内容。读取内容的紧急程度取决于属性值：

* `off`: 默认值，更新不会提醒。
* `polite`: 只有用户空闲的情况下提醒。
* `assertive`: 尽快提醒。
* `rude`: 会以打断用户操作的方式直接提醒。

通常来说 `assertive` 设置足以让你的更新在显示时按时序读出，因此，如果改变多次，那么他只会念出最后一个改变。除非紧急程度高到需要覆盖其他的更新才选择使用 `rude` 。

我们可以复制 aria-no-live.html 和 quotes.json ，然后像下面一样更新你的 `<section>` tag ：

```html
<section aria-live="assertive"></section>
```

这会让你的屏幕阅读器在更新时可以读取内容。

**备注：** 当你用 `file://` 协议头来发 `XMLHttpRequest` 大部分浏览器会抛出 security exception。所以你可能要设置一个 web 服务器来作为请求源，例如，使用 GitHub，或者设置一个本地服务器 Python's SimpleHTTPServer。

这里有一个附加的考虑——只读取更新的文本位。如果我们总是读出标题可能会很好，这样用户就可以记住正在读出的内容。为了能做到这个，我们增加了 `aria-atomic` 给 section。再次更新 `<section>`，像这样：

```html
<section aria-live="assertive" aria-atomic="true"></section>
```

这个 `aria-atomic="true"` 属性告诉屏幕阅读器去读取整个元素的内容作为一个原子单位，而不是里头某个字符串更新了。

**备注：** 你可在此完成此例子 aria-live.html (在线 demo).

**备注：** `aria-relevant` 属性对于控制更新实时区域时读取的内容也非常有用。例如，你读取内容添加或删除。

### 优化键盘的无障碍操作

正如上下文中其他几处讨论的，HTML 在无障碍方面的关键优势之一是按钮，表单控件和链接等功能的内置键盘无障碍。平时你可以使用 Tab 键在控件之间移动，使用 Enter / Return 键选择或激活控件，偶尔也可以根据需要使用其他控件（例如上下光标在`<select>` 框中的选项之间移动）。

但是在一些时候，你最终还是得编写代码去使用非语义元素作为按钮（或其他类型的控件），或者使用可聚焦控件来达到错误的目的。你可能正在尝试修复一些你之前的错误代码，或者你可能正在构建某种需要它的复杂小部件。

在让不可聚焦代码可聚焦这一方面，WAI-ARIA 用一些新的值来扩展了`tabindex` 的属性：

* `tabindex="0"` — 如上所述，这个值让不能被 tab 的元素变得 tabbable。这是 `tabindex` 最有用的值。
* `tabindex="-1"` — 这允许通常不可列表的元素以编程方式来接收 focus。例如用：JavaScript，或者作为链接的目标。

 我们更详细地讨论了这一点，并在 HTML 辅助功能文章中显示了一个典型的实现
 ——请看 Building keyboard accessibility back in.

### 非语义控件的无障碍

当一系列嵌套的 `<div>`s 与 CSS / JavaScript 一起用于创建复杂的 UI 功能，或者通过 JavaScript 大大地增强或者更改原生的控件，不仅键盘无障碍受损。而且如果没有语义或其他线索，屏幕阅读器用户会发现很难弄清楚该功能的作用。在这种情况下，ARIA 可以帮助提供那些缺失的语义。

#### 表单验证和错误显示

首先，让我们在此访问之前的文章（重读 Keeping it unobtrusive）。在本节的最后，我们展示了当你尝试提交表单时，如果存在验证错误，我们在错误消息框中包含了一些 ARIA 属性：

```html
<div class="errors" role="alert" aria-relevant="all">
  <ul></ul>
</div>
```

* `role="alert"` 自动将其转变为实时区域，所以它一变化就会念出来。也语义化地说明了这是一个 alert 信息（重要的 时间/上下文 敏感信息），而且展现了一种更好，更加易于读取的警告用户的方式（模态警告例如 `alert()` 的调用会导致一系列的无障碍问题，详情请看Popup Windows ）。
* 一个 `aria-relevant` 的值为 `all` 会指示屏幕阅读器在对其进行任何更改时读出错误列表的内容 — 即为错误的增加或者消失。这是很有用的，因为用户需要知道具体哪个错误的出现或者消失，不仅仅是表单错误列表出现了增加或者删除。

我们可以在 ARIA 的应用上更进一步，并提供更多验证上的帮助。例如支出某个字段是否必填，或者是要填的年龄的区间该是多少？

1. 首先，复制刚刚的 form-validation.html 还有 validation.js 文件，然后保存到本地。
2. 把两个文件都用文本编辑器打开并且看看运作原理。
3. 首先，在`<form>` 标签的正上方添加一个段落，如下，并用星号标记表单<label>。这通常是我们为有视力的用户标记必填字段的一个常用手法。

```html
<p>Fields marked with an asterisk (*) are required.</p>
```

4. 这对于具备视力的人显而易见，但是对于屏幕阅读器用户而言就不友好了。所幸 WAI-ARIA 提供了 `aria-required` 属性来让屏幕阅读器获取提示来告诉用户这个 input 必须填写，更新你的 `<input>` 元素如下：

```html
<input type="text" name="name" id="name" aria-required="true" />

<input type="number" name="age" id="age" aria-required="true" />
```

5. 你过你保存了并且现在用屏幕阅读器测试，你会听到如下内容：「Enter your name star, required, edit text」
6. 回到第二个关于数值范围的讨论，通常我们会用一个 tooltips 来展示，或者用 placeholder 显示提示信息。WAI-ARIA 有一个 `aria-valuemin` 和 `aria-valuemax` 属性来执行最大最小值，但现阶段看来支持程度并不好。另一个好办法就是用 `placeholder` 属性，当用户输入的时候，就会念出 placeholder 的内容最为信息提示。更新你的数值输入 input 如下：

```html
<input
 type="number"
 name="age"
 id="age"
 placeholder="Enter 1 to 150"
 aria-required="true" />
```

**备注：** 你可以在这里看这个在线完成的例子 form-validation-updated.html.

除了经典的 `<label>` 元素之外，WAI-ARIA 还支持一些高级表单标注技术。我们已经讨论过使用 `aria-label` 属性来提供标签，我们不希望标签对于有视力的用户是可见的（参见上面的 路牌/地标（Signposts/Landmarks） 部分）。还有一些其他标签技术使用其他属性，例如 `aria-labelledby` ，如果你想将非<label>元素指定为标签或标签多个表单输入具有相同的标签，并且 `aria-describedby`，如果你想关联 带有表单输入的其他信息，并将其读出。请查阅文章获得更多细节： WebAIM's Advanced Form Labeling article

还有许多其他有用的属性和状态，用于指示表单元素的状态。例如：`aria-disabled="true"` 可用于表示该表单字段已禁用。许多浏览器只会跳过禁用的表单字段，它们甚至不会被屏幕阅读器读出，但在某些情况下它们会被识别出来，所以最好包含这个属性让屏幕阅读器知道禁用的输入事实上已经被禁用。

如果输入的禁用状态可能会改变，那么指示它何时发生以及结果是什么也是一个好主意。例如，在我们的form-validation-checkbox-disabled.html 这一 demo 中，有一个复选框，选中后，启用另一个表单输入以允许输入更多信息。我们已经建立了一个隐藏的实时区域：

```html
<p class="hidden-alert" aria-live="assertive"></p>
```

这是使用绝对定位隐藏的视图。当选中/取消选中此项时，我们会更新隐藏的实时区域内的文本，以告诉屏幕阅读器用户检查此复选框的结果是什么，以及更新`aria-disabled`状态和一些可视指示器：

```js
function toggleMusician(bool) {
  var instruItem = formItems[formItems.length - 1];
  if (bool) {
    instruItem.input.disabled = false;
    instruItem.label.style.color = "#000";
    instruItem.input.setAttribute("aria-disabled", "false");
    hiddenAlert.textContent =
      "Instruments played field now enabled; use it to tell us what you play.";
  } else {
    instruItem.input.disabled = true;
    instruItem.label.style.color = "#999";
    instruItem.input.setAttribute("aria-disabled", "true");
    instruItem.input.removeAttribute("aria-label");
    hiddenAlert.textContent = "Instruments played field now disabled.";
  }
}
```

#### 描述非语义的 button 是个 button

在本课程中已经有几次，我们已经提到了原生的无障碍（以及使用其他元素伪造导致的无障碍问题）按钮，链接或表单元素（请参阅 HTML 辅助功能文章中的UI 控件 ，以及优化键盘的无障碍操作，上面）。基本上，利用 tabindex 和一些 JavaScript 的话，大部分情况下添加键盘辅助功能不会有多少麻烦。

但是屏幕阅读器呢？他们还是看着这个元素并不是一个 button，如果你用屏幕阅读器测试我们的 fake-div-buttons.html 例子，你会听到一段短语描述这个按钮，内容大概是 "Click me!, group"，显然这会让人疑惑。

依旧，WAI-ARIA 的角色可以解决一切，复制文件 fake-div-buttons.html，然后加上 `role="button"` 到每一个 button `<div>`，如下所示

```html
<div data-message="This is from the first button" tabindex="0" role="button">
  Click me!
</div>
```

这时候再用屏幕阅读器，这次你会听到短语“Click me!, button”——舒服了。

**备注：** 别忘了无论如何用正确的语义化元素是最佳选择。如果你想创建一个按钮，你可用 `<button>` 元素，你应该用 `<button>` 元素！

#### 通过复杂的小部件做引导用户

还有许多其他 roles 可以将非语义元素结构识别为常见的 UI 功能，这些功能超出了标准 HTML 中可用的功能，例如 `combobox`, `slider`, `tabpanel`, `tree`.。你可以在 Deque university code library 中看到许多有用的示例，以便了解如何使这些控件做到无障碍的。

让我们来看看我们自己的一个例子。我们将返回到我们简单的绝对定位选项卡界面（请参阅我们的 CSS 和 JavaScript 无障碍的文章的 Hiding things 段落），你可以在 Tabbed info box example中找到它（源码地址）。

这个例子在键盘无障碍方面运行良好——你可以愉快地在不同选项卡之间进行 tab 并选择它们然后显示选项卡内容。它也是相当容易访问的——你可以滚动浏览内容并使用标题进行导航，即使你无法看到屏幕上发生的事情。然而，内容并不明显——屏幕阅读器目前将内容报告为链接列表，以及一些内容包含三个标题。它不会让你知道内容之间的关系。为用户提供有关内容结构的更多线索总是好的。

为了优化它，我们创建了一个新的示例，名为 `aria-tabbed-info-box.html`（查看在线运行的实例）。我们更新了选项卡式界面的结构，如下所示：

```html
<ul role="tablist">
  <li
 class="active"
 role="tab"
 aria-selected="true"
 aria-setsize="3"
 aria-posinset="1"
 tabindex="0">
    Tab 1
  </li>
  <li
 role="tab"
 aria-selected="false"
 aria-setsize="3"
 aria-posinset="2"
 tabindex="0">
    Tab 2
  </li>
  <li
 role="tab"
 aria-selected="false"
 aria-setsize="3"
 aria-posinset="3"
 tabindex="0">
    Tab 3
  </li>
</ul>
<div class="panels">
  <article class="active-panel" role="tabpanel" aria-hidden="false">
    ...
  </article>
  <article role="tabpanel" aria-hidden="true">...</article>
  <article role="tabpanel" aria-hidden="true">...</article>
</div>
```

**备注：** 这里最明显的变化是我们删除了最初在示例中出现的链接，并且只使用了列表项作为选项卡——这样做是因为它使屏幕阅读器用户不那么容易混淆（链接并不会跳转，它们只更改视图），它允许大小修改/位置变化一类的特性更好地工作——当这些被放在链接上时，浏览器始终报告“1 of 1”，而不是“1 of 3”、“2 of 3”等。

以下刚刚用上的新特性：

* 新角色 — `tablist`, `tab`, `tabpanel` — 这些确定几个 tab 表界面的重要区域——tabs 的容器，tabs 自身，还有他们的一致性 tabpanels。
* `aria-selected` — 定义了 tab 当前正在被选中。和 tabs 被用户选中不同，这种值一般是由 JavaScript 修改。
* `aria-hidden` — 对屏幕阅读器隐藏一些元素，和 tabs 被用户选中不同，这种值一般是由 JavaScript 修改。
* `tabindex="0"` — 当我们删除链接时，我们需要为列表项提供此属性，以便为其提供键盘焦点。（为没有 tabindex 特性的元素也提供 tabindex 特性）
* `aria-setsize` — 此属性允许你指定屏幕阅读器元素是某个系列的一部分，以及该系列具有多少项。
* `aria-posinset` — 这个属性允许你设置一个元素在一个系列中的位置，随着 `aria-setsize`，他告诉屏幕阅读器（用于设置文件目录树视图）足够的信息去告诉你现在在 item "1 of 3" 位置等。大部分情况下，浏览器是可以从 DOM 层次结构中推断出这些信息，但它肯定有助于提供更多线索。

在我们的测试中，这个新结构确实有助于改善整体情况。这些选项卡现在被识别为选项卡（例如，屏幕阅读器说出「选项卡」），所选选项卡由“选择”表示，并使用选项卡名称读出，屏幕阅读器还会告诉你当前所在的选项卡编号。此外，由于`aria-hidden` 设置（只有非隐藏的选项卡有 `aria-hidden="false"` 设置），非隐藏内容是唯一可以向下导航的内容，这意味着所选内容更容易找到。

**备注：** 如果你有不想让屏幕阅读器读出来的东西，你可以给它一个 `aria-hidden="true"` 属性。

总结
--

本文并不是 WAI-ARIA 中的所有内容，但它应该为你提供足以了解使用它的信息，并提供了最常见的几种模式。

其他链接
----

* Definition of Roles — ARIA roles reference.
* Definitions of States and Properties (all aria-\* attributes) — properties and states reference.
* Deque university code library — a library of really useful practical examples showing complex UI controls made accessible using WAI-ARIA features.
* WAI-ARIA Authoring Practices — very detailed design patterns from the W3C, explaining how to implement different types of complex UI control whilst making them accessible using WAI-ARIA features.
* ARIA in HTML — A W3C spec that defines, for each HTML feature, what accessibility (ARIA) semantics that feature implicitly has set on it by the browser, and what WAI-ARIA features you may set on it if extra semantics are required.
* 上一页
* Overview: Accessibility
* 下一页


HTML 基础 - 学习 Web 开发

HTML 基础
=======

* 上一页
* Overview: Getting started with the web
* 下一页

超文本标记语言（英语：**H**yper**T**ext **M**arkup **L**anguage，简称：HTML）是一种用来结构化 Web 网页及其内容的标记语言。网页内容可以是：一组段落、一个重点信息列表、也可以含有图片和数据表。正如标题所示，本文将对 HTML 及其功能做一个基本介绍。

HTML 到底是什么？
-----------

HTML 不是一门编程语言，而是一种用于定义内容结构的*标记语言*。HTML 由一系列的元素组成，这些元素可以用来包围不同部分的内容，使其以某种方式呈现或者工作。一对标签可以为一段文字或者一张图片添加超链接，将文字设置为斜体，改变字号，等等。例如，键入下面一行内容：
```

My cat is very grumpy
```

可以将这行文字封装成一个段落元素来使其在单独一行呈现：

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

### HTML 元素详解

让我们深入探索一下这个段落元素。

![HTML 元素](/zh-CN/docs/Learn/Getting_started_with_the_web/HTML_basics/grumpy-cat-small.png)

这个元素的主要部分有：

1. **开始标签**（Opening tag）：包含元素的名称（本例为 p），被大于号、小于号所包围。表示元素从这里开始或者开始起作用——在本例中即段落由此开始。
2. **结束标签**（Closing tag）：与开始标签相似，只是其在元素名之前包含了一个斜杠。这表示着元素的结尾——在本例中即段落在此结束。初学者常常会犯忘记包含结束标签的错误，这可能会产生一些奇怪的结果。
3. **内容**（Content）：元素的内容，本例中就是所输入的文本本身。
4. **元素**（Element）：开始标签、结束标签与内容相结合，便是一个完整的元素。

元素也可以有属性（Attribute）：

![HTML 属性](/zh-CN/docs/Learn/Getting_started_with_the_web/HTML_basics/grumpy-cat-attribute-small.png)

属性包含了关于元素的一些额外信息，这些信息本身不应显现在内容中。本例中，`class` 是属性名称，`editor-note` 是属性的值。`class` 属性可为元素提供一个标识名称，以便进一步为元素指定样式或进行其他操作时使用。

属性应该包含：

1. 在属性与元素名称（或上一个属性，如果有超过一个属性的话）之间的空格符。
2. 属性的名称，并接上一个等号。
3. 由引号所包围的属性值。

**备注：** 不包含 ASCII 空格（以及 `"` `'` ``` `=` `<` `>`）的简单属性值可以不使用引号，但是建议将所有属性值用引号括起来，这样的代码一致性更佳，更易于阅读。

### 嵌套元素

也可以将一个元素置于其他元素之中——称作**嵌套**。要表明猫咪非常暴躁，可以将“very”用 `<strong>` 元素包围，“very”将突出显示：

```html

My cat is very grumpy.

```

必须保证元素嵌套次序正确：本例首先使用 `<p>` 标签，然后是 `<strong>` 标签，因此要先结束 `<strong>` 标签，最后再结束 `<p>` 标签。这样是不对的：

```html

My cat is very grumpy.

```

元素必须正确地开始和结束，才能清楚地显示出正确的嵌套层次。否则浏览器就得自己猜测，虽然它会竭尽全力，但很大程度不会给你期望的结果。所以一定要避免！

### 空元素

不包含任何内容的元素称为空元素。比如 `<img>` 元素：

```html

```

本元素包含两个属性，但是并没有 `</img>` 结束标签，元素里也没有内容。这是因为图像元素不需要通过内容来产生效果，它的作用是向其所在的位置嵌入一个图像。

### HTML 文档详解

以上介绍了一些基本的 HTML 元素，但孤木不成林。现在来看看单个元素如何彼此协同构成一个完整的 HTML 页面。回顾 文件处理 小节中创建的 `index.html` 示例：

```html
<!doctype html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>My test page</title>

```

这里有：

* `<!DOCTYPE html>`——文档类型。这是必不可少的开头。混沌初分，HTML 尚在襁褓（大约是 1991/92 年）之时，这个元素用来关联 HTML 编写规范，以供自动查错等功能所用。而在当今，它作用有限，可以说仅用于保证文档正常读取。现在知道这些就足够了。
* `<html></html>`——`<html>` 元素。该元素包含整个页面的所有内容，有时候也称作根元素。里面也包含了 `lang` 属性，写明了页面的主要语种。
* `<head></head>`——`<head>` 元素。所有那些你加到页面中，且*不*向观众展示的页面内容，都以这个元素为容器。其中包含诸如提供给搜索引擎的关键字和页面描述、用于设置页面样式的 CSS、字符集声明等等。
* `<meta charset="utf-8">`——该元素指明你的文档使用 UTF-8 字符编码，UTF-8 包括世界绝大多数书写语言的字符。它基本上可以处理任何文本内容。以它为编码还可以避免以后出现某些问题，没有理由再选用其他编码。
* `<meta name="viewport" content="width=device-width">`——视口元素可以确保页面以视口宽度进行渲染，避免移动端浏览器上因页面过宽导致缩放。
* `<title></title>`——`<title>` 元素。该元素设置页面的标题，显示在浏览器标签页上，也作为收藏网页的描述文字。
* `<body></body>`——`<body>` 元素。该元素包含期望让用户在访问页面时看到的*全部*内容，包括文本、图像、视频、游戏、可播放的音轨或其他内容。
图像
--

重温一下 `<img>` 元素：

```html

```

像之前所讲，该元素通过包含图像文件路径的地址属性 `src`，可在所在位置嵌入图像。

该元素还包括一个替换文字属性 `alt`，是图像的描述内容，用于当图像不能被用户看见时显示，不可见的原因可能是：

1. 用户有视觉障碍。视障用户可以使用屏幕阅读器来朗读 `alt` 属性的内容。
2. 有些错误使图像无法显示。可以试着故意将 `src` 属性里的路径改错。保存并刷新页面就可以在图像位置看到：

![图片内容为文字“测试图片”](/zh-CN/docs/Learn/Getting_started_with_the_web/HTML_basics/alt-text-example.png)

`alt` 属性的关键字即“描述文本”。`alt` 文本应向用户完整地传递图像要表达的意思。用 "测试图片" 来描述 Firefox 标志并不合适，修改成 "Firefox 标志：一只盘旋在地球上的火狐" 就好多了。

可以试着为图像编写一些更好的 `alt` 文本。

**备注：** 更多信息请参阅 无障碍访问。

标记文本
----

本段包含了一些最常用的文本标记 HTML 元素。

### 标题（Heading）

标题元素可用于指定内容的标题和子标题。就像一本书的书名、每章的大标题、小标题，等。HTML 文档也是一样。HTML 包括六个级别的标题， `<h1>` (en-US)–`<h6>` (en-US) ，一般最多用到 3-4 级标题。

```html

主标题

顶层标题

子标题

次子标题

```

可以尝试在 `<img>` 元素上面添加一个合适的标题。

**备注：** 你可以看到第一级标题是有隐式的主题样式。不要使用标题元素来加大、加粗字体，因为标题对于 无障碍访问 和 搜索引擎优化 等问题非常有意义。要保持页面结构清晰，标题整洁，不要发生标题级别跳跃。

### 段落（Paragraph）

如上文所讲，`<p>` 元素是用来指定段落的。通常用于指定常规的文本内容：

```html

这是一个段落

```

试着添加一些文本（在 设计网站的外观 小节）到一个或几个段落中，并把它们放在你的 `<img>` 元素下方。

### 列表（List）

Web 上的许多内容都是列表，HTML 有一些特别的列表元素。标记列表通常包括至少两个元素。最常用的列表类型为：

1. **无序列表**（Unordered List）中项目的顺序并不重要，就像购物列表。用一个 `<ul>` 元素包围。
2. **有序列表**（Ordered List）中项目的顺序很重要，就像烹调指南。用一个 `<ol>` 元素包围。

列表的每个项目用一个列表项目（List Item）元素 `<li>` 包围。

比如，要将下面的段落片段改成一个列表：

```html

  At Mozilla, we're a global community of technologists, thinkers, and builders
  working together…

```

可以这样更改标记：

```html

At Mozilla, we're a global community of

technologists

thinkers

builders

working together…

```

试着在示例页面中添加一个有序列表和无序列表。

链接
--

链接非常重要 — 它们赋予 Web 网络属性。要植入一个链接，我们需要使用一个简单的元素 — `<a>` — a 是 "anchor" （锚）的缩写。要将一些文本添加到链接中，只需如下几步：

1. 选择一些文本。比如“Mozilla Manifesto”。
2. 将文本包含在 `<a>` 元素内，就像这样：

```html
Mozilla Manifesto
```

3. 为此 `<a>` 元素添加一个 `href` 属性，就像这样：

```html
Mozilla Manifesto
```

4. 把属性的值设置为所需网址：

```html
Mozilla Manifesto
```

如果网址开始部分省略了 `https://` 或者 `http://`，可能会得到错误的结果。在完成一个链接后，可以试着点击它来确保指向正确。

**备注：** `href` 这个名字可能开始看起来有点令人费解，代表超文本引用（ **h**ypertext **ref**erence）。

现在就为页面添加一个链接吧。

小结
--

如果你一直跟着这篇文章里的指导做的话，你应该完成了一个像下面这样的页面（也可以查看这里）：

![](/zh-CN/docs/Learn/Getting_started_with_the_web/HTML_basics/finished-test-page-small.png)

如果你遇到困难，你可以将 Github 上的完整示例代码与你的文件进行比较。

在这里，我们只是介绍了一点点 HTML。要学习更多，访问我们的 HTML 学习主题页面 。

* 上一页
* Overview: Getting started with the web
* 下一页


设计网站外观 - 学习 Web 开发

设计网站外观
======

* 上一页
* Overview: Getting started with the web
* 下一页

本文将讲述在编写网站代码之前，需要进行什么样的规划和设计工作，包括“网站提供哪些信息？”、“用哪些字体和颜色？”、“网站是做什么的？”等。

第一步：计划
------

做任何事情之前，都要先有一些想法。你的网站到底是做什么的？一个网站基本上可以做任何事情，但对于第一个网站来说，最好简单一些。我们将从创建一个简单网页开始，它包含一个标题、一张图片和几个段落。

首先，请考虑以下问题：

1. **网站的主题是什么**？你喜欢狗、上海、还是吃豆人？
2. **基于所选主题要展示哪些信息**？写下标题和几段文字，再找个你想在网站上展示的图像。
3. 背景颜色用什么，或者，用高级一点的话来说，**你的网站外观是什么样的**？使用哪种字体比较合适：正式的、卡通的、粗体还是瘦体？

**备注：** 复杂的网站需要更详细的指引，深入到颜色、字体、页面上元素的间距、适当的书写风格等等以及其他细节。这有时被称为设计指南、设计系统或品牌手册，可以在 Firefox Photon 设计系统中找到一个示例。

绘制草图
----

接下来，拿起笔和纸，大致勾勒出你所希望的网站样子。当然，这个简单的网页不需要太复杂的草图，但你现在应该养成这样做的习惯。画草图很有用——并且不需要梵高的手法！

![画在纸上的一个粗略的网站草图](/zh-CN/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like/website-drawing-scan.png)

**备注：** 即使在实际的复杂网站中，设计团队通常也是从粗略的草图开始设计的，再使用图形编辑器或 Web 技术建立数字模拟图。

Web 团队通常包括一个平面设计师和一个用户体验（UX）设计师。平面设计师把网站的视觉效果放在一起。用户体验设计师则以一种更抽象的模式来解决用户如何体验及与网站交互方面的问题。

选定素材
----

此时，就可以开始组织网页上的内容了。

### 文本

准备好刚才撰写的标题和文字。把这些东西放到旁边。

### 主题颜色

使用色彩选择器挑选心仪的颜色。当选中某种颜色时，会显示一个六位神秘代码，类似于 `#660066`。它是一个*十六进制数*，用于表示颜色。将其复制并暂存。

![MDN 网站上的颜色选择器，包含 RGB、HSL、HEX 格式](/zh-CN/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like/color-picker.png)

### 图像

访问 Google 图片搜索 来搜索合适的图片。

1. 当找到你想要的图像时，点击该图像以获得其放大的视图。
2. 右键单击图像（Mac 上为 Ctrl + 单击），选择*将图像另存为...*，并选择一个可靠的位置来保存你的图像。或者，从浏览器地址栏中复制图片的网址，以便以后使用。

![Google 图片搜索中的搜索结果](/zh-CN/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like/updated-google-images.png)

请注意，网络上的大多数图片，包括谷歌图像中的图片，都是有版权的。为了减少侵权的可能性，可以使用谷歌的许可证过滤器。点击*工具*按钮，然后点击下面出现的*使用权限*选项。你应该选择*知识共享许可*这个选项。

![经知识共享许可过滤后的 Google 图片搜索结果](/zh-CN/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like/updated-google-images-licensing.png)

### 字体

和图片一样，很多字体都受版权保护，也就是说，你不可以在你的网站上随意使用它们。Google Fonts 是 Google 旗下的网络服务，提供了许多字体许可。

选好字体后，你有两种方式使用它：

1. 在你的代码中添加一个引用，从 Google 服务器加载这个字体。
2. 下载字体文件到你的系统内，自行挂载这个文件，并在你网站的代码中使用。

**备注：** 在你的网站使用从 Google 服务器加载的字体可能会违反欧盟的数据隐私规定 GDPR，因为加载字体时会暴露用户的 IP 地址。如果你遇到这种潜在风险，需要选择第二种方式。

另一个选择是使用 安全 Web 字体，如 Arial、Times New Roman、Courier New。

* 上一页
* Overview: Getting started with the web
* 下一页


JavaScript 基础 - 学习 Web 开发

JavaScript 基础
=============

* 上一页
* Overview: Getting started with the web
* 下一页

JavaScript 是一门编程语言，可为网站添加交互功能（例如：游戏、动态样式、动画以及在按下按钮或收到表单数据时做出的响应等）。本文介绍了 JavaScript 的精彩之处和主要用途。

JavaScript 到底是什么？
-----------------

JavaScript（缩写：JS）是一门完备的动态编程语言。当应用于 HTML 文档时，可为网站提供动态交互特性。由布兰登·艾克（Brendan Eich，Mozilla 项目、Mozilla 基金会和 Mozilla 公司的联合创始人）发明。

JavaScript 的应用场合极其广泛，简单到幻灯片、照片库、浮动布局和响应按钮点击，复杂到游戏、2D/3D 动画、大型数据库驱动程序等等。

JavaScript 相当简洁，却非常灵活。开发者们基于 JavaScript 核心编写了大量实用工具，可以使 开发工作事半功倍。其中包括：

* 浏览器应用程序接口（API）——浏览器内置的 API 提供了丰富的功能，比如：动态创建 HTML 和设置 CSS 样式、从用户的摄像头采集处理视频流、生成 3D 图像与音频样本等等。
* 第三方 API——让开发者可以在自己的站点中整合其他内容提供者（Twitter、Facebook 等）提供的功能。
* 第三方框架和库——用来快速构建网站和应用。

本节是一篇 JavaScript 简介，因此这个阶段不会对 JavaScript 语言和上述工具做过多的介绍。之后可以到 JavaScript 学习区 和 MDN 的其他地方学习更多细节。

下面对语言核心做一个不完整介绍，期间还可以接触到一些浏览器 API 特性。

“Hello World!”示例
----------------

读到这里你一定很激动，诚然——JavaScript 是最振奋人心的 Web 技术之一，而且在娴熟驾驭之后，你的网站在功能和创新力上将达到一个新的维度。

然而，JavaScript 比 HTML 和 CSS 学习起来更加复杂一点，所以必须一步一个脚印地学习。首先，来看看如何在页面中添加一些基本的 JavaScript 脚本来建造一个“Hello world!”示例（一切始于 Hello World）。

**警告：** 如果你没有完成之前的课程实践，可下载 上一章节示例的压缩包 并在本地解压作出发点。

1. 首先，打开你的测试站点，创建一个名为 `scripts` 的文件夹。然后在其中创建一个名为 main.js 的文件。
2. 下一步，在 `index.html` 文件</body> 标签前的新行添加以下代码。

```html
<script src="scripts/main.js" defer></script>
```

3. 与 CSS 的 `<link>` 元素类似，它将 JavaScript 引入页面以作用于 HTML（以及 CSS 等页面上所有内容）：
4. 现在将以下代码添加到 `main.js` 文件中：

```js
let myHeading = document.querySelector("h1");
myHeading.textContent = "Hello world!";
```

5. 最后，保存 HTML 和 JavaScript 文件，用浏览器打开 `index.html`。可以看到如下内容：
 ![](/zh-CN/docs/Learn/Getting_started_with_the_web/JavaScript_basics/hello-world.png)

**备注：** 我们将 `<script>` 放在 HTML 文件的底部附近的原因是浏览器会按照代码在文件中的顺序加载 HTML。如果先加载的 JavaScript 期望修改其下方的 HTML，那么它可能由于 HTML 尚未被加载而失效。因此，将 JavaScript 代码放在 HTML 页面的底部附近通常是最好的策略。

### 发生了什么？

JavaScript 把页面的标题改成了“Hello world!” 。首先用 `querySelector()` 函数获取标题的引用，并把它储存在 `myHeading` 变量中。这与 CSS 选择器的用法非常相像：若要对某个元素进行操作，首先得选择它。

之后，把 `myHeading` 变量的属性 `textContent` （标题内容）修改为“Hello world!” 。

**备注：** 上面用到的两个函数都来自 文档对象模型 (DOM) API，均用于控制文档。

JavaScript 快速入门
---------------

我们来学习一些 JavaScript 的核心特性，从而更好地理解它的运行机制。学习这些知识很有意义，因为这些原理普遍适用于所有编程语言，掌握好它们，可以做到融会贯通。

**警告：** 学习本节时，请尝试将示例代码输入到 JavaScript 控制台里看看会发生什么。JavaScript 控制台的更多信息请查看 浏览器开发者工具。

### 变量（Variable）

变量 是存储值的容器。要声明一个变量，先输入关键字 `let` 或 `var`，然后输入合适的名称：

```js
let myVariable;
```

**备注：** 行末的分号表示当前语句结束，不过只有在单行内需要分割多条语句时，这个分号才是必须的。然而，一些人认为每条语句末尾加分号是一种好的风格。分号使用规则的更多细节请参阅 JavaScript 分号使用指南（英文页面）。

**备注：** 几乎任何内容都可以作为变量名，但还是有一些限制（请参阅 变量命名规则）。如果你不确定，还可以 验证变量名 是否有效。

**备注：** JavaScript 对大小写敏感，`myVariable` 和 `myvariable` 是不同的。如果代码出现问题了，先检查一下大小写！

**备注：** 想要了解更多关于 `var` 和 `let` 的不同点，可以参阅 var 与 let 的区别。

变量定义后可以进行赋值：

```js
myVariable = "李雷";
```

也可以将定义、赋值操作写在同一行：

```js
let myVariable = "李雷";
```

可以直接通过变量名取得变量的值：

```js
myVariable;
```

变量在赋值后是可以更改的：
```

let myVariable = '李雷';
myVariable = '韩梅梅';
```

注意变量可以有不同的 数据类型 ：

| 变量 | 解释 | 示例 |
| --- | --- | --- |
| String | 字符串（一串文本）：字符串的值必须用引号（单双均可，必须成对）括起来。 | `let myVariable = '李雷';` |
| Number | 数字：无需引号。 | `let myVariable = 10;` |
| Boolean |
 布尔值（真 / 假）： `true`/`false` 是 JS
 里的特殊关键字，无需引号。
  | `let myVariable = true;` |
| Array | 数组：用于在单一引用中存储多个值的结构。 | `let myVariable = [1, '李雷', '韩梅梅', 10];`元素引用方法：`myVariable[0]`,
 `myVariable[1]` ……
  |
| Object | 对象：JavaScript 里一切皆对象，一切皆可储存在变量里。这一点要牢记于心。 | `let myVariable = document.querySelector('h1');`以及上面所有示例都是对象。 |

那么变量有什么用呢？我们说，编程时它们无所不在。如果值无法改变，那么就无法做任何动态的工作，比如发送个性化的问候，或是改变在图片库当前展示的图片。

### 注释

类似于 CSS，JavaScript 中可以添加注释。

```js
/\*
这里的所有内容
都是注释。
\*/
```

如果注释只有一行，可以更简单地将注释放在两个斜杠之后，就像这样：

```js
// 这是一条注释。
```

### 运算符

运算符 是一类数学符号，可以根据两个值（或变量）产生结果。以下表格中介绍了一些最简单的运算符，可以在浏览器控制台里尝试一下后面的示例。

**备注：** 这里说“根据**两个**值（或变量）产生结果”是不严谨的，计算两个变量的运算符称为“二元运算符”，还有一元运算符和三元运算符，下表中的“取非”就是一元运算符。

| 运算符 | 解释 | 符号 | 示例 |
| --- | --- | --- | --- |
| 加 | 将两个数字相加，或拼接两个字符串。 | `+` | `6 + 9;"Hello " + "world!";` |
| 减、乘、除 | 这些运算符操作与基础算术一致。只是乘法写作星号，除法写作斜杠。 | `-`, `*`, `/` | `9 - 3;8 * 2; //乘法在 JS 中是一个星号9 / 3;` |
| 赋值运算符 | 为变量赋值（你之前已经见过这个符号了） | `=` | `let myVariable = '李雷';` |
| 等于 |
 测试两个值是否相等，并返回一个 `true`/`false`
 （布尔）值。
  | `===` | `let myVariable = 3;myVariable === 4; // false` |
| 不等于 |
 和等于运算符相反，测试两个值是否不相等，并返回一个
 `true`/`false` （布尔）值。
  | `!==` | ``let myVariable = 3;`myVariable !== 3; //
false` |
| 取非 | 返回逻辑相反的值，比如当前值为真，则返回 `false`。 | `!` | 原式为真，但经取非后值为 `false`：`let myVariable = 3;!(myVariable === 3); // false` |

运算符种类远不止这些，不过目前上表已经够用了。完整列表请参阅 表达式和运算符。

**备注：** 不同类型数据之间的计算可能出现奇怪的结果，因此必须正确引用变量，才能得出预期结果。比如在控制台输入 `"35" + "25"`，为什么不能得到 `60`？因为引号将数字转换成了字符串，所以结果是连接两个字符串而不是把两个数字相加。输入 `35 + 25` 才能得到正确结果。

### 条件语句

条件语句是一种代码结构，用来测试表达式的真假，并根据测试结果运行不同的代码。一个常用的条件语句是 `if ... else`。下面是一个示例：

```js
let iceCream = "chocolate";
if (iceCream === "chocolate") {
  alert("我最喜欢巧克力冰淇淋了。");
} else {
  alert("但是巧克力才是我的最爱呀……");
}
```

`if ( ... )` 中的表达式进行测试，用（上文所提到的）等于运算符来比较变量 `iceCream` 与字符串 `'chocolate'` 是否相等。如果返回 `true`，则运行第一个代码块；如果返回 `false`，则跳过第一块直接运行 `else` 之后的第二个代码块。

### 函数（Function）

函数 用来封装可复用的功能。如果没有函数，一段特定的操作过程用几次就要重复写几次，而使用函数则只需写下函数名和一些简短的信息。之前已经涉及过一些函数，比如：

```js
let myVariable = document.querySelector("h1");
```

```js
alert("hello!");
```

`document.querySelector` 和 `alert` 是浏览器内置的函数，随时可用。

如果代码中有一个类似变量名后加小括号 `()` 的东西，很可能就是一个函数。函数通常包括参数，参数中保存着一些必要的数据。它们位于括号内部，多个参数之间用逗号分开。

比如， `alert()` 函数在浏览器窗口内弹出一个警告框，还应为其提供一个字符串参数，以告诉它警告框里要显示的内容。

好消息是：人人都能定义自己的函数。下面的示例是为两个参数进行乘法运算的函数：

```js
function multiply(num1, num2) {
  let result = num1 \* num2;
  return result;
}
```

尝试在控制台运行这个函数，不妨多试几组参数，比如：

```js
multiply(4, 7);
multiply(20, 20);
multiply(0.5, 3);
```

**备注：** `return` 语句告诉浏览器当前函数返回 `result` 变量。这是一点很有必要，因为函数内定义的变量只能在函数内使用。这叫做变量的 作用域。（详见 变量作用域。）

### 事件

事件能为网页添加真实的交互能力。它可以捕捉浏览器操作并运行一些代码做为响应。最简单的事件是点击事件，鼠标的点击操作会触发该事件。可尝试将下面的代码输入到控制台，然后点击页面的任意位置：

```js
document.querySelector("html").addEventListener("click", function () {
  alert("别戳我，我怕疼。");
});
```

将事件与元素绑定有许多方法。在这里选用了 `<html>` 元素，然后调用了它的 `addEventListener()` 方法，将事件名称（`'click'`）以及其回调函数（当事件发生时，调用该函数）传入该函数中作为调用参数。

刚刚我们传递给 `addEventListener()` 的函数被称为*匿名函数*，因为它没有名字。匿名函数还有另一种我们称之为*箭头函数*的写法，箭头函数使用 `() =>` 代替 `function ()`：

```js
document.querySelector("html").addEventListener("click", () => {
  alert("别戳我，我怕疼。");
});
```

完善示例网页
------

现在你已经具备了一些 JavaScript 基础，下面来为示例网页添加一些更酷的特性。

### 添加一个图像切换器

这里将用新的 DOM API 为网页添加另一张图片，并用 JavaScript 使图片在点击时进行切换。

1. 首先，找到另一张你想要在你的页面上展示的图片，且尺寸与第一张图片尽可能相同。
2. 将这张图片储存在你的`images`目录下。
3. 将图片重命名为'firefox2.png'（去掉引号）。
4. 打开 `main.js` 文件，输入下面的 JavaScript 代码 ( 请删除刚才的 "hello world" 脚本)：

```js
let myImage = document.querySelector("img");

myImage.onclick = function () {
  let mySrc = myImage.getAttribute("src");
  if (mySrc === "images/firefox-icon.png") {
    myImage.setAttribute("src", "images/firefox2.png");
  } else {
    myImage.setAttribute("src", "images/firefox-icon.png");
  }
};
```

5. 保存所有文件并用浏览器打开 `index.html` 。点击图片可以发现它能够切换了！

这里首先把 `<img>` 元素的引用存放在 `myImage` 变量里。然后将这个变量的 `onclick` 事件与一个匿名函数绑定。每次点击图片时：

1. 获取这张图片的 `src` 属性值。
2. 用一个条件句来判断 `src` 的值是否等于原始图像的路径：
    1. 如果是，则将 `src` 的值改为第二张图片的路径，并在 `<img>` 内加载该图片。
    2. 如果不是（意味着它已经修改过）, 则把 `src` 的值重新设置为原始图片的路径，即原始状态。
### 添加个性化欢迎信息

下面来添加另一段代码，在用户初次进入站点时将网页的标题改成一段个性化欢迎信息（即在标题中添加用户的名字）。名字信息会由 Web Storage API 保存下来，即使用户关闭页面之后再重新打开，仍可得到之前的信息。还会添加一个选项，可以根据需要改变用户名字以更新欢迎信息。

1. 打开 `index.html`，在 `<script>` 标签**前**添加以下代码，将在页面底部显示一个“切换用户”字样的按钮：

```html
<button>切换用户</button>
```

2. 将以下 JavaScript 代码原封不动添加到 `main.js` 文件底部，将获取新按钮和标题的引用，并保存至变量中：

```js
let myButton = document.querySelector("button");
let myHeading = document.querySelector("h1");
```

3. 然后添加以下函数来设置个性化欢迎信息。（函数需要在调用后生效，下文中提供了两种对该函数的调用方式）

```js
function setUserName() {
  let myName = prompt("请输入你的名字。");
  localStorage.setItem("name", myName);
  myHeading.textContent = "Mozilla 酷毙了，" + myName;
}
```

该函数首先调用了 `prompt()` 函数，与 `alert()` 类似会弹出一个对话框。但是这里需要用户输入数据，并在确定后将数据存储在 `myName` 变量里。接下来将调用 `localStorage` API，它可以将数据存储在浏览器中供后续获取。这里用 `localStorage` 的 `setItem()` 函数来创建一个`'name'` 数据项，并把 `myName` 变量复制给它。最后将 `textContent` 属性设置为一个欢迎字符串加上这个新设置的名字。
4. 接下来，添加以下的 `if ... else` 块。我们可以称之为初始化代码，因为它在页面初次读取时进行构造工作：

```js
if (!localStorage.getItem("name")) {
  setUserName();
} else {
  let storedName = localStorage.getItem("name");
  myHeading.textContent = "Mozilla 酷毙了，" + storedName;
}
```

这里首次使用了取非运算符（逻辑非，用 `!` 表示）来检测 `'name'` 数据是否存在。若不存在，调用 `setUserName()` 创建。若存在（即用户上次访问时设置过），调用 `getItem()` 获取保存的名字，像上文的 `setUserName()` 那样设置 `textContent`。
5. 最后，为按钮设置 onclick 事件处理器。按钮按下时运行 setUserName() 函数。这样用户就可以通过按这个按钮来自由设置新名字了：

```js
myButton.onclick = function () {
  setUserName();
};
```

第一次访问网页时，页面将询问用户名并发出一段个性化的信息。可随时点击按钮来改变用户名。告诉你一个额外的福利，因为用户名是保存在 `localStorage` 里的，网页关闭后也不会丢失，所以重新打开浏览器时所设置的名字信息将依然存在:)

### 用户名为 null?

运行示例代码，弹出输入用户名的对话框，试着按下 `取消` 按钮。此时标题会显示为“Mozilla 酷毙了，null”。这是因为取消提示对话框后值将设置为 `null`，这是 JavaScript 中的一个特殊值，表示引用不存在。

也可以不输入任何名字直接按 `确认`，你的标题会显示为“Mozilla 酷毙了，”，原因么显而易见。

要避免这些问题，应该更新 `setUserName()` 来检查用户是否输入了 `null` 或者空名字：

```js
function setUserName() {
  let myName = prompt("请输入你的名字。");
  if (!myName) {
    setUserName();
  } else {
    localStorage.setItem("name", myName);
    myHeading.textContent = "Mozilla 酷毙了，" + myName;
  }
}
```

用人话说就是：如果 `myName` 没有值或值为 `null`，就再次从头运行`setUserName()`。如果有值（上面的表达式结果不为真），就把值存储到 `localStorage` 并且设置标题。

小结
--

如果你按部就班完成本文的实践，那么最终可以得到以下页面（可以 查看我们的版本）：

![测试页面，添加了 一个 js 脚本，可以显示用户名、更改 Firefox 图片。](/zh-CN/docs/Learn/Getting_started_with_the_web/JavaScript_basics/beginner-site-scripted.png)

若遇到问题，可以参考 GitHub 上的 完整示例代码 进行对比。

本章介绍的 JavaScript 知识非常有限，更多内容请访问 Javascript 学习页面。

* 上一页
* Overview: Getting started with the web
* 下一页


安装基础软件 - 学习 Web 开发

安装基础软件
======

* Overview: Getting started with the web
* 下一页

在*安装基础软件*中，我们向你展示了进行简单的 Web 开发需要哪些工具，以及如何正确安装它们。

专业人士使用什么工具？
-----------

* **计算机**。也许这对一些人来说听起来习以为常，但你们中的一些人正在使用手机或图书馆的电脑阅读这篇文章。对于重度的 Web 开发，最好购买一台运行 Windows、macOS 或 Linux 的台式机或笔记本电脑。
* **文本编辑器**，用来写代码。可以是一个文本编辑器（如 Visual Studio Code、Sublime Text、Atom 、GNU Emacs 或者 VIM ），或一个混合编辑器（ Dreamweaver 或 WebStorm）。Office 文档不适合这种用途，因为它们依赖隐藏的元素，会干扰网络浏览器使用的渲染引擎。
* **网络浏览器**，用以测试代码。目前，最常用的浏览器是 Firefox 、Chrome、Opera、Safari、Internet Explorer 和 Microsoft Edge。你还应该测试你的网站在移动设备和你的目标受众可能仍在使用的任何旧浏览器（如 IE 8-10）上的表现。Lynx，一个基于文本的终端网络浏览器，对于查看视力障碍用户对你的网站的体验是非常好的。
* **图形编辑器**，如 GIMP 、Figma 、Paint.NET 、Photoshop 、Sketch 或 XD ，为你的网页制作图像或图形。
* **版本控制系统**，用来管理服务器上的文件，与团队合作开展项目，共享代码和资产，避免编辑冲突。现在，Git 是最流行的版本控制系统，还有 GitHub 或 GitLab 托管服务。
* **FTP 工具**，老式 Web 托管账户，以管理服务器上的文件（Git 正越来越多地取代 FTP 用于此目的）。有大量的 (S)FTP 程序可用，包括 Cyberduck、Fetch 和 FileZilla。
* **自动化构建工具**，如 Webpack 、Grunt 或 Gulp ，以自动执行重复性任务，如简化代码和运行测试。
* 库、框架等，以加快编写常用功能。一个库往往是一个现有的 JavaScript 或 CSS 文件，它提供了现成的功能，供你在代码中使用。框架则更进一步，为你提供一个完整的系统和一些自定义的语法，让你在上面写一个 Web 应用。
* 此外还有更多的工具！
现在，我究竟需要什么工具？
-------------

这看起来是一个冗长的清单，但幸运的是，你可以在不了解这些东西的情况下开始进行 Web 开发。在这篇文章中，我们只为你准备了最基本的东西——一个文本编辑器和一些现代网络浏览器。

### 安装文本编辑器

你的电脑上可能已经有一个基本的文本编辑器。默认情况下，Windows 是 Notepad ，macOS 则有 TextEdit。Linux 发行版有所不同；Ubuntu 下是 gedit 。

对于 Web 开发，你可能可以做得比记事本或 TextEdit 更好。我们建议从 Visual Studio Code 开始，它是一个免费的编辑器，提供实时预览和代码提示。

### 安装现代网络浏览器

现在，我们将安装几个桌面网络浏览器来测试我们的代码。在下面选择你的操作系统，然后点击相关链接，下载你喜欢的浏览器：

* Linux：Firefox 、Chrome 、Opera 、Brave.
* Windows：Firefox 、Chrome 、Opera 、Internet Explorer 、Microsoft Edge 、Brave （Windows 10 默认带有 Edge；如果你有 Windows 7 或以上版本，你可以安装 Internet Explorer 11；否则，你应该安装一个替代浏览器）。
* macOS：Firefox 、Chrome 、Opera 、Safari 、Brave （macOS 和 iOS 默认带有 Safari 浏览器）。

在继续之前，你应该至少安装两款这样的浏览器，并准备好进行测试。

**备注：** Internet Explorer 与一些现代网络功能不兼容，它可能无法运行你的项目。你通常不需要为你的 Web 项目与它兼容而操心，因为很少还有人在使用它——至少在你学习的时候不要太担心它。你可能会在以后遇到一个需要支持它的项目。

### 安装本地 Web 服务器

有些例子需要通过 Web 服务器才能成功运行。你可以在这找到该怎么做如何设置本地测试服务器？

* Overview: Getting started with the web
* 下一页


发布网站 - 学习 Web 开发

发布网站
====

* 上一页
* Overview: Getting started with the web
* 下一页

在你已经写好了代码并且整理好了你网站的全部文件后，你需要将它们全部上线，这样别人才能看到。这篇文章将向你展示如何轻松地将你简单的示例代码传到网上。

有哪些方法可供选择？
----------

发布一个网页并不是三言两语就能简单说明的，这主要是因为我们有很多种方法去完成它。在这篇文章里我们并不准备讲述所有方法，而是从初学者的视角讨论以下三种常见的方式的利弊，然后带你看看我们将要使用的一种方法。

### 获取主机服务和域名

如果你想要完全控制你发布的网页，那么你将需要花钱购置：

* 主机服务——在主机服务提供商的 Web 服务器上租用文件空间。将你网站的文件上传到这里，然后服务器会提供 Web 用户需求的内容。
* 域名——一个可以让人们访问的独一无二的地址，比如 `http://www.mozilla.org` 或 `http://www.bbc.co.uk`。你可以从**域名注册商**租借域名。

许多专业的网站通过这种方法接入互联网。

此外，你将需要一个 文件传输协议 程序 ( 点击钻研在网络上做某些事情要花费多少：软件查看详细信息 ) 来将网站文件上传到服务器。不同的 FTP 程序涵盖了不同的范围，但是你通常需要使用主机服务提供商给你的详细信息（比如用户名、密码、主机名）登录到 Web 服务器。然后程序在两个窗口里分别显示本地文件和服务器文件，这样你就可以在它们之间进行传输：

![](/zh-CN/docs/Learn/Getting_started_with_the_web/Publishing_your_website/ftp.jpg)

#### 寻找主机服务和域名的建议

* 我们不会推荐任何商业化的主机公司。要找到主机公司和域名注册商，只需要搜索 "网络主机服务" 和 "域名" 来找到一家出售域名的公司。所有这种类型的公司都允许你查看你想要的域名是否可用。
* 你的家庭或办公 网络服务提供商 可能会提供一些受限制的的小型主机空间。它们的能使用的功能都会受到限制，但是它们会非常适合你的第一个实验的——联系一下他们！
* 有一些免费服务比如 Neocities ， Blogspot ，和 Wordpress 。重复一遍，一分钱一分货，不过它们对于你的初次实验可能会是很理想的。免费服务大部分也不需要 FTP 软件来上传文件——你只需要将文件拖入到它们网页的界面里。
* 有时公司会打包提供主机服务和域名。
### 使用在线工具如 GitHub 或 Google App Engine

有一些工具能使你在线发布网站 :

* GitHub 是一个“社交编程”网站。它允许你上传代码库并储存在 Git 版本控制系统里。然后你可以协作代码项目，系统是默认开源的，也就是说世界上任何人都可以找到你 GitHub 上的代码。去使用 GitHub，从中学习并且提高自己吧！你也可以对别人的代码那样做！这是一个非常重要、有用的社区，而且 Git/GitHub 是非常流行的 版本控制系统 — 大部分科技公司在工作中使用它。GitHub 有一个非常有用的特点叫 GitHub pages，允许你将网站代码放在网上。
* Google App Engine 是一个让你可以在 Google 的基础架构上构建和运行应用的强劲平台——无论你是需要从头开始构建多级 web 应用还是托管一个静态网站。参阅How do you host your website on Google App Engine?以获取更多信息。

不同于大部分其他托管服务，这类工具通常是免费的，不过你只能使用有限的功能。

### 使用像 CodePen 这样基于 Web 的集成开发环境

有许多 web 应用能够仿真一个网站开发环境。你可以在这种应用——通常只有一个标签页——里输入 HTML、CSS 和 JavaScript 代码然后像显示网页一样显示代码的结果。通常这些工具都很简单，对学习很有帮助，而且至少有免费的基本功能，它们在一个独特的网址显示你提交的网页。不过，这些应用的基础功能很有限，而且应用通常不提供空间来存储图像等内容。

使用一下以下几种工具，看看你最喜欢哪一个：

* JSFiddle
* Glitch
* JSBin
* CodePen

![](/zh-CN/docs/Learn/Getting_started_with_the_web/Publishing_your_website/jsbin-screen.png)

通过 GitHub 发布
------------

现在，让我们通过 Github 页面告诉你公布的你的代码是如此的简单。

1. 首先， 注册一个 GitHub 账号， 并确认你的邮箱地址。
2. 接下来，你需要创建一个新的资源库 ( repository ) 来存放你的文件。
3. 在这个页面上，在 *Repository name* 输入框里输入 *username*.github.io，username 是你的用户名。比如，我们的朋友 bobsmith 会输入 *bobsmith.github.io。同时勾选* *Initialize this repository with a README*，然后点击 *Create repository*。
 ![](/zh-CN/docs/Learn/Getting_started_with_the_web/Publishing_your_website/github-create-repo.png)
4. 然后，将你的网站文件夹里的内容拖拽到你的资源库 ( repository )，再点击 *Commit changes*。

**备注：** 确保你的文件夹有一个 *index.html* 文件。
5. 现在将你的浏览器转到 *username*.github.io 来在线查看你的网站。比如，*如果用户名为 chrisdavidmills*, 请转到 chrisdavidmills.github.io。

**备注：** 你的网站可能需要几分钟的时间才能投入使用。如果它不能立即工作，你可能需要等待几分钟，然后再试一次。

想要了解更多，请看 GitHub Pages Help.

延展阅读
----

* 什么是网络服务器？
* 什么是域名？
* 钻研在网络上做某些事情要花费多少？
* Deploy a Website（英文）：来自 Codeacademy 的一个很好的教程，它比本教程更进一步，并展示了一些其他技术。
* Scott Murray 的 Cheap or free static web hosting （价格低廉或免费的静态 Web 主机服务）包含一些对可用的 Web 主机服务的建议。
* 上一页
* Overview: Getting started with the web
* 下一页


Web 和 Web 标准 - 学习 Web 开发

Web 和 Web 标准
============

这篇文章提供了一些有用的 Web 背景知识——它是如何产生的，什么是 Web 标准技术，它们是如何协同工作的，为什么“Web 开发人员”是一个很好的职业选择，以及你将在本课程中学习哪些最佳做法。

Web 简史
------

我们会简单叙述，因为别处已有很多关于 Web 历史的详尽说明，稍后我们会链接到它们（如果那你对更多细节内容感兴趣，也请试着在你惯用的搜索引擎中搜索“Web 的历史”以获取相关内容。）

在 20 世纪 60 年代末期，美国军方开发了一个名为 ARPANET 的通信网络。这可以认为是 Web 的先驱，因为它基于 分组交换（packet switching） 进行工作，并且首次实现了 TCP/IP 协议族（TCP/IP protocol suite） 。这两种技术构成了互联网基础设施的基础。

1980 年，Tim Berners-Lee（通常称之为 TimBL）写了一个叫 ENQUIRE 的笔记本程序，这个程序实现了不同节点之间链接的概念。听起来有点熟悉对吧？

快进到 1989 年，TimBL 在 CERN 撰写了 《Information Management: A Proposal》 和《HyperText》 ；这两个出版物共同为 Web 将如何工作做了铺垫。两个出版物获得了极大的关注，这足以说服 TimBL 的上司让他继续前进，并创建一个全球超文本系统。

到 1990 年底，TimBL 已经创建了运行第一个版本的 Web 所需的所有东西——HTTP、HTML、名为 WorldWideWeb 的第一个 Web 浏览器、一个 HTTP 服务器和一些用于查看的网页。

在随后的几年中，随着多个浏览器的发布，数以千计 Web 服务器的建立，上百万网页的生成，Web 爆发式发展。OK，这只是对事件非常粗略的描述，但我向你说过会简单叙述。

最后一个值得分享的重要事件在 1994 年，TimBL 建立了万维网联盟（World Wide Web Consortium，W3C），该组织汇集了来自许多不同技术公司的代表，共同制定 Web 技术规范。随后其他的技术像 CSS 和 JavaScript 出现了，Web 开始看起来更像我们现在所了解的 Web。

Web 标准
------

**Web 标准**是我们用来建立 Web 网站的技术。这些标准存在于名为规范的较长的技术文档中，该文档详细说明了技术应如何工作。这些文档对于学习如何使用它们所描述的技术并不是很有用（这就是我们建立像 MDN Web Docs 这样的网站的原因），而是旨在供软件工程师用来实现这些技术（通常在 Web 浏览器中）。

例如，HTML Living Standard 描述了应如何实现 HTML（所有 HTML 元素及其关联的 API 和其他相关技术）。

Web 标准是由标准机构创建的——这些机构邀请不同技术公司的人员聚集在一起，并就如何以最佳方式实现所有用例达成共识。W3C 是最著名的 Web 标准组织，但还有其他组织，例如WHATWG（负责 HTML 语言的现代化），ECMA（发布基于 JavaScript 的 ECMAScript 标准），Khronos（发布 3D 图形技术，例如 Web GL）等。

### “开放”标准

Web 标准的关键方面之一，TimBL 和 W3C 从一开始就认同的一点，Web（和 Web 技术）应该自由地贡献和使用，并且不受专利/许可的约束。因此，任何人都可以编写代码免费建立网站，并且任何人都可以为编写规范的标准创建过程做出贡献。

由于 Web 技术是开放的，因此在许多不同公司之间的协作中，这意味着没有一家公司可以控制它，这确实是一件好事。你不会希望任何一家公司突然决定将整个 Web 置于付费壁垒之后，或者发布每个人都必须购买以继续制作网站的新版 HTML，或者更糟糕的是，仅仅将他们不再感兴趣的网站关闭。

这一点允许 Web 保持免费可用，使其成为公共资源。

### 不要破坏 Web

关于开放式 Web 标准，你将听到的另一句话是“不要破坏 Web”——这句话是说，引入的任何新 Web 技术都应向后兼容以前的版本（即旧网站仍将继续工作），并向前兼容（将未来的技术与我们目前拥有的技术兼容）。在阅读此处介绍的学习材料时，你将开始学习如何通过一些非常精妙的设计和做法来实现这一点。

Web 开发者是一个很好的选择
---------------

如果你正在寻找工作，网络行业是一个非常有吸引力的市场。最新公布的数据表明，目前全球大约有 1900 万网络开发人员，并且这个数字在接下来的十年中将增长两倍以上。同时，该行业存在技能短缺的问题，那么还有什么更好的时间来学习 Web 开发呢？

然而，这并不仅仅是娱乐或者游戏——建立网站比以前要复杂得多，并且你必须花一些时间来研究要用到的所有不同的技术，所有你需要了解的技巧和最佳的技术做法，以及所有需要实现的典型模式。真正起步需要花几个月的时间，然后你需要继续学习，继续练习和完善自己的技术，以使你的知识与 Web 平台上出现的所有新工具和功能步调一致。

*唯一不变的就是变化。*

这听起来很难？不用担心——我们致力于为你提供入门所需的一切，事情将会变得更加轻松。一旦你适应了网络的不断变化和不确定性，你将开始享受乐趣。作为 Web 社区的一员，你将拥有整个 Web 的联系人和有用的资料来帮助你，并且你将开始享受它所带来的创造的可能性。

你现在是数字创意家了。享受这种体验和谋生的可能性吧。

现代网络技术概述
--------

如果你想成为前端 Web 开发人员，可以学习多种技术。在本节中，我们将简要描述它们。有关其中某些功能是如何协同工作的详尽说明，请阅读我们的文章 Web 是如何工作的。

### 浏览器

你可能此刻正在 Web 浏览器中阅读这些文字（除非你已将其打印出来，或正在使用辅助技术，例如屏幕阅读器将其读给你听）。Web 浏览器是人们用来浏览 Web 的软件程序，包括 Firefox、Chrome、Opera、Safari 和 Edge.

### HTTP

超文本传输协议（Hypertext Transfer Protocol，HTTP），它允许 Web 浏览器与 Web 服务器（存储网站的位置）进行通信。典型的通信就像这样
```

"你好 Web 服务器。你可以给我用于渲染 bbc.co.uk 的文件吗？"

"当然啦 Web 浏览器——给你"

[下载文件并渲染 Web 页面]
```

HTTP 消息（称为请求和响应）的实际语法不是人类可读的，但这个例子为你提供了基本概念。

### HTML , CSS , 和 JavaScript

HTML，CSS，和 JavaScript 是你用来建立网站的三种主要技术：

* 超文本标记语言（HTML）是一种标记语言，由可以包装（标记）内容以赋予其含义（语义）和结构的各种元素组成。简单的 HTML 看起来像这样：

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

<p>这是一个文本段落</p>

<img src="cat.jpg" alt="我家猫猫的图片" />
```

如果我们采用房屋建筑类比的话，HTML 就像房屋的地基和墙壁一样，赋予房屋结构并将其结合在一起。
* 级联样式表（Cascading Style Sheets，CSS）是一种基于规则的语言，用于将样式应用于 HTML，例如，设置文本和背景颜色，添加边框，设置动画效果或以某种方式布置页面。作为一个简单的示例，以下代码会将我们的 HTML 段落变为红色：

```css
p {
  color: red;
}
```

在房屋类比中，CSS 就像用来使房屋看起来更漂亮的油漆，墙纸，地毯和油画。
* 从动态样式切换到从服务器获取更新，再到复杂的 3D 图形， **JavaScript** 是我们用来向网站添加交互性的编程语言。以下简单的 JavaScript 将在内存中存储对我们段落的引用，并更改其中的文本：

```js
let pElem = document.querySelector("p");
pElem.textContent = "我们改变了文本！";
```

在房屋类比中，JavaScript 就像炊具，电视，微波炉或吹风机，这些东西为你的房屋提供了有用的功能。
### 开发工具

一旦了解了可用于构建网页的“原始”技术（例如 HTML，CSS 和 JavaScript），你很快就会发现各种可用于使工作更轻松或更有效的工具。例如：

* 现代浏览器中的 开发人员工具（developer tools）可用于调试代码。
* 可用于运行测试以显示你的代码是否按预期运行的 测试工具（Testing tools）。
* 建立在 JavaScript 之上的库和框架，使你可以更快，更有效地构建某些类型的网站。
* 所谓的“Linters” ，它包含了一组规则，检查你的代码之后，会突出显示你未正确遵循规则的地方。
* Minifiers，它将代码文件中的所有空格删除以使其更小，从而可以更快地从服务器下载。
### 服务器端语言和框架

HTML，CSS 和 JavaScript 是前端（或客户端）语言，这意味着它们由浏览器运行以生成用户可以使用的网站前端。

还有另一类语言，称为后端（或服务器端）语言，这意味着它们先在服务器上运行，然后再将结果发送到浏览器进行显示。服务器端语言的一种典型用法是从数据库中获取一些数据并生成一些 HTML 以包含该数据，然后再将 HTML 发送给浏览器以将其显示给用户。

服务器端语言的例子包括 ASP.NET，Python，PHP 和 NodeJS。

Web 最佳做法
--------

我们已经简要讨论了用于构建网站的技术。现在，让我们讨论应该采用的最佳做法，以确保以最佳方式使用这些技术。

在进行 Web 开发时，不确定性的主要原因来自以下实际情况：你不知道每个用户将使用哪类技术条件来查看你的网站：

* 用户 1 可能正在带有狭窄屏幕的 iPhone 上观看它。
* 用户 2 可能正在连接了宽屏显示器的 Windows 笔记本电脑上查看它。
* 用户 3 可能是盲人，并且使用屏幕阅读器向他们朗读网页。
* 用户 4 可能正在使用无法运行现代浏览器的旧台式机。

因为你不完全知道用户将使用什么，所以你需要进行防御性设计——使你的网站尽可能灵活，以便上述所有用户都可以使用它，即使他们可能得到并不完全相同的体验。简而言之，我们正在努力使所有人都能使用 Web。

在学习的某些时候，你将遇到以下概念。

* **跨浏览器兼容性**（Cross-browser compatibility）是一种确保你的网页能够在尽可能多的设备上运行的做法。这包括使用所有浏览器都支持的技术，为可以处理这些浏览器的浏览器提供更好的体验（逐步增强），和/或编写代码，从而使之退回到较旧的浏览器中更简单但仍可用的体验（平稳降级）。它还涉及大量测试，以查看某些浏览器是否有任何故障，然后进行更多工作来修复这些故障。
* **响应式网页设计**（Responsive Web design）是一种使功能和布局变得灵活以便它们可以自动适应不同的浏览器的做法。一个明显的例子是在桌面上的宽屏浏览器中以一种方式进行布局，但在手机浏览器中以另一种更紧凑的单列布局的网站。现在请尝试调整浏览器窗口的宽度，然后看看会发生什么。
* **性能**（Performance）意味着要尽快加载网站，而且还应使其直观易用，以使用户不会碰壁离开。
* **无障碍**（Accessibility）意味着使你的网站可供尽可能多的不同类型的人使用（相关概念是多样性和包容性，以及包容性设计）。这包括视力障碍，听力障碍，认知障碍或肢体障碍的人。它也不仅仅局限于残疾人——也包含年轻人或老年人、来自不同文化的人、使用移动设备的人、或网络连接不可靠或缓慢的人。
* **国际化**（Internationalization）意味着使网站可以供来自不同文化背景的人使用，这些人会说和你不同的语言。这一点可以考虑一些技术手段（例如，更改布局以使其对于从右到左甚至垂直的语言仍然可以正常使用）和人为手段（例如，使用简单的非俚语，以便使以你的语言作为第二或第三语言的人更可能理解你的文字）。
* **隐私与安全**（Privacy & Security）这两个概念相关但不同。隐私是指允许人们私下从事其业务，而不是监视他们或收集你绝对不需要的更多数据。安全性是指以安全的方式构建你的网站，以使恶意用户无法从你或你的用户那里窃取信息。
参见
--

* History of the World Wide Web
* How does the internet work?


CSS 基础 - 学习 Web 开发

CSS 基础
======

* 上一页
* Overview: Getting started with the web
* 下一页

CSS（Cascading Style Sheets，层叠样式表）是为 web 内容添加样式的代码。本节将介绍 CSS 的基础知识，并解答像这样的问题：怎样将文本设置为红色？怎样将内容显示在屏幕的特定位置？怎样用背景图片或颜色来装饰网页？

什么是 CSS？
--------

和 HTML 类似，CSS 也不是真正的编程语言，甚至不是标记语言。**CSS 是一门样式表语言**，这也就是说人们可以用它来选择性地为 HTML 元素添加样式。举例来说，以下 CSS 代码选择了所有的段落文字，并将它们设置为红色。

```css
p {
  color: red;
}
```

让我们来试一试！在文本编辑器中，将上述的三行 CSS 代码粘贴到一个新的文件中，将文件命名为 `style.css` 并保存到 `styles` 文件夹下。

为了使代码发挥作用，我们仍然需要将上述 CSS 样式应用到你的 HTML 文档中。否则，这些样式不会改变 HTML 的外观。（如果你没有完成前几节的实践，请复习处理文件和 HTML 基础。）

1. 打开 `index.html` 文件，然后将下面一行粘贴到文档头部（也就是 `<head>` 和 `</head>` 标签之间）。

```html
<link href="styles/style.css" rel="stylesheet" />
```

2. 保存 `index.html` 并用浏览器将其打开。应该看到以下页面：

![一个 Mozilla 徽标和一些段落，段落文字通过 css 设置为红色](/zh-CN/docs/Learn/Getting_started_with_the_web/CSS_basics/website-screenshot-styled.png)如果段落文字变红，那么祝贺你，CSS 样式已经生效了。

### “CSS 规则集”详解

让我们来剖析一下红色段落文字的 CSS 代码，了解它是如何工作的：

![CSS p 声明，其中 color 为 red](/zh-CN/docs/Learn/Getting_started_with_the_web/CSS_basics/css-declaration-small.png)

整个结构称为**规则集**（*规则集*通常简称*规则*），注意各个部分的名称：

选择器（Selector）

HTML 元素的名称位于规则集开始。它选择了一个或多个需要添加样式的元素（在这个例子中就是 `<p>` 元素）。要给不同元素添加样式，只需要更改选择器。

声明（Declaration）

一个单独的规则，如 `color: red;` 用来指定添加样式元素的**属性**。

属性（Properties）

改变 HTML 元素样式的途径（本例中 `color` 就是 `<p>` 元素的属性）。CSS 中，由编写人员决定修改哪个属性以改变规则。

属性的值（Property value）

在属性的右边，冒号后面即**属性的值**，它从指定属性的众多外观中选择一个值（我们除了 `red` 之外还有很多属性值可以用于 `color` ）。

注意其他重要的语法：

* 除了选择器部分，每个规则集都应该包含在成对的大括号里（`{}`）。
* 在每个声明里要用冒号（`:`）将属性与属性值分隔开。
* 在每个规则集里要用分号（`;`）将各个声明分隔开。

如果要同时修改多个属性，只需要将它们用分号隔开，就像这样：

```css
p {
  color: red;
  width: 500px;
  border: 1px solid black;
}
```

### 选择多个元素

也可以选择多种类型的元素并为它们添加一组相同的样式。将不同的选择器用逗号分开。例如：

```css
p,
li,
h1 {
  color: red;
}
```

### 不同类型的选择器

选择器有许多不同的类型。上面只介绍了**元素选择器**，用来选择 HTML 文档中给定的元素。但是选择操作可以更加具体。下面是一些常用的选择器类型：

| 选择器名称 | 选择的内容 | 示例 |
| --- | --- | --- |
| 元素选择器（也称作标签或类型选择器） | 所有指定类型的 HTML 元素 | `p`选择 `<p>` |
| ID 选择器 | 具有特定 ID 的元素。单一 HTML 页面中，每个 ID 只对应一个元素，一个元素只对应一个 ID | `#my-id`选择 `<p id="my-id">` 或
 `<a id="my-id">` |
| 类选择器 | 具有特定类的元素。单一页面中，一个类可以有多个实例 | `.my-class`选择
 `<p class="my-class">` 和
 `<a class="my-class">` |
| 属性选择器 | 拥有特定属性的元素 | `img[src]`选择
 `<img src="myimage.png">` 但不是
 `<img>` |
| 伪类选择器 | 特定状态下的特定元素（比如鼠标指针悬停于链接之上） | `a:hover`选择仅在鼠标指针悬停在链接上时的 `<a>` 元素 |

选择器的种类远不止于此，更多信息请参阅 MDN 的选择器指南。

字体和文本
-----

在探索了一些 CSS 基础后，我们来把更多规则和信息添加至 `style.css` 中，从而让示例更美观。

1. 第一步，找到之前在你的网站会是什么样子？中保存的 Google Font 输出的地址。并以 `<link>` 元素的形式添加进 `index.html` 文档头部（ `<head>` 和 `</head>` 之间的任意位置）。代码如下：

```html
<link
 href="https://fonts.googleapis.com/css?family=Open+Sans"
 rel="stylesheet" />
```

这段代码将你的页面链接到一个样式表，该样式表将 Open Sans 字体家族与你的网页一起加载。
2. 接下来，删除 `style.css` 文件中已有的规则。虽然测试是成功的，但是红字看起来并不太舒服。
3. 添加以下几行（如下图所示），用你在你的网站会是什么样子？中选择的 `font-family` 替换 `font-family`。`font-family` 属性指的是你想用于文本的字体。这个规则为整个页面定义了一个全局的基本字体和字体大小。由于 `<html>` 是整个页面的父元素，它里面的所有元素都继承相同的 `font-size` 和 `font-family`。

```css
html {
  font-size: 10px; /\* px 表示“像素（pixel）”: 基础字号为 10 像素 \*/
  font-family: "Open Sans", sans-serif; /\* 这应该是你从 Google Fonts 得到的其余输出。 \*/
}
```

**备注：** CSS 文档中所有位于 `/*` 和 `*/` 之间的内容都是 **CSS 注释**。浏览器在渲染代码时会忽略注释。CSS 注释是一种让你写下关于你的代码或逻辑的有用注解的方式。
4. 接下来为 HTML 主体内的元素（h1、`<li>` 和 `<p>`）设置字体大小。我们也将标题居中显示。最后，扩充下方的第二个规则集，为正文设置行高和字间距，从而提高页面的可读性。

```css
h1 {
  font-size: 60px;
  text-align: center;
}

p,
li {
  font-size: 16px;
  line-height: 2;
  letter-spacing: 1px;
}
```

可以随时调整这些 `px` 值来获得满意的结果，以下是大体效果：

![一个 Mozilla 徽标和一些段落，设置了 sans-serif 字体，字体大小、行高和字间距已经调整，主页的标题已经居中](/zh-CN/docs/Learn/Getting_started_with_the_web/CSS_basics/website-screenshot-font-small.png)

CSS：一切皆盒子
---------

编写 CSS 时你会发现，你的工作好像是围绕着一个一个盒子展开的——设置尺寸、颜色、位置，等等。页面里大部分 HTML 元素都可以被看作若干层叠的盒子。

![一大堆箱子堆在一起](/zh-CN/docs/Learn/Getting_started_with_the_web/CSS_basics/boxes.jpg)

照片来自 https://www.geograph.org.uk/photo/3418115 ，Jim Barton cc-by-sa/2.0 版权所有

CSS 布局主要是基于*盒子模型*。在你的页面上占用空间的每个盒子都有类似的属性：

* `padding`（内边距）：是指内容周围的空间。在下面的例子中，它是段落文本周围的空间。
* `border`（边框）：是紧接着内边距的线。
* `margin`（外边距）：是围绕元素边界外侧的空间。

![有三个彼此包含的盒子。从外到内，它们被标记为 margin、border 和 padding](/zh-CN/docs/Learn/Getting_started_with_the_web/CSS_basics/box-model.png)

这里还使用了：

* `width`：元素的宽度
* `background-color`：元素内容和内边距底下的颜色
* `color`：元素内容（通常是文本）的颜色
* `text-shadow`：为元素内的文本设置阴影
* `display`：设置元素的显示模式（继续阅读文章以了解更多细节）

开始在页面中添加更多 CSS 吧！大胆将这些新规则都添加到 `style.css` 的底部，而不要纠结改变属性值会带来什么结果。

### 更改页面颜色

```css
html {
  background-color: #00539f;
}
```

这条规则为整个页面设置了背景颜色。将颜色代码修改为设置为在“我的网站将会是什么样子？”中所选择的颜色。

### 文档体样式

```css
body {
  width: 600px;
  margin: 0 auto;
  background-color: #ff9500;
  padding: 0 20px 20px 20px;
  border: 5px solid black;
}
```

这里有对于 `<body>` 元素的几条声明，我们来逐条查看：

* `width: 600px;` 强制页面永远保持 600 像素宽。
* `margin: 0 auto;` 当你在 `margin` 或 `padding` 这样的属性上设置两个值时，第一个值影响元素的*上下*方向（在这个例子中设置为 `0`）；第二个值影响*左右*方向。(这里，`auto` 是一个特殊的值，它将可用的水平空间平均分配给左和右）。如 Margin 语法中所记载的那样，你也可以使用一个、两个、三个或四个值。
* `background-color: #FF9500;` 如前文所述，指定元素的背景颜色。我们给 body 用了一种略微偏红的橘色以与深蓝色的 `<html>` 元素形成反差，你也可以尝试其他颜色。
* `padding: 0 20px 20px 20px;` 我们给内边距设置了四个值来让内容四周产生一点空间。这一次我们不设置上方的内边距，设置右边，下方，左边的内边距为 20 像素。值以上、右、下、左的顺序排列。与 `margin` 一样，你也可以像 Padding 语法中所记载的那样，使用一个、两个、三个或四个值。
* `border: 5px solid black;` 这是为边框的宽度、样式和颜色设置的值。在本例中，它是一个在主体的所有侧面的 5 像素宽的纯黑色边框。
### 定位页面主标题并添加样式

```css
h1 {
  margin: 0;
  padding: 20px 0;
  color: #00539f;
  text-shadow: 3px 3px 1px black;
}
```

你可能已经注意到，在正文的顶部有一个难看的间隙。这是因为浏览器对 h1 元素（以及其他元素）应用了默认样式。这可能看起来是个坏主意，但其目的是为没有样式的页面提供基本的可读性。为了消除这种间隙，我们用设置 `margin: 0;` 来覆盖浏览器的默认样式。

接下来，我们将标题的顶部和底部内边距设置为 20 像素。

之后，我们将标题文本设置为与 HTML 背景颜色相同的颜色。

最后，`text-shadow` 对元素的文本内容施加阴影。它的四个值是：

* 第一个像素值设置阴影与文本的**水平偏移量**：它横移的距离。
* 第二个像素值设置阴影与文本的**垂直偏移量**：它向下移动的距离。
* 第三个像素值设置阴影的**模糊半径**。一个更大的值会产生一个更模糊的阴影。
* 第四个值设置阴影的基色。

试着用不同的值进行试验，看看它是如何改变外观的。

### 图像居中

```css
img {
  display: block;
  margin: 0 auto;
}
```

最后，我们把图像居中来使页面更美观。可以复用 body 的 `margin: 0 auto`，但有一些差异，需要额外的设置来使 CSS 发挥作用。

`<body>` 元素是**块级**元素，意味着它占据了页面的空间并且能够赋予外边距和其他改变间距的值。而图片是**行级**元素，不具备块级元素的一些功能。所以为了使图像有外边距，我们必须使用 `display: block` 给予其块级行为。

**备注：** 以上说明假定所选图片小于页面宽度（600 像素）。更大的图片会溢出 body 并占据页面的其他位置。要解决这个问题，可以：
 1）使用图片编辑器 来减小图片宽度；
 2）用 CSS 限制图片大小，即减小 `<img>` 元素 `width` 属性的值。

**备注：** 如果你暂时不能理解 `display: block` 和块级元素与行级元素的差别也没关系；随着你对 CSS 学习的深入，你将明白这个问题。`display` 属性的更多信息请查看 display 属性参考页面。

总结
--

如果你按部就班完成本文的实践，那么最终可以得到以下页面：

![一个居中的 Mozilla 的标志，还有一个页眉和段落。现在它看起来很有风格，整个页面的背景是蓝色的，居中的主要内容条是橙色的背景](/zh-CN/docs/Learn/Getting_started_with_the_web/CSS_basics/website-screenshot-final.png)

（你可以在这里查看我们的版本。）

若遇到问题，可以参考 GitHub 上的完整示例代码做对比。

本章介绍的 CSS 知识非常有限，更多内容请访问学习使用 CSS 为 HTML 添加样式。

* 上一页
* Overview: Getting started with the web
* 下一页