前言
本章介绍一些浏览器与服务器中最常见的传输文档语言——超文本标记语言 (Hypertext Markup Language, HTML),我们主要学习 HTML 语言系列中最为严格的分支——XHTML(可扩展超文本标记语言),XHTML 具有与 HTML 相同的基本语法和元素,但在规则上更为严格。同时也将介绍一些简单的 XML 语言。
特别参考:
HTML 简介与编辑器
HTML 是一种标记语言,这意味着它用来标记(指示)文档中的各个部分,以指定文档在打印件或者显示器上的显示方式。HTML 因为早期开发时各个厂商的规范与标准不同,W3C(万维网联盟) 在 1999 发布了规范 HTML4.01。但 HTML4.01 存在两个根本性的问题。首先,它的语法规则不够严谨。所以 HTML 文档可能存在各种各样的形式,不同的浏览器会以不同方式解释它们。这导致 HTML 文档的编写十分随意。
于是,W3C 在 2000 年早期制定的 XHTML 1.0 标准重新定义了 HTML4.01,并遵循 XML 语法规则。
XHTML 文档旨在格式良好,这意味着它们符合特定的结构和语法规则。这确保了 XHTML 文档可以被 Web 浏览器和其他软件以一致的方式解析和解释。
使用 XHTML 的好处之一是可以更容易地为残障人士创建无障碍网站。通过遵循严格的语法规则,开发人员可以更轻松地创建符合无障碍指南的网页。
直到 2010 年,许多 Web 开发人员使用 XHTML 来编写文档,以便利用更严格的语法规则、标准的格式和验证工具,但是文档仍然使用 text/html, 并且浏览器仍然使用 HTML 解析器。然而,自 HTML5 推出以来,XHTML 在 Web 开发中变得不太流行,因为 HTML5 提供了许多相同的优点,同时更加灵活且能够容忍语法错误。
说了这么多,我们主要注意一些 XHTML 的规范,它主要的限制规范:
- 所有标签必须 小写。
- 所有标签 必须正确嵌套,即每个开始标签必须有一个相应的结束标签,并且它们不能重叠。
- 所有标签 必须关闭。即使某些标签在 HTML 中可以省略结束标签,但在 XHTML 中不行。
- 所有属性必须用引号括起来,单引号或双引号均可。属性名称和属性值都必须符合 XML 命名规范。
- 所有非空元素必须包含一个结束标签,或者采取自闭合形式。
- 所有空元素必须采取自闭合形式,即在标签末尾添加斜杠。
- 所有注释必须采用 HTML 的注释格式。
- 所有实体引用必须以 “&” 开头,以 “;” 结尾。
而学习 XHTML 其实和学习 HTML 基本无异,我们只是在 HTML 基础上使用 XHTML 标准。学习编写 HTML 的时候,我们应该 多试多练。
本篇中的编辑器使用 在线编辑器 进行演示,中国大陆可以使用 W3CSchool 提供的编辑器:
国际地区可以使用 Programiz 提供的:
其他建议搜索引擎查找。本地编辑器这里推荐使用 vscode、sublime、notepad— 之类的。
同时推荐一些 VSCode 前端方面的拓展,可以让你的 VSCode 更好用:
- Open-In-Browser:在快捷菜单中添加了在默认浏览器中打开的选项。
- HTML Boilerplate:生成干净的文档结构。
- Auto Rename Tag:自动重命名配对的 HTML 标记。
- Auto Close Tag:自动闭合 HTML/XML 标签。
- Code Spell Checker:自动检查代码语法。
- CSS Peek:可以追踪至样式表中 CSS 类和 ids 定义的地方。
基本 HTML
HTML 元素
在 HTML 中我们一般会把形如下列情况的 HTML 代码称为 HTML 标签 (tag):
- HTML 标签是由 尖括号 包围的关键词,比如
<html> - HTML 标签 通常 是 成对 出现的,比如
<b>和</b> - 标签对中的第一个标签是 开始标签,第二个标签是 结束标签
- 开始和结束标签也被称为 开放标签 和 闭合标签
而一个 HTML 元素 (Element) 是包含了 HTML 开始标签、结束标签 (结束标签可能没有) 与内容。
嵌套元素
在使用时可以把元素放到其他元素之中——这被称作 嵌套。
例如:
<p>My cat is <strong>very</strong> grumpy.</p>你需要确保元素被正确的嵌套:在上面的例子中我们先打开 p 元素,然后才打开 strong 元素,因此必须先将 strong 元素关闭,然后再去关闭 p 元素。
块级元素和内联元素
在 HTML 中有两种你需要知道的重要元素类别,块级元素和内联元素。
- 块级元素在页面中以块的形式展现。一个块级元素出现在它前面的内容之后的新行上。任何跟在块级元素后面的内容也会出现在新的行上。块级元素通常是页面上的结构元素。一个块级元素不会嵌套在一个内联元素里面,但它可能嵌套在另一个块级元素里面。
- 内联元素 通常出现在块级元素中并环绕文档内容的一小部分,而不是一整个段落或者一组内容。内联元素不会导致文本换行。它通常与文本一起使用,例如,
<a>创建一个超链接,<em>和<strong>等创建强调。 - 块级元素与内联元素最基本的区别就是块级元素自带结尾换行,而内联元素不自带换行。
空元素
不是所有元素都拥有开始标签、内容和结束标签。一些元素只有一个标签,通常用来在此元素所在位置插入/嵌入一些东西。这些元素被称为空元素。例如:
<img src="avatar.png" />我们插入了一张图片,<img> 元素为空元素,它不需要结束标签。在 HTML 标准中,无需在一个空元素的标签末尾添加 /,但在 XHTML 中应该使用这种形式。
属性
属性是 HTML 元素提供的附加信息。属性包含元素的额外信息,这些信息 不会出现 在实际的内容中。
属性一般 描述于开始标签,且总是以 属性名=“属性值” 的形式出现,比如:name=“value”。
必须存在一个空格 在属性和元素名称之间。如果一个元素具有多个属性,则每个属性之间必须由空格分隔。
属性和属性值对大小写不敏感,但 XHTML 中必须使用小写。例如:
<a href="https://www.example.com">Example</a>我们一般使用双引号包裹属性值,当然单引号也可以,看个人喜欢。但应该注意 单引号和双引号不能在一个属性值里面混用。
布尔属性
有时你会看到没有值的属性,用于标识一些内容,这也是完全可以接受的,这些属性被称为布尔属性。布尔属性只能有一个值,这个值一般与属性名称相同。例如:
<input type="text" disabled="disabled" />为了简便,一般写成:
<input type="text" disabled />基本 HTML 语法
一般来说,一个 HTML 应该包含下面四个部分:
- 文档声明:
<!DOCTYPE html> - html 标签对:
<html></html> - head 标签对:
<head></head> - body 标签对:
<body></body>
接下来我们来看一个简单的 HTML 代码作为示例。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head> <meta charset="utf-8" /> <title>HelloWorld</title></head><body> <p>Hello World!</p></body></html>文档声明
DOCTYPE 标签是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它 应该使用什么样的文档类型定义(DTD)来解析文档。文档类型是一个历史遗留问题,需要包含它才能使其他东西正常工作。
通常情况下,下列代码是最短的有效文档声明就可以了:
<!DOCTYPE html>而采用了严格的 XHTML 格式的文档应该写成这样:
<!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">HTML 元素
<html> 标签元素表示一个 HTML 文档的根(顶级元素),所以它也被称为根元素。所有其他元素必须是此元素的后代。
在 HTML 中我们一般不需要任何属性,而在 XHTML 中我们 必须 加上 xmlns 属性以指派文档的 XML 命名空间。
<html xmlns="http://www.w3.org/1999/xhtml">Head 元素
<head> 元素用于表示 头部内容,页面在浏览器加载后它的内容 不会在浏览器中显示,它的作用是保存页面的一些元数据。我们有一些元素可以包含在里面:
可用于
<head>元素内的元素有:<title>、<base>、<link>、<style>、<meta>、<script>、<noscript>
<meta> 元素表示那些不能由其他 HTML 元相关(meta-related)元素表示的元数据信息,通常有 name 属性和 charset 属性。name 属性表示文档级别元数据,而 charset 属性是一个字符集声明,告诉文档使用哪种字符编码。
<title> 元素设置了页面的标题,也就是出现在该页面加载的浏览器标签中的内容。当页面被加入书签时,页面标题也被用来描述该页面。
Body 元素
包含了你访问页面时所有显示在页面上的内容,包含文本、图片、视频、游戏、可播放音频轨道等等。内部其他的基本元素在之后会涉及。
HTML 特殊语义
空白
无论你在 HTML 元素的内容中使用多少空格(包括一个或多个空白字符或换行),当渲染这些代码的时候,HTML 解释器会将连续出现的空白字符减少只剩下 一个单独的空格符。例如:
<p>你 好 呀 。</p><p>你 好 呀 。</p>上述语句在 HTML 中都是一样的(第一句的展示),因为多个空格被消减为一个空格符。
如果我们不想让 HTML 忽略这些空格符,我们应该把它们包裹在 <pre> 标签中。
<pre> 元素表示预定义格式文本。在该元素中的文本 通常按照原文件中的编排,以等宽字体的形式展现出来,文本中的空白符(比如空格和换行符)都会显示出来。(紧跟在 <pre> 开始标签后的换行符也会被省略)
注释
HTML 拥有在代码中写注释的机制。浏览器会忽略注释,有效地使注释对用户来说不可见。
为了将一段 HTML 中的内容置为注释,你需要将其用特殊的记号 <!— 和 —> 包裹起来,比如:
<!-- <p>我在注释内!</p> -->实体引用
在 HTML 中,字符 <、>、”、’ 和 & 是特殊字符,因为它们是 HTML 语法自身的一部分。我们必须使用字符实体引用——表示字符的特殊编码,它们可以在需要转义特殊符号的情况下使用。
每个字符引用以符号 & 开始,以分号 (;) 结束。常见的有:
| 显示结果 | 描述 | 实体名称 | 实体编号 |
|---|---|---|---|
| 不间断空格 | |   | |
| < | 小于号 | < | < |
| > | 大于号 | > | > |
| & | 和号 | & | & |
| ” | 双引号 | " | " |
| ’ | 单引号 | ' | ' |
| × | 乘号 | × | × |
| ÷ | 除号 | ÷ | ÷ |
虽然 HTML 不区分大小写,但实体字符对大小写敏感。
补充一些原型:
- ** lt** : less than
- ** gt** : greater than
- ** amp** : ampersand
- ** quot** : quotation
基本 HTML 元素
基本文本处理——标题与段落
大部分结构化文本由标题和段落组成。在 HTML 中,每个段落是通过 <p> 元素标签进行定义的,例如:
<p>我是一个段落。</p>每个标题 (Heading) 都必须被包裹在一个标题元素中:
<h1>我是文章的标题</h1>一共有六种标题元素标签——h1、h2、h3、h4、h5 和 h6。每个元素代表文档中不同级别的内容:<h1> 表示主标题,<h2> 表示二级子标题,<h3> 表示三级子标题等等。
<!DOCTYPE html><html> <head> <title>Headings</title> </head><body> <h1>Heading 1</h1> <h2>Heading 2</h2> <h3>Heading 3</h3> <h4>Heading 4</h4> <h5>Heading 5</h5> <h6>Heading 6</h6> <p>The default paragraph text.</p></body></html>建议:
- 最好只对每个页面使用一次
<h1>。 - 请确保在层次结构中以正确的顺序使用标题。
- 减少标题层次的层数。
格式化文本——强调与样式
在表达中,我们有时会强调某些字,有可能是 ** 加粗** 也有 斜体。一般使用内联元素 <em> 表示斜体,用 <strong> 表示粗体。例如:
<p>你好,我是 <strong>田所浩二</strong>,24岁,是 <em>学生</em>。</p>除了上述外,之前还定义有 <b>、<i> 和 <u> 分别表示粗体、斜体和下划线。
因为 HTML 会自动将空格减少到 1 个,当我们在 <p> 元素中换行时也许只显示一个空格甚至不显示。当我们需要手动空行的时候,我们需要使用 <br> 元素。例如:
<p>话说天下大势,分久必合,合久必分。<br>周末七国分争,并入于秦。</p>当然,因为 <p> 元素是块元素,我们也可以通过多个 <p> 元素实现换行。
当我们在使用日期、化学方程式、和数学方程式时会偶尔使用上标和下标,我们可以使用 <sup> 和 <sub> 元素。例如:
<p> 咖啡因的化学方程式是 C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>。</p><p>如果 x<sup>2</sup> 的值为 9,那么 x 的值必为 3 或 -3。</p>HTML 还支持将时间和日期标记为可供机器识别的格式的 <time> 元素。例如:
<time datetime="2016-01-20">20 January 2016</time>超文本格式(链接)
我们通过将文本或其他内容包裹在 <a> 元素内,并给它一个包含网址的 href 属性来创建一个基本链接。例如:
<a href="https://hoyue.fun">hoyue</a>你可能要添加到你的链接的另一个属性是 title,用于鼠标悬停时显示补充信息:
<a href="https://hoyue.fun" title="View Hoyue Blog">hoyue</a>链接目标可使用相对/绝对路径:
- 绝对 URL:包含协议和域名,如
https://www.example.com/projects/index.html - 相对 URL:
- 指向当前目录:
HelloWorld.html或./HelloWorld.html - 指向子目录:
projects/index.html或./projects/index.html - 指向上级目录:
../pdfs/project-brief.pdf
- 指向当前目录:
示例(根目录 D:\WEB):
- 在
D:\WEB\HTML\hello.html跳转至D:\WEB\HTML\HelloWorld.html:
<a href="HelloWorld.html">Click here to jump.</a>或
<a href="D:\WEB\HTML\HelloWorld.html">Click here to jump.</a>- 给
hello.html添加 CSS:D:\WEB\HTML\CSS\style.css
<link rel="stylesheet" href="CSS/style.css" />或
<link rel="stylesheet" href="./CSS/style.css" />- 添加图片:
D:\WEB\Homework\avatar.jpg
<img src="../Homework/avatar.jpg" />内部锚点链接:给目标元素添加 id,用 #id 跳转:
<a href="#goto1">111</a><h1 id="goto1">Heading1</h1>邮箱链接 (mailto):
<a href="mailto:hoyue@hoyue.fun">向 hoyue 发邮件</a>下载链接(建议文件名):
<a href="https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=zh-CN" download="firefox-latest-64bit-installer.exe"> 下载最新的 Firefox 中文版 - Windows(64 位)</a>多媒体处理(图片)
用 <img> 引入图片,它是 空元素,最少有 src 属性。例如:
<img src="../Homework/avatar.jpg" alt="错误的时候才能看到我" />alt:图片无法显示或看不到时的文本描述width/height:尺寸(像素/百分比),建议用 CSS 控制title:鼠标悬停时的说明
<img src="images/dinosaur.jpg" alt="一只恐龙头部和躯干的骨架,它有一个巨大的头,长着锋利的牙齿。" width="400" height="341" title="A T-Rex on display in the Manchester University Museum" />(多图语义:HTML5 中可用 <figure> / <figcaption> 包裹)
表处理——列表
三种列表:
- 无序列表:
<ul>+<li> - 有序列表:
<ol>+<li> - 自定义列表:
<dl>+<dt>/<dd>
示例(无序):
<ul> <li>豆浆</li> <li>油条</li> <li>馒头</li> <li>包子</li></ul>示例(有序):
<ol> <li>豆浆</li> <li>油条</li> <li>馒头</li> <li>包子</li></ol>示例(自定义):
<dl> <dt>豆浆</dt> <dd>我早餐喜欢喝</dd> <dt>油条</dt> <dd>适合和豆浆一起吃</dd></dl>表处理——表格
基本结构:
<table>:表格<tr>:行<td>:单元格<th>:表头单元格
<table border="1"> <tr> <td>row 1, cell 1</td> <td>row 1, cell 2</td> </tr> <tr> <td>row 2, cell 1</td> <td>row 2, cell 2</td> </tr></table>合并单元格:
- 横向合并:
colspan - 纵向合并:
rowspan
<table border="1"> <tr> <th colspan="2">Header</th> </tr> <tr> <td rowspan="2">row 1/2, cell 1</td> <td>row 1, cell 2</td> </tr> <tr> <td>row 2, cell 2</td> </tr></table>大标题:<caption> 置于 <table> 内首位。
表处理——表单
<form> 的常用属性:
action:提交目标 URLmethod:HTTP 方法 (get/post)target:响应显示位置
表单 target 取值:
| 值 | 说明 |
|---|---|
_blank | 响应显示在新窗口或选项卡中 |
_self | 响应显示在当前窗口中 |
_parent | 响应显示在父框架中 |
_top | 响应显示在窗口的整个 body 中 |
| framename | 响应显示在命名的 iframe 中 |
表单常用元素:
<label>:标签说明<input>:单行输入/按钮等(空元素)<textarea>:多行文本输入<button>:按钮(可含 HTML 内容)
label 与 input 关联两种方式:
<label for="cheese">Do you like cheese?</label><input type="checkbox" name="cheese" id="cheese" />或
<label>Do you like peas? <input type="checkbox" name="peas" /></label><input> 的常见 type:
text:文本password:密码submit:提交reset:重置radio:单选checkbox:复选button:按钮
其它属性:
value:初始值name:控件名(提交时的键名)readonly:只读disabled:禁用size:宽度(字符数)maxlength:最大长度required:必填
<textarea>:
rows/cols指定大小- 内容写在开始/结束标签间(不使用 value)
<form action="" method="post"> <label for="story">Tell us your story:</label><br> <textarea id="story" name="story" rows="10" cols="50">It was a dark and stormy night...</textarea></form><button> 的 type:
submit:提交(默认)reset:重置button:普通按钮
下拉选择:
<form action="" method="post"> <select id="simple" name="simple"> <option>Banana</option> <option selected>Cherry</option> <option>Lemon</option> </select></form>分组
<fieldset> / <legend> 对表单控件进行分组及标题说明:
<form> <fieldset> <legend>health information</legend> height: <input type="text" /> weight: <input type="text" /> </fieldset>
<fieldset> <legend>Choose your favorite monster</legend> <input type="radio" id="kraken" name="monster" value="K" /> <label for="kraken">Kraken</label><br /> <input type="radio" id="sasquatch" name="monster" value="S" /> <label for="sasquatch">Sasquatch</label><br /> <input type="radio" id="mothman" name="monster" value="M" /> <label for="mothman">Mothman</label> </fieldset></form>网站基础构架
常见结构:
- 页眉(标题):网站主信息
- 导航栏:主要区段链接
- 主内容:页面主体
- 侧边栏:相关/辅助信息
- 页脚:版权/联系方式等
可用 <div>(块级,无语义)、<span>(内联,无语义)结合 class 灵活布局;样式布局建议用 CSS 实现。示例用表格实现简单主-侧布局(演示):
<table> <tr> <td style="vertical-align:top" width="70%"> <h2>Title</h2> <p>Context</p><br /> </td> <td style="vertical-align:top" width="30%"> <h2>Sidebar</h2> <ul> <li><b>Name:</b></li> <li><b>Age:</b></li> <li><b>Birth Place:</b></li> <li><b>Residence Place:</b></li> <li><b>Occupation:</b></li> </ul> </td> </tr></table>基本 XML
XML 语法与语义
XML 指可扩展标记语言(EXtensible Markup Language),XML 被设计为 传输和存储数据,其焦点是数据的内容。HTML 被设计用来显示数据,其焦点是数据的外观。
XML 仅仅是纯文本而已,并不能做任何事情。能读懂 XML 的应用程序可以有针对性地处理 XML 的标签。标签的功能性意义依赖于应用程序的特性。
示例(便签):
<note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body></note>XML 没有预定义的标签。HTML 中的标签是预定义的(如 <p>、<h1>)。
XML 的语法规则很简单:
- 必须有关闭标签:
错误:<p>This is a paragraph
正确:<p>This is a paragraph</p> - 大小写敏感:
错误:<Message>…</message>
正确:<message>…</message> - 正确嵌套:
正确:<b><i>…</i></b> - 属性值须加引号:
例如:<note date=“16/03/2023”> - 注释:
<!— This is a comment —> - 空格保留(不会折叠):
<p>Hello my name is David.</p>→ 输出中保留空格
- 实体引用(预定义 5 个):
<、>、&、'、"
| 实体 | 字符 | 含义 |
|---|---|---|
< | < | 小于 |
> | > | 大于 |
& | & | 和号 |
' | ’ | 单引号 |
" | ” | 引号 |
建议即便在 XML 中只有 < 和 & 必须转义,也养成统一使用实体引用的习惯。
文档类型定义(DTD)
DTD 定义合法的 XML 文档构建模块。它使用一系列合法的元素来定义文档的结构。
元素声明
基本格式:
<!ELEMENT 元素名称 类别>- 空元素:类别用
EMPTY
例如:<!ELEMENT br EMPTY> - 任意内容:类别用
ANY
例如:<!ELEMENT note ANY> - 子元素序列(逗号分隔:有序,必须按序出现)
例如:<!ELEMENT note (to,from,heading,body)> - 选一(竖线分隔:二选一,且不能同时出现)
例如:<!ELEMENT select (optgroup|option)> - 允许字符数据(PCDATA):
例如:
<!ELEMENT to (#PCDATA)> - 次数修饰符:
+:至少一次?:零次或一次*:零次或多次
示例(混合内容):
<!ELEMENT note (#PCDATA|to|from|header|message)*>示例(嵌套与选择):
<!ELEMENT note (to,from,header,(message|body))>属性声明
基本格式:
<!ATTLIST 元素名称 属性名称 属性类型 默认值>属性类型:
| 类型 | 描述 |
|---|---|
| CDATA | 字符数据 |
| (en1|en2|..) | 枚举列表中的一个值 |
| ID | 唯一 id |
| IDREF | 另外一个元素的 id |
| IDREFS | 其他 id 的列表 |
| NMTOKEN | 合法的 XML 名称 |
| NMTOKENS | 合法 XML 名称的列表 |
| ENTITY | 一个实体 |
| ENTITIES | 一个实体列表 |
| NOTATION | 一个符号的名称 |
| xml: | 预定义的 XML 值 |
默认值:
| 值 | 解释 |
|---|---|
| ”value” | 属性默认值 |
| #REQUIRED | 必需 |
| #IMPLIED | 非必需 |
| #FIXED “value” | 固定值 |
示例:
<!ATTLIST contact fax CDATA #IMPLIED><!ATTLIST person number CDATA #REQUIRED><!ATTLIST sender company CDATA #FIXED "Microsoft"><!ATTLIST payment type (check|cash) "cash">合法示例:
<contact fax="555-667788" /><person number="5677" /><sender company="Microsoft" /><payment type="check" /><payment type="cash" />实体声明
实体:用于定义引用普通文本或特殊字符的快捷方式的变量。
内部实体:
<!ENTITY writer "Hoyue">XML 中引用:&writer;
参数实体(DTD 级别,可被其他声明引用):
<!ENTITY % entity_name "entity_value">在 DTD 其他位置以 %entity_name; 形式被展开使用。
后记
本章介绍了 HTML 中最严格的分支——XHTML 的基本使用,以及 XML 语言的基本内容,便于我们编写文档。