文档结构

HTML 文档包括文档类型声明和 <html> 根元素。在 <html> 元素中嵌套着文档头部和文档主体。虽然文档头部对于有视觉的访问者来说是不可见的,但它对于使您的网站正常运行至关重要。它包含所有元信息,包括用于搜索引擎和社交媒体结果的信息、浏览器选项卡和移动设备主屏幕快捷方式的图标,以及内容的行为和呈现方式。在本节中,您将了解几乎每个网页上都存在的组件(尽管这些组件不可见)。

要创建 MachineLearningWorkshop.com (MLW) 网站,首先要包含对于每个网页都应视为必不可少的组件:文档类型、内容的人类语言、字符集,当然还有网站或应用程序的标题或名称。

添加到每个 HTML 文档

有几个功能应被视为任何和每个网页都必不可少的。如果缺少这些元素,浏览器仍然会呈现内容,但请包含它们。务必包含。

<!DOCTYPE html>

任何 HTML 文档中的第一件事都是序言。对于 HTML,您只需要 <!DOCTYPE html>。这看起来可能像一个 HTML 元素,但它不是。它是一种称为“doctype”的特殊类型的节点。doctype 告诉浏览器使用标准模式。如果省略,浏览器将使用称为怪异模式的不同渲染模式。包含 doctype 有助于防止怪异模式。

<html>

<html> 元素是 HTML 文档的根元素。它是 <head><body> 的父元素,包含 HTML 文档中除 doctype 之外的所有内容。如果省略,则会暗示包含,但包含它很重要,因为这是声明文档内容语言的元素。

内容语言

添加到 <html> 标记的 lang 语言属性定义了文档的主要语言。lang 属性的值是一个由两位或三位 ISO 语言代码后跟区域组成的语言标记。区域是可选的,但建议使用,因为一种语言在不同区域之间可能差异很大。例如,法语在加拿大 (fr-CA) 和布基纳法索 (fr-BF) 非常不同。此语言声明使屏幕阅读器、搜索引擎和翻译服务能够知道文档语言。

lang 属性不限于 <html> 标记。如果页面中存在与主文档语言不同的语言文本,则应使用 lang 属性来标识文档中主语言的例外情况。就像包含在头部中一样,主体中的 lang 属性没有视觉效果。它仅添加语义,使辅助技术和自动化服务能够知道受影响内容的语言。

除了设置文档的语言以及该基本语言的例外情况外,该属性还可以在 CSS 选择器中使用。<span lang="fr-fr">Ceci n'est pas une pipe.</span> 可以使用属性和语言选择器 [lang|="fr"]:lang(fr) 进行定位。

在打开和关闭 <html> 标记之间嵌套着两个子元素:<head><body>

<!DOCTYPE html>
<html lang="en-US">
  <head>
  </head>
  <body>
  </body>
</html>

<head>,或文档元数据头部,包含站点或应用程序的所有元数据。主体包含可见内容。本节的其余部分重点介绍嵌套在打开和关闭 <head></head> 内的组件

<head> 内的必需组件

文档元数据,包括文档标题、字符集、视口设置、描述、基本 URL、样式表链接和图标,都可以在 <head> 元素中找到。虽然您可能不需要所有这些功能,但始终包含字符集、标题和视口设置。

字符编码

<head> 中的第一个元素应该是 charset 字符编码声明。它位于标题之前,以确保浏览器可以呈现该标题中的字符以及文档其余部分中的所有字符。

大多数浏览器中的 默认编码windows-1252,具体取决于区域设置。但是,您应该使用 UTF-8,因为它支持所有字符(甚至包括您甚至不知道存在的字符)的一到四字节编码。此外,它是 HTML5 要求的编码类型。

要将字符编码设置为 UTF-8,请包含

<meta charset="utf-8" />

通过声明 UTF-8(不区分大小写),您甚至可以在标题中包含表情符号(但请不要这样做)。

字符编码被继承到文档中的所有内容,甚至包括 <style><script>。这个小小的声明意味着您可以在类名和 selectorAPI 中包含表情符号(再次强调,请不要这样做)。如果您使用表情符号,请确保以增强可用性而不损害无障碍功能的方式使用它们。

文档标题

您的主页和所有其他页面都应具有唯一的标题。文档标题的内容,即打开和关闭 <title> 标记之间的文本,显示在浏览器选项卡、打开的窗口列表、历史记录、搜索结果中,除非使用 <meta> 标记重新定义,否则也会显示在社交媒体卡片中。

<title>Machine Learning Workshop</title>

视口元数据

