Skip to content
This page has been auto-translated and may contain errors.View in English

你的第一个 HTML 页面

docs.scrimba.com

每个 HTML 文档都共享相同的基本结构:声明文档类型的一行,包装所有内容的根元素,用于存放页面信息的 head,以及用于存放人们看到的内容的 body。本章逐行分解这个结构,然后将其保存到可以在浏览器中打开的文件。

文档框架

以下是每个页面都从这个框架开始的内容。你可以完全按照它复制,并改变 body 中的部分:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>My first page</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>This is my first web page.</p>
  </body>
</html>

第一行 <!DOCTYPE html> 告诉浏览器这是一个现代 HTML 页面。之后是 根元素 <html>,它包装了页面上的所有其他内容。在它内部有两个盒子:<head> 用于幕后信息,<body> 用于访问者看到的文字和图片。你的标题和段落应该放在 body 中,因为那是展示的部分。

把整个事物想象成一个标有标签的包裹。doctype 是说明要使用哪个邮政系统的邮票,<html> 是盒子,head 是外面的标签,body 是包装里面的东西。

每个文档都由相同的四个部分构成,按照每个部分的作用来命名会很有帮助:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>My first page</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>This is my first web page.</p>
  </body>
</html>

<!DOCTYPE html>文档类型声明。它不是 HTML 标签,而是一个开关:它的存在告诉浏览器以标准模式而不是为 1990 年代页面保留的旧 quirks 模式进行渲染。<html> 是根元素,是包含所有其他元素的单个元素。它的 lang="en" 属性声明了页面的语言。然后 <head> 保存关于页面的信息,<body> 保存内容。缩进不是必需的,但将 head 和 body 嵌套在 <html> 中,并将它们的子元素嵌套在它们中,可以保持结构可读性。

框架看起来像样板文件,但每一行都改变了浏览器处理文档的方式。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>My first page</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>This is my first web page.</p>
  </body>
</html>

<!DOCTYPE html> 是文档类型声明,尽管它包含尖括号,但它不是元素。它是一个模式开关。有了它,浏览器使用 标准模式,这意味着它遵循当前的布局和盒模型规范。省略它,浏览器就会回退到 quirks 模式,这是 1990 年代行为的一个模拟,会在盒子宽度等细节上出错。今天 HTML 只有一个正确的 doctype,就是这个短的;XHTML 时代那些长的、有版本号的 doctype 已经过时了。

<html> 是根元素,是整个文档树下降的单个节点。所有其他内容都是它的后代。lang 属性放在这里是因为它为整个文档设置了基础语言。<head><body> 是它唯一允许的两个子元素,按照这个顺序:元数据优先,内容其次。如果你忽略了 <head><body> 标签,解析器会为你插入它们(那个宽恕解析又来了),但写出来会让你的源代码和生成的树保持一致,这是你在推理任何一个时想要的。

Juno文档框架 每个页面都从相同的框架开始:<!DOCTYPE html>,然后是 <html> 包装一个 <head> 和一个 <body>。按原样复制,并在 body 中放入你自己的文字。现在不需要记住它;你会打字足够多次使它自然地坚持下去。
Juno文档框架 四个部分,每个有一个作用:doctype 打开标准模式,<html> 是根,<head> 是关于页面的信息,<body> 是内容。lang 属性放在 <html> 上,因为它描述了整个文档。将这个形状记在你的指尖中,每个新页面都以相同的可靠方式开始。
Juno文档框架 doctype 是一个模式开关,不是标签:有它你得到标准模式,没有它就是 quirks 模式和错误的盒大小。<html> 是恰好有两个子元素的根,head 然后 body,如果你忘记了解析器会插入它们。不管怎样都写出来,这样你的源代码就与你实际推理的树相匹配。

head 与 body 中放什么

<html> 内的两个盒子有不同的作用。<head> 保存浏览器需要知道但访问者不在页面上阅读的东西。<body> 保存访问者确实看到的所有内容。

html
<head>
  <title>My recipe notes</title>
</head>
<body>
  <h1>Banana bread</h1>
  <p>Mix, pour, bake for an hour.</p>
</body>

<title> 位于 head 中,它是页面的名称:它显示在浏览器标签中,而不是在页面中间。标题和段落位于 body 中,所以它们出现在页面本身上。一个简单的开始规则:如果访问者应该阅读它,它就放在 body 中。

划分是关于页面的信息对比页面的内容。<head> 是用于 元数据:关于文档的数据而不是文档的内容。<body> 是内容本身,在浏览器窗口中呈现的部分。

html
<head>
  <title>Banana bread recipe</title>
</head>
<body>
  <h1>Banana bread</h1>
  <p>Mix, pour, bake for an hour.</p>
</body>

最清晰的例子是 <title>。它位于 head 中是因为它不是页面内容的一部分,但它做真实的工作:它命名标签,它是有人收藏页面时保存的标签,它是搜索引擎在其结果中显示的标题。其他 head 元素遵循相同的逻辑。它们配置或描述页面。head 中没有任何内容会在页面区域中绘制,所以如果你发现自己想在 head 中放一个标题或图像,它实际上属于 body 中。

