1. 主页
  2. 文档
  3. 超文本 HTML — 构建 Web
  4. HTML 介绍
  5. HTML 调试

HTML 调试

HTML 优雅明了,但要是出了错,你会不会一头雾水呢,本节将介绍一些查找和修复 HTML 错误的工具。

预备知识:阅读并理解 HTML 入门HTML 文字处理初步 和 创建超链接 等文章,熟悉 HTML 的基本概念。
学习目标:学习调试工具的基础用法,以查找 HTML 中的错误。

调试并不可怕

写代码通常都是按部就班的,但是一旦犯了错,可怕的代码问题就出现了:或彻底罢工,或得不到正确结果。比如,以下窗口显示了:用 Rust 编写的一个小程序在 编译 时得到的出错信息:

一个控制台窗口,显示了一个rust工程编译时的出错信息。(println宏少一个引号)

这里错误信息比较容易理解:”unterminated double quote string”,即”双引号字符串未闭合”。错误列表中可以看到 println!(Hello, world!"); 这里少一个双引号,然而当程序规模变大时,错误信息也会变得更复杂和更难解释,同时对于 Rust 新手而言,上述提示也是找不到北。

调试其实没有那么可怕,写代码和调试的关键其实是:熟悉语言本身和相关工具。

HTML 和调试

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

宽松的代码

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

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

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

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

主动学习:研究宽容的代码风格

现在来研究 HTML 代码的宽松特性。

  1. 首先,下载并保存 debug-example.html。代码中故意留了一些错误,以便探究(这里的 HTML 标记写成了 糟糕的格式,与 良好的格式 相反)。
  2. 下一步,在浏览器中打开,可以看到:
  3. 看起来糟透了,我们到源代码中寻找原因(只列出 body 部分):<h1>HTML 调试示例</h1> <p>什么使得 HTML 出错? <ul> <li>未闭合的元素:如果元素<strong>没有正确的结束标记,那么将影响下方整个区域,这不是你期望的。 <li>错误嵌套元素:正确进行嵌套是一项重要的编码习惯。<strong>重点(strong)<em>重点强调(strongly emphasised)?</strong>这又是什么鬼?</em> <li>未闭合的属性:另一种 HTML 常见错误。来看一个示例:<a href="https://www.mozilla.org/>Mozilla 主页链接</a> </ul> Copy to Clipboard
  4. 以下是问题清单:
    • 段落(Paragraph) 和 列表项(list item) 元素没有结束标签。但是由于元素的结束和另一个的开始很容易推断出来,因此上图中并没有太严重的渲染错误。
    • 第一个 <strong> 元素没有结束标签。这就严重了,因为该元素结束的位置难以确定。事实上所有剩余文本都加粗了。
    • 一下嵌套有问题:<strong>重点(strong)<em>重点强调(strongly emphasised)?</strong>这又是什么鬼?</em>​​​​。浏览器很难做出正确解释,理由同上。
    • href 属性缺少了一个双引号。从而导致了一个最严重的问题:整个链接完全没有渲染出来。
  5. 下面暂时忽略源代码中的标记,先看一下浏览器渲染出的标记。打开浏览器的开发者工具。如果不太熟悉,请先阅读 浏览器开发工具概览
  6. 在 DOM 查看器中可以看到渲染的标记:
  7. 通过 DOM 查看器可以清楚地看到,浏览器已经尝试修补代码错误(我们尝试了 Firefox,其他现代浏览器也应给出同样结果):
    • 段落和列表元素加上了关闭标签。
    • 第一个 <strong> 没有明确的关闭标签,因此浏览器为之后所有独立块都补全了 <strong></strong>
    • 浏览器是这样修补嵌套错误的:<strong>重点(strong) <em>重点强调(strongly emphasised)?</em> </strong> <em>这又是什么鬼?</em>Copy to Clipboard
    • 删除整个缺少双引号的链接。最后一个列表项就成了:<li> <strong>未闭合的属性:另一种 HTML 常见错误。来看一个示例:</strong> </li>Copy to Clipboard

HTML 验证

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

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

The HTML validator homepage

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

主动学习:验证 HTML 文档

不妨用上文的 debug-example.html 尝试一下:

  1. 在浏览器中打开 Markup Validation Service 。
  2. 选择 Validate by Direct Input 标签。
  3. 将整个示例文档的代码(而不仅仅是body部分)复制粘贴到正中的文本框内。
  4. 点击 Check 按钮。

将返回一个包含错误和其它信息的列表。

W3C验证工具为本示例给出的验证结果。

错误信息分析

错误信息一般都是有用的,也有没用的,有一些经验后你就能够分析并修复这些错误。下面来观察这些错误信息。可以看到每条信息都对应一个行号和一条信息,使得定位错误更方便。

  • End tag li implied, but there were open elements(需要 li 的结束标签,但又开始了新的元素)(共出现 2 次):这条信息表明有开始标签必须有结束标签,必须出现结束标签的地方却没有找到它。行/列信息指出结束标签必须出现的位置的第一行,这一线索已经足够明显了。
  • Unclosed element strong(未闭合元素 strong ):非常容易理解,<strong> 元素没有闭合,行/列信息表明了它的位置。
  • End tag strong violates nesting rules(结束标签 strong 违反了嵌套规则):指出了错误嵌套的元素,行/列信息表明了它的位置。
  • End of file reached when inside an attribute value. Ignoring tag(在属性值内达到文件末尾。忽略标签): 这个比较难懂,它说的是在某个地方有一个属性的值格式有误,估计是在文件末尾附近,因为文件的结尾出现在了一个属性值里。事实上浏览器没有渲染超链接已经是一个很明显的线索了。
  • End of file seen and there were open elements(文件结尾有未闭合的元素):这个略有歧义,但基本上表明了有元素没有正确闭合。行号指向文件最后几行,且错误信息给出了一个这种错误的案例:来看一个示例:<a href=”https://www.mozilla.org/>Mozilla 主页链接</a> ↩ </ul>↩ </body>↩</html>注:属性缺少结束引号会导致元素无法闭合。因为文档所有剩余部分(直到文档某处出现一个引号)都将被解析为属性的内容。
  • Unclosed element ul(未闭合元素 ul):这个意义不大,因为 <ul> 已经正确闭合了。出现这个错误是因为 <a> 元素没有右引号而没有闭合。

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

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

W3C站点上HTML通过验证的横幅

小结

以上就是 HTML 调试的一篇入门介绍,同时对于调试 CSS 和 JavaScript 也有帮助,或者你职业生涯中的任一门语言。这也是 HTML 学习一章的最后一节,接下来是两个小测试,点击“下一页”来小试牛刀吧。