另一个应被视为必不可少的元标记是 视口元标记,它有助于网站的自适应性,使内容默认情况下能够很好地呈现,无论视口宽度如何。虽然 视口元标记 自 2007 年 6 月第一部 iPhone 问世以来就已经存在,但直到最近才在规范中记录。由于它能够控制视口的大小和比例,并防止网站内容被缩小以将 960px 的站点适应到 320px 的屏幕上,因此绝对值得推荐。

<meta name="viewport" content="width=device-width" />

前面的代码意味着“使网站具有自适应性,首先使内容的宽度与屏幕宽度相同”。除了 width 之外,您还可以设置缩放和可伸缩性,但它们都默认为可访问的值。如果您想明确指定,请包含

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1" />

视口是 Lighthouse 无障碍功能审核的一部分;如果您的网站是可伸缩的并且没有设置最大尺寸,则您的网站将通过审核。

到目前为止,我们的 HTML 文件的轮廓是

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Machine Learning Workshop</title>
    <meta name="viewport" content="width=device-width" />
  </head>
  <body>

  </body>
</html>

其他 <head> 内容

<head> 中还有很多内容。事实上,是所有元数据。您将在 <head> 中找到的大多数元素都在这里介绍,同时将大量的 <meta> 选项留到下一章。

您已经看到了元字符集和文档标题,但是除了 <meta> 标记之外,还有很多其他元数据也应该包含在内。

CSS

<head> 是您包含 HTML 样式的的地方。如果您想了解样式,有一个专门介绍 CSS 的学习路径,但您确实需要知道如何在 HTML 文档中包含样式。

有三种包含 CSS 的方法:<link><style>style 属性。

在 HTML 文件中包含样式的主要两种方法是使用 rel 属性设置为 stylesheet<link> 元素包含外部资源,或者在文档头部的打开和关闭 <style> 标记内直接包含 CSS。

<link> 标记是包含样式表的首选方法。链接单个或少量外部样式表对于开发者体验和网站性能都很有好处:您可以将 CSS 保存在一个位置,而不是将其散布在各处,并且浏览器可以缓存外部文件,这意味着不必在每次页面导航时都重新下载它。

语法是 <link rel="stylesheet" href="styles.css">,其中 styles.css 是您的样式表的 URL。您经常会看到 type="text/css"。没有必要!如果您要包含用 CSS 以外的语言编写的样式,则需要 type,但由于没有其他类型,因此不需要此属性。rel 属性定义了关系:在本例中为 stylesheet。如果省略此属性,则不会链接您的 CSS。

您很快会发现其他一些 rel 值,但让我们首先讨论包含 CSS 的其他方法。

如果您希望您的外部样式表样式位于级联层中,但您无法访问编辑 CSS 文件以将层信息放入其中,则您需要使用 <style> 内的 @import 来包含 CSS

<style>
  @import "styles.css" layer(firstLayer);
</style>

当使用 @import 将样式表导入到您的文档中时,可以选择导入到级联层中,@import 语句必须是您的 <style> 或链接样式表中的第一个语句,位于字符集声明之外。

虽然级联层仍然相当新,您可能不会在头部 <style> 中看到 @import,但您经常会看到在头部样式块中声明的自定义属性

<style>
  :root {
    --theme-color: #226DAA;
  }
</style>

样式,无论是通过 <link> 还是 <style>,或者两者都通过,都应该放在头部。如果包含在文档主体中,它们也可以工作,但您希望将样式放在头部中是出于性能原因。这可能看起来违反直觉,因为您可能会认为您希望先加载内容,但实际上您希望浏览器知道在加载内容时如何呈现内容。首先添加样式可以防止在元素首次呈现后对其进行样式设置时发生的不必要的重绘。

还有一种包含样式的方法,您永远不会在文档的 <head> 中使用它:内联样式。您可能永远不会在头部中使用内联样式,因为用户代理的样式表默认情况下会隐藏头部。但是,例如,如果您想制作一个没有 JavaScript 的 CSS 编辑器,以便您可以测试页面的自定义元素,您可以使用 display: block 使头部可见,然后隐藏头部中的所有内容,然后使用内联 style 属性,使可编辑内容的样式块可见。

<style contenteditable style="display: block; font-family: monospace; white-space: pre;">
  head { display: block; }
  head * { display: none; }
  :root {
    --theme-color: #226DAA;
  }
</style>

虽然您可以在 <style> 上添加内联样式,但在 style 中设置 <style> 的样式更有趣。我离题了。

link 元素用于在 HTML 文档和外部资源之间创建关系。其中一些资源可能会被下载,另一些是信息性的。关系的类型由 rel 属性的值定义。目前有 25 个可用于 rel 属性的值,这些值可以与 <link><a><area><form> 一起使用,其中一些可以与所有元素一起使用。最好将与元信息相关的元素包含在头部中,并将与性能相关的元素包含在 <body> 中。