head 是文档描述和配置自己的地方;body 是该描述适用的内容。head 中的所有内容都是元数据,关于文档的数据而不是在页面区域中显示的内容。

html
<head>
  <title>Banana bread recipe</title>
  <meta name="description" content="A quick loaf: mix, pour, bake." />
</head>
<body>
  <h1>Banana bread</h1>
  <p>Mix, pour, bake for an hour.</p>
</body>

<title> 赚取了它的地位好多次。它命名浏览器标签,它是页面被收藏或分享时的默认文本,它是搜索结果中可点击的标题,这使它成为页面上最高价值的字符串之一。<meta name="description"> 元素提供搜索引擎可能在该标题下方显示的摘要行;它永远不会在页面上呈现,这就是重点。

head 也保存引入其他文件的元素:用于 CSS 的 <link rel="stylesheet"> 和用于 JavaScript 的 <script>,尽管 script 通常位于 body 的末尾,以便内容先解析。保持这个清洁的规则:head 在 body 之前被解析,所以任何页面需要在其内容被读取之前配置的东西(其编码、其样式表、其标题)都属于那里,而每个人实际上阅读的一切都属于 body 中。

Junohead 与 body 中放什么 Head 是幕后,body 是展示。<title> 位于 head 中并命名浏览器标签;你的标题和段落位于 body 中,人们在那里阅读它们。如果访问者应该看到它,它就放在 body 中。这个问题几乎排序了所有内容。
Junohead 与 body 中放什么 head 是元数据,关于页面的信息;body 是页面的内容。<title> 同时是标签名称、书签标签和搜索标题,这就是为什么它在 head 中值得一个位置。head 中没有任何内容会在页面上绘制,所以你想展示的标题或图像属于 body 中。
Junohead 与 body 中放什么 Head 描述和配置文档,body 是该配置适用的内容,head 首先被解析。<title><meta name="description"> 是搜索引擎阅读的高价值字符串,永远不会在页面上绘制。任何页面在其内容之前需要设置的东西,其编码和样式表,都放在 head 中;人们阅读的所有内容都放在 body 中。

字符集和视口

另外两行几乎在每个页面的 head 中。你可以按原样复制它们:

html
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>My first page</title>
</head>

第一行告诉浏览器如何读取你的文本,这样带重音的字母、花体引号和表情符号就能正确出现,而不是变成奇怪的符号。第二行告诉浏览器将页面适应屏幕宽度,这就是使其在手机上看起来合理而不是桌面页面的微小缩放版本的原因。你现在不需要理解每个单词。把两者都放在 head 的顶部,你的页面就会正常工作。

两个 <meta> 元素属于基本上每个页面的 head 中。<meta> 元素是一个空元素,在其属性中携带单个元数据。

html
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>My first page</title>
</head>

第一个设置 字符编码:浏览器用来将存储的字节转换回字母的方案。UTF-8 是覆盖你可能使用的每个字符的编码,从英语到表情符号,它是现代的默认值。把这一行放在 head 的第一位。

第二个是 视口 标签,它控制页面如何映射到移动屏幕。width=device-width 告诉浏览器将页面的宽度视为实际设备宽度,initial-scale=1.0 将起始缩放设置为 100%。没有它,手机假设页面是为桌面设计的,并缩小整个东西以适应,所以你的文本到达时无法阅读。这两行几乎是不可协商的,这就是为什么启动模板默认包括它们。

两个 <meta> 元素实际上是必需的,原因归结为浏览器如何处理文件。

html
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>My first page</title>
</head>

<meta charset> 声明字符编码,浏览器用来将文件的原始字节转换回字符(你输入的字母、标点和符号)的映射。这必须是 head 中的第一件事,理想情况下在文档的前 1024 字节内,因为存在序列问题:解析器必须先将字节解码为文本,然后才能读取其中任何一个,包括字符集声明本身。浏览器通过使用临时解码开始,然后在声明的字符集不同时重新解析来解决这个悖论。把声明放在第一位,就没有任何东西需要重新解析。使用 UTF-8;它编码了整个 Unicode,是现代网络的假定默认值。

回到 <html> 上的 lang 属性也是一个解析问题,尽管是语义上的。它为无法推断的软件命名文档的自然语言:屏幕阅读器(为看不到的人大声读出页面的软件)使用 lang 来选择正确的发音规则和语音,翻译工具用它来了解源语言。丢失或错误的 lang 会给盲人用户一个用错误的口音读出的页面,或者更糟,发音无意义。

<meta name="viewport"> 解决了移动渲染默认值。早期的智能手机为了应对仅桌面的页面,呈现到大约 980 像素宽的虚拟画布中,然后将其缩放以适应屏幕。width=device-width 覆盖了这一点,将页面的布局宽度映射到设备自己的宽度,这样你的响应式 CSS 就有了实际屏幕尺寸来处理;initial-scale=1.0 将初始缩放设置为 1:1。省略这个标签,响应式布局仍然根据 980 像素的假设计算,所以你精心构建的移动设计以桌面宽度呈现,然后被缩小,使整个练习失败。标签本身不做任何样式;它给你的 CSS 正确的尺寸来对其进行样式处理。

