调试 HTML

编写 HTML 很好,但是如果出现问题,并且你无法找出代码中的错误在哪里,该怎么办?本文将向你介绍一些可以帮助你查找和修复 HTML 中错误的工具。

预备知识 掌握 基本 HTML 语法中涵盖的基本 HTML 知识。文本级语义,例如 标题和段落以及 列表结构化 HTML
学习成果
  • 调试 HTML 的关键背景知识
  • 使用浏览器开发者工具中的 DOM 检查器深入了解你的 HTML 代码。
  • 探索常见的 HTML 错误类型。
  • 使用 HTML 验证器检测 HTML 错误。

调试并不可怕

编写某种代码时,一切都很好,直到出现可怕的错误时刻——你做错了什么,所以你的代码不起作用——要么根本不起作用,要么没有按照你想要的方式运行。例如,下面显示了尝试编译Rust 语言编写的简单程序时报告的错误。

A console window showing the result of trying to compile a rust program with a missing quote around a string in a print statement. The error message reported is error: unterminated double quote string.

在这里,错误消息相对容易理解——“未终止的双引号字符串”。如果你查看列表,你可能会看到 println!(Hello, world!"); 逻辑上可能缺少一个双引号。然而,随着程序的增大,错误消息会很快变得更加复杂且难以解释,即使是简单的情况对于不了解 Rust 的人来说也可能显得有些吓人。

然而,调试并不一定可怕——熟练编写和调试任何代码的关键是熟悉语言和相关工具。

HTML 和调试

HTML 不像 Rust 那样复杂难懂。HTML 在解析之前不会被编译成不同的形式(它被解释,而不是编译)。而且,HTML 的元素语法可以说比 Rust、JavaScriptPython 等“真正的编程语言”更容易理解。

浏览器解析 HTML 的方式比大多数编程语言的解析方式要宽松得多,这既是好事也是坏事。

但首先,我们所说的宽松是什么意思?一般来说,当你在代码中做错了什么时,你会遇到两种主要的错误类型

  • 语法错误:这些是代码中的拼写错误,导致程序无法运行,就像前面显示的 Rust 错误一样。只要你熟悉语言的语法并知道错误消息的含义,这些错误通常很容易修复。
  • 逻辑错误:这些是语法实际上是正确的错误,但代码没有按照你的意图执行,这意味着程序运行不正确。这些错误通常比语法错误更难修复,因为没有错误消息可以直接引导你找到错误源。

HTML 本身没有语法错误,因为浏览器以宽松的方式解析它,这意味着即使源代码中有语法错误,页面仍然会显示。浏览器内置了规则来规定如何解释编写不正确的 HTML 标记(通常称为无效格式不正确的标记),并将其自动更改为一些有效的标记。

例如,以下 HTML 片段包含不正确嵌套的元素

html
<p>I didn't expect to find the <em>next-door neighbor's <strong>cat</em></strong> here!</p>

闭合的 </strong> 标签应该在闭合的 </em> 标签之前,但它在它之后。

如果你将此 HTML 加载到浏览器中,然后查看渲染的 DOM,你会看到嵌套已被浏览器更正

html
<p>
  I didn't expect to find the
  <em>next-door neighbor's <strong>cat</strong></em> here!
</p>

那么,这为什么既是好也是坏呢?嗯,在这种情况下,浏览器创建了预期的结果,但正如你稍后将看到的,情况并非总是如此。你总会得到一些东西运行,但浏览器并不总是能正确处理,这可能会导致问题。最好一开始就编写正确的标记。

注意:HTML 之所以被宽松解析,是因为在 Web 最初创建时,人们决定发布内容比确保语法绝对正确更重要。如果 Web 从一开始就更加严格,它可能不会像今天这样受欢迎。

那么如何查找标记错误呢?稍后我们将向你展示如何使用一个名为 HTML 验证器的工具查找 HTML 中的错误,但首先我们将向你展示如何使用DOM 检查器手动检查你的 HTML,然后探索你可能会寻找哪些类型的标记错误,以及浏览器可能如何解释这些错误。

使用 DOM 检查器

所有现代浏览器都内置了一套开发者工具(devtools),它们提供了一系列功能,用于检查当前选项卡中加载的网页。这些工具可以向你展示页面中渲染的 HTML、应用于每个 DOM 节点的 CSS、页面中运行的 JavaScript 等等。它们还允许你编辑当前运行的代码并实时查看页面上的效果。

你可以在每个浏览器中以类似的方式打开开发者工具——请参阅如何在浏览器中打开开发者工具以了解如何操作。

对于本文,唯一相关的开发者工具功能是 DOM 检查器,它显示当前渲染的 HTML DOM 并允许你编辑它。我们现在来看看这个

  1. 在浏览器中打开开发者工具。
  2. 打开 DOM 检查器。它在每个浏览器中的位置都相同——开发者工具中行首的第一个选项卡。在 Firefox 中,它被标记为检查器,而在 Safari、Edge 和 Chrome 中,它被标记为元素。这应该是你第一次打开开发者工具时默认选中的选项卡,如果不是,请选中它。
  3. 检查选项卡中显示的 DOM 树结构,并注意如何单击每个 DOM 节点开头的扩展箭头以展开和折叠它们并显示其后代节点。你还可以使用向上和向下光标键在节点之间上下移动,并使用向右和向左光标键展开和折叠节点。
  4. 还要尝试将鼠标悬停在节点上(或使用光标键选择它们),并注意当前悬停(或选择)的元素如何在视口中突出显示。
  5. 您还可以编辑渲染的 DOM。本文中我们不会使用编辑功能,但如果您好奇,请花一些时间了解如何操作。

轮到你了:使用 DOM 检查器学习 HTML

在本节中,你将使用 DOM 检查器研究一些代码,并了解浏览器如何处理常见的标记错误。

  1. 首先,将以下 HTML 文件列表保存为 debug-example.html,保存在你的本地机器上的某个位置。这个演示是故意编写了一些内置错误供我们探索。

    html
    <!doctype html>
    <html lang="en-US">
      <head>
        <meta charset="utf-8">
        <title>HTML debugging examples</title>
      </head>
    
      <body>
        <h1>HTML debugging examples</h1>
        <p>What causes errors in HTML?
        <ul>
          <li>Unclosed elements: If an element is <strong>not closed properly,then its effect can spread to areas you didn't intend
          <li>Badly nested elements: Nesting elements properly is also very important for code behaving correctly. <strong>strong <em>strong emphasized?</strong> what is this?</em>
          <li>Unclosed attributes: Another common source of HTML problems. Let's look at an example: <a href="https://www.mozilla.org/>link to Mozilla homepage</a>
        </ul>
      </body>
    </html>
    
  2. 接下来,在浏览器中打开它。你将看到类似这样的内容:一个简单的 HTML 文档,标题为 HTML 调试示例,以及一些关于常见 HTML 错误的信息,例如未闭合的元素、嵌套错误的元素和未闭合的属性。

  3. 这看起来立刻就不太好;让我们看看源代码,看我们能否找出原因(只显示了 body 内容)

    html
    <h1>HTML debugging examples</h1>
    
    <p>What causes errors in HTML?
    
    <ul>
      <li>Unclosed elements: If an element is <strong>not closed properly,
          then its effect can spread to areas you didn't intend
    
      <li>Badly nested elements: Nesting elements properly is also very important
          for code behaving correctly. <strong>strong <em>strong emphasized?</strong>
          what is this?</em>
    
      <li>Unclosed attributes: Another common source of HTML problems. Let's
          look at an example: <a href="https://www.mozilla.org/>link to Mozilla
          homepage</a>
    </ul>
    
  4. 让我们回顾一下问题

    • 段落列表项元素没有闭合标签。查看上面的图片,这似乎没有严重影响标记渲染,因为很容易推断一个元素应该在哪里结束,另一个元素应该在哪里开始。
    • 第一个 <strong> 元素没有闭合标签。这有点麻烦,因为不容易判断该元素应该在哪里结束。事实上,其余的文本都被渲染为粗体。
    • 此部分嵌套错误:<strong>strong <em>strong emphasized?</strong> what is this?</em>。由于之前的问题,很难判断这被解释成了什么。
    • href 属性值缺少一个闭合双引号。这似乎造成了最大的问题——链接根本没有被渲染。
  5. 现在我们来检查渲染的 DOM,而不是源代码。为此,请打开浏览器的 DOM 检查器。你将看到渲染标记的表示:Firefox 中的 HTML 检查器,突出显示了我们示例的段落,显示文本“HTML 中错误的原因是什么?”在这里你可以看到段落元素已被浏览器关闭。

  6. 看看浏览器是如何尝试修复我们的 HTML 错误的(我们是在 Firefox 中进行的审查;其他现代浏览器应该给出相同的结果)

    • 段落和列表项已被赋予闭合标签。

    • 不清楚第一个 <strong> 元素应该在哪里闭合,所以浏览器将每个单独的文本块都包装在它自己的 <strong> 元素中,一直到文档底部!

    • 浏览器已修复了不正确的嵌套,如下所示

      html
      <strong>
        strong
        <em>strong emphasized?</em>
      </strong>
      <em> what is this?</em>
      
    • 缺少双引号的链接已完全删除。最后一个列表项如下所示

      html
      <li>
        <strong>
          Unclosed attributes: Another common source of HTML problems. Let's look
          at an example:
        </strong>
      </li>
      

HTML 验证

从上面的例子你可以看出,你确实需要确保你的 HTML 格式良好!但是如何做到呢?在一个像上面这样的小例子中,很容易逐行查找错误,但是对于一个巨大而复杂的 HTML 文档呢?

这项工作的工具是 标记验证服务(或HTML 验证器),它由 W3C 创建和维护(你可以在Web 标准模型中了解它)。验证器将 HTML 文档作为输入,遍历它,并为你提供一份报告,告诉你 HTML 中有什么问题。

The HTML validator homepage

要指定要验证的 HTML,你可以提供一个网址、上传一个 HTML 文件,或者直接输入一些 HTML 代码。

验证 HTML 文档

在此任务中,我们将让你尝试 HTML 验证器。你将验证我们的示例文档,并查看返回的结果。此示例包含你之前使用 DOM 检查器研究过的相同 HTML。

  1. 首先,在新的浏览器选项卡中加载标记验证服务(如果尚未打开)。
  2. 切换到通过直接输入验证选项卡。
  3. 复制所有示例文档的代码(不仅仅是 body 部分),并将其粘贴到标记验证服务中显示的大文本区域。
  4. 按下检查按钮。

这应该会给你一个错误和其他信息的列表。

A list of HTML validation results from the W3C markup validation service

解释错误消息

错误消息通常很有帮助,但有时它们不太容易理解。通过一些练习,你可以弄清楚如何解释这些消息来修复你的代码。让我们逐一查看错误消息,看看它们是什么意思。你会看到每条消息都带有一行和列号,以帮助你轻松定位错误。

  • “结束标签 li 隐式存在,但存在未闭合的元素”(2 个实例):这些消息表明存在一个应该闭合但未闭合的元素。结束标签是隐式存在的,但实际上并不在那里。行/列信息指向应该真正存在闭合标签的那一行之后的第一个行,但这足以作为线索来发现错误。

  • “未闭合元素 strong”:这更容易理解——一个 <strong> 元素未闭合,行/列信息直接指向它的位置。

  • “结束标签 strong 违反嵌套规则”:这指出了嵌套错误的元素,并且行/列信息指出了它们的位置。

  • “到达文件末尾,位于属性值内部。忽略标签”:这条信息相当神秘;它指的是某个地方有一个属性值格式不正确,可能靠近文件末尾,因为文件末尾出现在属性值内部。浏览器没有渲染链接的事实应该给我们一个很好的线索,知道哪个元素出了问题。

  • “已看到文件末尾并且存在开放元素”:这有点含糊,但基本上是指存在需要正确关闭的开放元素。行号指向文件的最后几行,并且此错误消息附带一行代码,指出一个开放元素的示例

    example: <a href="https://www.mozilla.org/>link to Mozilla homepage</a> ↩ </ul>↩ </body>↩</html>
    

    注意:属性缺少闭合引号会导致开放元素,因为文档的其余部分被解释为属性的内容。

  • “未闭合元素 ul”:这不是很 G 助,因为 <ul> 元素正确闭合的。此错误发生是因为 <a> 元素未闭合,原因是缺少闭合引号。

如果你无法理解每个错误消息的含义,请不要担心。一个好的策略是每次修复几个错误,然后在每组修复后重新验证你的 HTML,以显示还剩下哪些错误。有时,修复一个较早的错误也会消除其他错误消息——几个错误通常可能由一个问题引起,形成多米诺骨牌效应。

当看到一个漂亮的小绿横幅告诉你没有错误报告时,你就知道所有错误都已修复。在撰写本文时,它显示“文档检查完成。没有错误或警告显示。”

总结

至此,我们对 HTML 调试的介绍就结束了,它应该能为你提供一些有用的技能,以便在课程后期调试 HTML、CSS 和 JavaScript 代码时使用。这也标志着《使用 HTML 构建内容》模块的结束。