您现在将在头部中包含其他三种类型:iconalternatecanonical。(您将在下一个模块中包含第四种类型,rel="manifest")。

Favicon

使用 <link> 标记,以及 rel="icon" 属性/值对来标识要用于您的文档的 favicon。favicon 是一个非常小的图标,通常出现在浏览器选项卡上,通常位于文档标题的左侧。当您打开了大量选项卡时,选项卡会缩小,标题可能会完全消失,但图标始终保持可见。大多数 favicon 都是公司或应用程序徽标。

如果您不声明 favicon,浏览器将在顶级目录(网站的根文件夹)中查找名为 favicon.ico 的文件。使用 <link>,您可以使用不同的文件名和位置

<link rel="icon" sizes="16x16 32x32 48x48" type="image/png" href="/images/mlwicon.png" />

前面的代码表示“对于 16px、32px 或 48px 大小合适的情况,请使用 mlwicon.png 作为图标。”sizes 属性接受 any 值(对于可伸缩图标)或以空格分隔的方形 widthXheight 值列表;其中宽度和高度值在 16、32、48 或更大的几何序列中,像素单位被省略,X 不区分大小写。

<link rel="apple-touch-icon" sizes="180x180" href="/images/mlwicon.png" />
<link rel="mask-icon" href="/images/mlwicon.svg" color="#226DAA" />

Safari 浏览器有两种特殊的非标准图标:用于 iOS 设备的 apple-touch-icon 和用于 macOS 上固定选项卡的 mask-iconapple-touch-icon 仅在用户将网站添加到主屏幕时应用:您可以为不同的设备指定具有不同 sizes 的多个图标。mask-icon 仅在用户在桌面 Safari 中固定选项卡时使用:图标本身应为单色 SVG,并且 color 属性会用所需的颜色填充图标。

虽然您可以使用 <link> 在每个页面甚至每个页面加载时定义完全不同的图像,但请不要这样做。为了保持一致性和良好的用户体验,请使用单个图像!Twitter 使用蓝色的鸟:当您在浏览器选项卡中看到蓝色的鸟时,您就知道该选项卡是打开到 Twitter 页面的,而无需单击该选项卡。Google 为其不同的应用程序使用不同的 favicon:例如,有邮件图标、日历图标。但是所有 Google 图标都使用相同的配色方案。同样,您只需从图标即可确切知道打开的选项卡的内容。

网站的备用版本

我们使用 rel 属性的 alternate 值来标识网站的翻译版本或备用表示形式。

假设我们有翻译成法语和巴西葡萄牙语的网站版本

<link rel="alternate" href="https://www.machinelearningworkshop.com/fr/" hreflang="fr-FR" />
<link rel="alternate" href="https://www.machinelearningworkshop.com/pt/" hreflang="pt-BR" />

当为翻译使用 alternate 时,必须设置 hreflang 属性。

alternate 值不仅仅用于翻译。例如,当 type 属性设置为 application/rss+xmlapplication/atom+xml 时,type 属性可以定义 RSS 源的备用 URI。让我们链接到网站的假想 PDF 版本。

<link rel="alternate" type="application/x-pdf" href="https://machinelearningworkshop.com/mlw.pdf" />

如果 rel 值为 alternate stylesheet,则它定义了一个备用样式表,并且必须设置 title 属性,为该备用样式命名。

Canonical

如果您创建了多个 Machine Learning Workshop 的翻译版本或版本,搜索引擎可能会对哪个版本是权威来源感到困惑。为此,请使用 rel="canonical" 来标识网站或应用程序的首选 URL。

在您的所有翻译页面和主页上包含规范 URL,指示我们的首选 URL

<link rel="canonical" href="https://www.machinelearning.com" />

rel="canonical" 规范链接最常用于与出版物和博客平台进行交叉发布,以注明原始来源;当网站联合内容时,应包含指向原始来源的规范链接。

脚本

<script> 标记用于包含脚本。默认类型是 JavaScript。如果您包含任何其他脚本语言,请包含带有 mime 类型的 type 属性,或者如果是 JavaScript 模块,则包含 type="module"。只有 JavaScript 和 JavaScript 模块会被解析和执行。

<script> 标记可用于封装您的代码或下载外部文件。在 MLW 中,没有外部脚本文件,因为与普遍的看法相反,您不需要 JavaScript 即可获得功能齐全的网站,而且,嗯,这是一个 HTML 学习路径,而不是 JavaScript 学习路径。

您将在稍后包含一小段 JavaScript,以创建一个彩蛋

