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

什么是 HTML ​

你访问过的每一个网站,最初都是一份用 HTML 写成的纯文本文档。你在页面上看到的标题、段落、按钮、图片和链接,全都是用这一种语言描述出来的。

在给页面添加样式或让它动起来之前,你得先说清楚页面上有什么。这个描述工作,就是 HTML 在做的事。

页面就是结构化的文本 ​

HTML 的全称是 HyperText Markup Language(超文本标记语言)。这里的关键词是**标记(markup)**。

你拿一段普通文本,标出哪部分是标题,哪部分是段落,哪部分是链接。你不是在给计算机下达要执行的指令。你是在给内容贴标签,让浏览器知道每一块内容到底是什么。

想象一下你手动排版一份文档:把标题圈出来,给章节标题加下划线,给一张照片画个框。HTML 做的就是这类圈画和标注,只不过是用浏览器能读懂的方式。

html
<h1>Welcome</h1>
<p>This is a paragraph of text on my first web page.</p>

两行文字,两种结构:一个标题,一个段落。浏览器读取这些标签,把第一行显示得又大又粗,第二行显示为普通正文。

Juno页面就是结构化的文本 HTML 就是给页面各部分贴标签,好让浏览器知道它们是什么。你不是在写指令,而是在标记内容:这一块是标题,那一块是段落。这就是全部的核心思路,其他一切都建立在这个基础上。

如果你觉得这个答案简单得不像是真正的答案——它确实就是这么简单。我第一周一直在找那个"复杂的部分",结果根本没有。

Juno页面就是结构化的文本 这里有个专门的词叫声明式(declarative):你描述你想要的结构,浏览器负责搞清楚怎么把它呈现出来。这里没有逻辑,没有循环,没有变量。

这就是为什么 HTML 从通常意义上讲不算一门编程语言。它不计算任何东西,它只是组织内容。把它的职责在脑子里划清楚,CSS 和 JavaScript 就更容易归位了——因为一旦你发现自己在问"我要怎么用 HTML 实现 X",那通常就是信号,说明你已经不小心跑到另外两门语言的地盘上去了。

Juno页面就是结构化的文本 浏览器会把你的标记解析成一棵由对象组成的树,叫做 DOM,也就是文档对象模型(Document Object Model):这是页面在内存中活生生的表示形式。你写的源代码是输入,而 DOM 才是真正被渲染出来的东西,也是其他一切 Web 技术真正打交道的对象。

这个框架能解释 HTML 很多行为背后的原因。解析过程被特意设计得非常宽容,所以少了一个闭合标签,或者标签嵌套错了,几乎不会报错。解析器会按照一套既定的恢复算法继续走下去,硬是搭出一棵有效的树来——正因如此,二十年来那些不完美的页面才一直能正常运行。

这也意味着"能渲染出来"并不能说明代码写得对。浏览器几乎能从任何东西里构建出一个 DOM,所以结构是否规范要靠你自己把关,而不是靠解析器。这就是一个页面能不能撑到第二个开发者手里的区别所在。

元素、标签和属性 ​

HTML 大部分是由**元素(element)**组成的。一个元素通常有一个开始标签、一些内容,和一个结束标签:

html
<p>Hello there.</p>

<p> 是开始标签,</p> 是结束标签(注意那个斜杠),中间的 "Hello there." 是内容。三者合在一起构成一个段落元素。标签是标签,内容才是访问者真正会读到的东西。

你还可以用**属性(attribute)**给标签附加额外信息,写法是在开始标签里加上 name="value" 这样的键值对。链接需要知道要跳转到哪里,你就用 href 来告诉它:

html
<a href="https://scrimba.com">Visit Scrimba</a>

有些元素根本没有内容,所以也没有结束标签。这些就是**空元素(void elements)**,你会经常碰到它们:<img>、<br>、<input>、<hr>。它们需要的一切信息都放在属性里,所以没什么内容要包裹,也没什么需要闭合的。

html
<img src="golden-retriever.jpg" alt="A golden retriever sitting in tall grass">
Juno元素、标签和属性 一个元素就是开始标签、一些内容,加上结束标签,就像 <p>...</p> 这样。属性写在开始标签里,用来补充细节,比如一个链接指向哪里。

请不要试图把每一个标签都背下来。标签有一百多个,没有人能把它们全都记在脑子里。你会慢慢掌握用得上的那一小部分,剩下的就一直查,跟我们其他人一样。

Juno元素、标签和属性 现在有必要把这几个词的定义钉死,因为很多人用得很随意。**标签(tag)**是你打出来的文本,比如 <p> 或者 </p>。**元素(element)**是解析器最终产出的整个东西:标签、它的内容,以及所有子级内容。**属性(attribute)**则是用来配置它的。

等你哪天在评审时读别人写的标记,"标签"和"元素"就不能再混着用了。空元素最容易让人绊一下:没有内容,没有结束标签,一切信息都在属性里。

Juno元素、标签和属性 标签、元素、属性是三个不同的概念,把它们分清楚,等你第一次快速读一段报错堆栈信息时就会体会到好处。