Juno字符集和视口 两行几乎出现在每个页面的 head 顶部附近:一行使你的文本正确阅读,包括重音和表情符号,一行使页面适应手机屏幕而不是缩小。把两者都复制进来,现在不要过度思考措辞。它们悄悄地修复了你原本会花一个下午追赶的问题。
Juno字符集和视口<meta charset="UTF-8"> 设置字节如何变成字母,所以把它放在 head 的第一位;UTF-8 覆盖了从纯英语到表情符号的所有内容。带有 width=device-width 的视口标签阻止了手机缩小桌面大小的页面到什么都没有。跳过视口线,你的移动布局到达时很小,这是经典的"为什么我的网站在我的手机上看起来坏了"的 bug。
Juno字符集和视口charset 首先来是因为解析器必须在可以读取声明本身之前将字节解码为文本;把它放在顶部,就没有任何东西需要重新解析。<html> 上的 lang 是屏幕阅读器用来选择发音的,所以错误的值用错误的口音读出页面。删除视口标签,你的响应式 CSS 根据 980px 画布计算,所以你构建的移动设计以桌面宽度呈现并被缩小。

保存和打开 .html 文件

HTML 页面是一个纯文本文件,所以你可以在任何文本编辑器中创建一个。唯一重要的事情是名称:保存它以 .html 结尾。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My first page</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>This is my first web page.</p>
  </body>
</html>

保存为 index.html。然后在你的计算机上找到该文件并双击它:它在你的浏览器中打开并显示你的标题和段落。没有服务器要启动,也没有什么要安装。.html 结尾是告诉你的计算机以网页而不是代码墙打开它的信号。改变一个单词,保存,并刷新浏览器标签以查看更新。

HTML 文档是一个纯文本文件。在任何编辑器中写它并用 .html 扩展名保存。文件扩展名,名称中点后面的部分,是告诉操作系统和浏览器将文件视为 HTML 的内容。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My first page</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>This is my first web page.</p>
  </body>
</html>

保存为 index.html。名称 index 是一个值得尽早采用的约定:服务文件夹的 web 服务器默认查找 index.html,所以它成为你稍后构建的任何网站的主页。要立即查看它,双击文件或将其拖到浏览器窗口中。地址栏会显示类似 file:///Users/you/index.html 的内容,file:// 告诉你浏览器直接从磁盘读取而不是通过网络。编辑是一个循环:改变文件,保存,刷新标签。

HTML 文档是纯文本,浏览器只需要文件本身就能呈现它。用 .html 扩展名保存它,以便操作系统将其与浏览器关联,浏览器将其作为 HTML 而不是字面显示的文本来提供。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My first page</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>This is my first web page.</p>
  </body>
</html>

打开本地文件使用 file:// 协议:地址变成类似 file:///Users/you/index.html 的东西,浏览器直接从磁盘读取。这对单个页面来说是完美的,但它有一个上限。在 file:// 下,浏览器应用严格的 同源策略(限制页面可以从其他位置加载什么的安全规则),并将每个本地文件视为单独的来源,所以像 fetch 请求来加载数据和 ES 模块导入这样的东西被阻止了。依赖于通过 http:// 提供服务的功能在双击文件时将无法工作。

当你到达那个点时,修复是一个 本地开发服务器:一个小程序,在 http://localhost 上提供你的文件夹,这样浏览器会将其视为真实网站。编辑器扩展和单行命令为你完成这个。对于纯粹的第一页,尽管 file:// 是完全正确的:没有服务器,没有构建步骤,没有依赖。保存文件,双击,浏览器呈现它。保持 index.html 名称值得,因为服务目录的服务器默认返回 index.html,一旦你移动到 http://,它就成为入口点。

Juno保存和打开 .html 文件 网页是一个名称以 .html 结尾的文本文件。保存你的为 index.html,双击它,浏览器立即打开它,完全不用设置。要查看更改,保存文件并刷新标签。那个保存和刷新循环是构建页面的整个节奏。
Juno保存和打开 .html 文件 使用 .html 扩展名保存文件,浏览器知道将其呈现为页面;双击或拖入,地址栏显示 file://,这意味着它从磁盘读取。将其命名为 index.html,因为稍后服务器将其视为默认主页。然后这是一个循环:编辑,保存,刷新。
Juno保存和打开 .html 文件 双击在 file:// 上打开文件,这对于一个页面来说很好,但强制实行严格的同源策略,所以 fetch 和 ES 模块导入被阻止。当你遇到那堵墙时,运行本地开发服务器,这样页面通过 http://localhost 加载并表现得像真实网站。保持名称 index.html,因为那是服务器为文件夹返回的默认值。