<script>
  document.getElementById('switch').addEventListener('click', function() {
    document.body.classList.toggle('black');
  });
</script>

此代码段为 ID 为 switch 的元素创建了一个事件处理程序。使用 JavaScript,您不希望在元素存在之前引用它。它还不存在,所以我们暂时不包含它。当我们添加灯开关元素时,我们将把 <script> 添加到 <body> 的底部,而不是 <head> 中。为什么?两个原因。我们希望确保在遇到引用它们的脚本之前元素存在,因为我们没有将此脚本基于 DOMContentLoaded 事件。而且,主要是,JavaScript 不仅是渲染阻塞的,而且浏览器在下载脚本时会停止下载所有资源,并且在 JavaScript 执行完成之前不会恢复下载其他资源。因此,您经常会在文档末尾而不是头部找到 JavaScript 请求。

有两个属性可以减少 JavaScript 下载和执行的阻塞性质:deferasync。使用 defer,HTML 渲染在下载期间不会被阻止,并且 JavaScript 仅在文档完成渲染后才执行。使用 async,渲染在下载期间也不会被阻止,但是一旦脚本完成下载,渲染就会暂停,同时执行 JavaScript。

loading when using async and defer.

要将 MLW 的 JavaScript 包含在外部文件中,您可以编写

<script src="js/switch.js" defer></script>

添加 defer 属性会将脚本的执行推迟到所有内容都渲染完毕之后,从而防止脚本损害性能。asyncdefer 属性仅在外部脚本上有效。

Base

还有另一个仅在 <head> 中找到的元素。不太常用,<base> 元素允许设置默认链接 URL 和目标。href 属性定义了所有相对链接的基本 URL。

target 属性,在 <base> 以及链接和表单上有效,设置了这些链接应在何处打开。默认值 _self 在与当前文档相同的上下文中打开链接的文件。其他选项包括 _blank(在新窗口中打开每个链接)、当前内容的 _parent(如果打开器不是 iframe,则可能与 self 相同)或 _top(在同一个浏览器选项卡中,但从任何上下文中弹出以占据整个选项卡)。

大多数开发者将 target 属性添加到他们希望在新窗口中打开的少数链接(如果有)本身的链接或表单上,而不是使用 <base>

<base target="_top" href="https://machinelearningworkshop.com" />

如果我们的网站发现自己嵌套在像 Yummly 这样的网站上的 iframe 中,则包含 <base> 元素将意味着当用户单击我们文档中的任何链接时,链接将加载弹出 iframe,占据整个浏览器窗口。

此元素的缺点之一是锚链接使用 <base> 解析。<base> 有效地将链接 <a href="#ref"> 转换为 <a target="_top" href="https://machinelearningworkshop.com#ref">,从而触发对附加了片段的基本 URL 的 HTTP 请求。

关于 <base> 的其他一些注意事项:文档中只能有一个 <base> 元素,并且它应该在任何相对 URL(包括可能的脚本或样式表引用)使用之前出现。

现在的代码看起来像这样

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Machine Learning Workshop</title>
    <meta name="viewport" content="width=device-width" />
    <link rel="stylesheet" src="css/styles.css" />
    <link rel="icon" type="image/png" href="/images/favicon.png" />
    <link rel="alternate" href="https://www.machinelearningworkshop.com/fr/" hreflang="fr-FR" />
    <link rel="alternate" href="https://www.machinelearningworkshop.com/pt/" hreflang="pt-BR" />
    <link rel="canonical" href="https://www.machinelearning.com" />
  </head>
  <body>

    <!-- <script defer src="scripts/lightswitch.js"></script>-->
  </body>
</html>

HTML 注释

请注意,脚本被包裹在一些角括号、破折号和一个感叹号之间。这就是您注释掉 HTML 的方式。在页面上实际内容之前,我们将脚本注释掉。 <!----> 之间的任何内容都将不可见或不被解析。HTML 注释可以放在页面上的任何位置,包括头部或主体,但脚本或样式块除外,在脚本或样式块中,您应分别使用 JavaScript 和 CSS 注释。

您已经了解了 <head> 中基本内容,但您想学习的不仅仅是基础知识。在接下来的章节中,我们将学习元标记,以及如何控制在社交媒体上链接到您的网站时显示的内容。

检查您的理解情况

测试您对文档结构的知识。

您如何识别文档的语言?

language 属性添加到 HTML 标记。
再试一次。
lang 属性添加到 HTML 标记。
正确!
将 <lang> 元素添加到 <head>
再试一次。

选择可以包含在 <head> 中的元素。

<p>
再试一次。
<title>
正确!
<meta>
正确!