在这一层,属性的值全都是字符串——毫无例外,包括数字和布尔值。disabled 是一个布尔属性,光是它出现在标签里就代表 true;而 <input value="5"> 里存的是字符串 "5",直到有代码把它当数字读取为止。所以等你第一次在 JavaScript 里发现该做加法的地方却变成了字符串拼接,你就已经知道原因了。

有时你会在 <br /> 后面看到那个多余的斜杠,它是可选的,实际上什么作用都没有,是 XHTML 时代留下来的老习惯。不用管它,谁跟你说不一样都别信。

HTML、CSS 和 JavaScript 如何分工 ​

一个完整的网页通常由三种语言搭建而成,每一种只负责一件事:

  • HTML 负责结构:标题、文字、图片和按钮。
  • CSS 负责样式:颜色、字体、间距和布局。
  • JavaScript 负责行为:点击、输入或滚动时会发生什么。

这里有个我一直用来打比方的画面。HTML 是一座房子的墙和房间,CSS 是油漆和家具,JavaScript 则是让东西通上电、能开关的那部分。

你先学墙,是因为在结构还不存在之前,根本没有什么可以刷漆或接电的。

尽早养成把这三者分开的习惯,很值得。当你的内容放在 HTML 里、样式放在 CSS 里、行为放在 JavaScript 里,你就可以单独修改其中任何一个,而不会影响另外两个。

JunoHTML、CSS 和 JavaScript 如何分工 三种语言,三件事:HTML 是结构,CSS 是样式,JavaScript 是行为。你从 HTML 开始学,是因为其他一切都建立在它之上。

墙一旦立起来,油漆和电线就有地方可去了。而且光靠这一层,你就能搭出一个真实、有用的页面——等你觉得另外两门语言离你很远的时候,知道这一点会挺安心的。

JunoHTML、CSS 和 JavaScript 如何分工 这种分层是有意为之的。HTML 提供结构和含义,CSS 读取这个结构并描述它该长什么样,JavaScript 读取并根据事件去改变它。

尽量克制住在 HTML 里"假装"布局的冲动:比如用一堆连续的 <br> 标签来撑间距,或者用一个空的 <div> 把东西往下推。一开始看着能用,但很快就会变得很麻烦。现在养成好习惯成本很低,等到代码已经上线了再想改就贵得多。

JunoHTML、CSS 和 JavaScript 如何分工 这种分离不只是为了整洁,它是页面能不能扛得住意外的关键。一个含义完全由 HTML 承载的页面会优雅降级:CSS 加载失败,内容依然可读、有序;JavaScript 被禁用或者报错,核心内容依然摆在那里。这就是**渐进增强(progressive enhancement)**这个理念的全部意义,它撑了二十年,而很多喊得更响的想法都没撑下来。

这也是无障碍和性能方面的考量。辅助技术读取的是 DOM,所以承载在 HTML 里的含义能被它读到,而靠 CSS 假装出来的、或者由 JavaScript 后期注入的内容往往读不到。HTML 也是浏览器能最先解析和绘制出来的东西,等着 JavaScript 一来一回才出现的内容,就是让用户干等的内容。

不确定某个东西该放在哪一层时,就从最底层开始,只有单靠结构撑不住的时候,才往上爬一层。我见过的那些后悔这个决定的团队,后悔的方向都是一样的。

第一次完整看一个页面 ​

下面是一个完整的网页,很小但是真实存在的那种。接下来几章你会好好认识它的每一部分,所以现在先别纠结细节。眼下只需要注意到,它全都是由你已经见过的标签和属性搭出来的:

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

从上往下读。第一行告诉浏览器这是一份现代 HTML 页面。<html> 把所有内容都包裹在里面。<head> 存放页面标题这类幕后信息,<body> 存放你实际看到的内容。

前面出现过的标题和段落都放在 body 里面,因为它们是给访问者看的内容。这种划分——页面的信息和页面的内容分开——是每份文档都要做的第一个结构性决定。

下一章讲的是你的第一个 HTML 页面,会把这个骨架逐行拆开来讲。

Juno第一次完整看一个页面 每个页面都是从同一个小骨架搭起来的:一个文档类型声明,然后是 <html> 包着一个 <head> 和一个 <body>。head 里是幕后信息,body 里是大家看到的内容。

下一章会把这个骨架好好拆开讲清楚,所以现在只需要大概看一眼就够了。第一次看会觉得内容不少,看到第五次差不多就没什么感觉了。

Juno第一次完整看一个页面 核心的划分是:元数据放在 head 里,可见内容放在 body 里。你写的几乎每一份文档都是从这个形状开始的,所以值得一看就能认出来。

你的编辑器会帮你自动生成这个骨架,但当骨架出问题的时候,能看出缺了什么,还是很值得培养的能力。

Juno第一次完整看一个页面 这个骨架的顺序是有原因的。<meta charset> 放在 head 的最前面,是为了让解析器在读取文档剩余部分的字节之前,先知道该怎么解码它们;<html> 上的 lang 则是告诉屏幕阅读器和翻译工具,它们面对的是哪种语言。

这里没有一个字是多余的。head 配置了这份文档要怎么被解析和理解,而 body 则是这份配置所应用的内容。理解了这一点,你才能有信心去修改它——这一点很重要,因为生产环境里出乎意料多的 bug,其实都悄悄藏在 head 里。