定义
超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用来结构化 Web 网页及其内容的标记语言。HTML 提供了网页的骨架和语义结构,与 CSS(样式)和 JavaScript(行为)共同构成了现代 Web 开发的基础技术栈。
1. 基本概念
1.1 什么是 HTML
HTML 不是一门编程语言,而是一种用于定义内容结构的标记语言(Markup Language)。HTML 由一系列的元素(elements)组成,这些元素可以用来包围不同部分的内容,使其以某种方式呈现或者工作。
核心特点:
- 标记语言:使用标签(tags)来描述文档结构
- 超文本:支持链接到其他文档或资源
- 平台无关:可在任何设备和浏览器上运行
- 开放标准:由 W3C 维护的开放标准
<p>My cat is very grumpy</p>1.2 HTML 发展历程
- HTML 1.0 (1991):最初的 HTML 规范,包含基本的标签
- HTML 2.0 (1995):标准化版本,增加了表单元素
- HTML 3.2 (1997):增加了表格、脚本和更多样式选项
- HTML 4.01 (1999):严格的规范,引入了 CSS
- XHTML 1.0 (2000):基于 XML 的更严格的 HTML 版本
- HTML5 (2014):当前主要版本,支持多媒体和语义化标签
- HTML5.1/5.2 (2016-2017):持续改进和新特性
- HTML5.3 (2023):最新标准,包含更多 Web 组件特性
1.3 HTML 元素详解
1.3.1 元素组成结构
一个完整的 HTML 元素由以下几个部分组成:
<p class="editor-note">My cat is very grumpy</p>主要组成部分:
- 开始标签(Opening Tag):
<p class="editor-note">- 元素名称:
p - 属性:
class="editor-note"
- 元素名称:
- 内容(Content):
My cat is very grumpy - 结束标签(Closing Tag):
</p>
1.3.2 标签和元素的区别
- 标签(Tag):只是
<p>或</p>这样的标记 - 元素(Element):开始标签 + 内容 + 结束标签的完整组合
1.3.3 属性(Attributes)
属性为元素提供额外信息,常见的属性类型:
<!-- 基础属性 -->
<div id="header" class="main-header">...</div>
<!-- 事件属性 -->
<button onclick="alert('Hello!')">点击我</button>
<!-- 数据属性 -->
<div data-user-id="123" data-role="admin">...</div>
<!-- ARIA 属性(无障碍) -->
<button aria-label="关闭对话框" aria-expanded="false">×</button>
<!-- 自定义属性(data-*) -->
<div data-component="user-card" data-variant="dark">...</div>属性命名规范:
- 使用小写字母
- 多词属性使用连字符分隔:
data-user-id - 布尔属性可以省略值:
<input disabled>等同于<input disabled="disabled">
1.4 空元素(Void Elements)
不包含任何内容的元素称为空元素或自闭合元素。这些元素只有一个开始标签,没有结束标签。
<!-- 常见空元素 -->
<img src="images/firefox-icon.png" alt="My test image">
<br>
<hr>
<input type="text" name="username">
<link rel="stylesheet" href="styles.css">
<meta charset="utf-8">
<!-- HTML5 空元素可以省略斜杠 -->
<img src="image.jpg" alt="description">
<img src="image.jpg" alt="description" />常用空元素列表:
<img>- 图像<br>- 换行<hr>- 水平分割线<input>- 输入框<link>- 外部资源链接<meta>- 元数据<source>- 媒体源<track>- 文本轨道<area>- 图像映射区域<base>- 基础 URL<col>- 表格列<embed>- 嵌入内容<param>- 参数<wbr>- 单词换行机会<keygen>- 密钥对生成器(已废弃)
1.5 嵌套元素
HTML 元素可以嵌套在其他元素内部,形成层次结构:
<div class="article">
<h1>文章标题</h1>
<p>这是第一段文字,包含 <em>强调</em> 和 <strong>加粗</strong> 文本。</p>
<div class="meta">
<span class="author">作者:张三</span>
<span class="date">2023-01-01</span>
</div>
</div>嵌套规则:
- 块级元素可以包含块级和行内元素
- 行内元素通常只能包含其他行内元素或文本
- 某些元素有特定的嵌套限制(如
<p>不能包含其他块级元素) - 必须正确闭合标签,避免交叉嵌套
2. HTML文档详解
2.1 完整 HTML 文档结构
一个完整的 HTML5 文档包含以下基本结构:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<!-- 基础元数据 -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- SEO 优化 -->
<title>网页标题 - 网站名称</title>
<meta name="description" content="网页描述,用于搜索引擎结果展示">
<meta name="keywords" content="关键词1,关键词2,关键词3">
<meta name="author" content="作者名称">
<!-- 外部资源 -->
<link rel="stylesheet" href="styles.css">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<!-- Open Graph 标签 -->
<meta property="og:title" content="网页标题">
<meta property="og:description" content="网页描述">
<meta property="og:image" content="https://example.com/image.jpg">
<meta property="og:url" content="https://example.com/page">
<meta property="og:type" content="website">
<!-- 其他头部信息 -->
<meta name="robots" content="index,follow">
</head>
<body>
<!-- 页面可见内容 -->
<header>
<h1>网站标题</h1>
<nav>
<ul>
<li><a href="#home">首页</a></li>
<li><a href="#about">关于</a></li>
<li><a href="#contact">联系</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h2>文章标题</h2>
<p>文章内容...</p>
</article>
</main>
<footer>
<p>© 2023 版权信息</p>
</footer>
<!-- JavaScript 文件 -->
<script src="script.js"></script>
</body>
</html>2.1.1 文档声明
<!DOCTYPE html>:HTML5 的文档类型声明,告诉浏览器使用 HTML5 标准解析页面
2.1.2 根元素
<html lang="zh-CN">:根元素,包含整个页面内容lang属性指定页面语言,有助于无障碍访问和搜索引擎优化
2.1.3 头部元素(<head>)
头部元素包含页面元数据,对用户不可见:
基础元数据:
<meta charset="UTF-8"> <!-- 字符编码 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 响应式视口 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- IE 兼容模式 -->SEO 优化标签:
<title>页面标题 - 网站名称</title>
<meta name="description" content="页面描述(建议50-160字符)">
<meta name="keywords" content="关键词1,关键词2,关键词3">
<meta name="author" content="作者名称">
<meta name="robots" content="index,follow">外部资源链接:
<link rel="stylesheet" href="styles.css">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://cdn.example.com">2.1.4 主体元素(<body>)
主体元素包含用户可见的所有内容,建议使用语义化标签:
<body>
<!-- 头部区域 -->
<header>...</header>
<!-- 导航区域 -->
<nav>...</nav>
<!-- 主要内容区域 -->
<main>
<article>...</article>
<aside>...</aside>
</main>
<!-- 页脚区域 -->
<footer>...</footer>
</body>2.2 图像(Images)
图像是网页中重要的视觉元素,HTML 提供了多种图像相关的标签和属性。
2.2.1 基础图像标签
<img src="images/firefox-icon.png" alt="Firefox 浏览器图标" width="32" height="32">主要属性:
src:图像路径(必需)alt:替代文本(必需,用于无障碍访问)width、height:图像尺寸(建议设置,避免页面布局抖动)title:鼠标悬停时显示的提示文本loading="lazy":延迟加载,提升性能decoding="async":异步解码,不影响其他内容渲染
2.2.2 响应式图像
<!-- 使用 srcset 属性 -->
<img src="image-small.jpg"
srcset="image-small.jpg 480w,
image-medium.jpg 768w,
image-large.jpg 1024w"
sizes="(max-width: 480px) 480px,
(max-width: 768px) 768px,
1024px"
alt="响应式图像示例">
<!-- 使用 picture 元素 -->
<picture>
<source media="(max-width: 600px)" srcset="image-mobile.webp" type="image/webp">
<source media="(max-width: 600px)" srcset="image-mobile.jpg" type="image/jpeg">
<source srcset="image-desktop.webp" type="image/webp">
<img src="image-desktop.jpg" alt="图片描述">
</picture>2.2.3 图像格式选择
<!-- WebP 格式(现代浏览器,体积小) -->
<img src="image.webp" alt="描述">
<!-- 传统格式(兼容性好) -->
<img src="image.jpg" alt="描述"> <!-- 照片类图片 -->
<img src="image.png" alt="描述"> <!-- 透明背景、图标类图片 -->
<!-- SVG 矢量图(可缩放) -->
<img src="icon.svg" alt="图标描述">
<!-- SVG 直接嵌入(无需额外请求) -->
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z"/>
</svg>2.2.4 图像最佳实践
- 始终提供 alt 属性,即使是空的 alt=""
- 设置 width 和 height,避免布局抖动
- 使用合适的图像格式,平衡质量和文件大小
- 实施延迟加载,提升页面性能
- 提供多种格式,确保兼容性
- 优化图像大小,使用压缩工具
2.3 链接(Links)
链接是 HTML 的核心特性,使网页能够相互连接形成网络。
2.3.1 基础链接
<!-- 外部链接 -->
<a href="https://www.mozilla.org/zh-CN/about/manifesto/">Mozilla Manifesto</a>
<!-- 内部链接(相对路径) -->
<a href="/about.html">关于我们</a>
<a href="#section1">跳转到第一部分</a>
<!-- 邮件链接 -->
<a href="mailto:someone@example.com?subject=Hello&body=消息内容">发送邮件</a>
<!-- 电话链接(移动端) -->
<a href="tel:+8613800138000">拨打电话</a>2.3.2 链接属性
<!-- 在新标签页打开 -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">外部链接</a>
<!-- 下载链接 -->
<a href="/files/document.pdf" download="report.pdf">下载 PDF</a>
<!-- 带提示的链接 -->
<a href="https://example.com" title="访问示例网站">示例网站</a>
<!-- 安全属性 -->
<a href="https://external.com" rel="noopener noreferrer nofollow">外部链接</a>2.3.3 链接状态和伪类
<style>
/* 不同链接状态 */
a:link { color: blue; } /* 未访问 */
a:visited { color: purple; } /* 已访问 */
a:hover { color: red; } /* 鼠标悬停 */
a:focus { color: orange; } /* 焦点状态 */
a:active { color: darkred; } /* 点击时 */
</style>2.3 标题(Heading)
标题元素可用于指定内容的标题和子标题。就像一本书的书名、每章的大标题、小标题,等。HTML 文档也是一样。HTML 包括六个级别的标题, <h1> (en-US)–<h6> (en-US) ,一般最多用到 3-4 级标题。
<h1>主标题</h1>
<h2>顶层标题</h2>
<h3>子标题</h3>
<h4>次子标题</h4>2.4 段落(Paragraph)
<p>元素是用来指定段落的。通常用于指定常规的文本内容:
<p>这是一个段落</p>2.5 列表(Lists)
列表是网页中常用的内容组织方式,HTML 提供了多种列表类型。
2.5.1 无序列表(Unordered List)
项目顺序不重要时的列表,使用 <ul> 元素:
<ul>
<li>苹果</li>
<li>香蕉</li>
<li>橙子</li>
</ul>
<!-- 嵌套列表 -->
<ul>
<li>水果
<ul>
<li>苹果</li>
<li>香蕉</li>
</ul>
</li>
<li>蔬菜
<ul>
<li>胡萝卜</li>
<li>白菜</li>
</ul>
</li>
</ul>2.5.2 有序列表(Ordered List)
项目顺序重要时的列表,使用 <ol> 元素:
<ol>
<li>第一步:准备材料</li>
<li>第二步:开始烹饪</li>
<li>第三步:享用美食</li>
</ol>
<!-- 自定义起始数字 -->
<ol start="5">
<li>第五个项目</li>
<li>第六个项目</li>
</ol>
<!-- 反序列表 -->
<ol reversed>
<li>最后一个项目</li>
<li>倒数第二个项目</li>
<li>倒数第三个项目</li>
</ol>
<!-- 不同类型 -->
<ol type="A">
<li>第一个项目</li>
<li>第二个项目</li>
</ol>2.5.3 描述列表(Description List)
用于术语及其描述的列表,使用 <dl>、<dt>、<dd> 元素:
<dl>
<dt>HTML</dt>
<dd>超文本标记语言,用于创建网页的标准标记语言</dd>
<dt>CSS</dt>
<dd>层叠样式表,用于设置网页的样式和布局</dd>
<dt>JavaScript</dt>
<dd>一种编程语言,用于实现网页的交互功能</dd>
</dl>
<!-- 多个描述 -->
<dl>
<dt>水果</dt>
<dd>富含维生素和纤维的健康食品</dd>
<dd>建议每天食用适量水果</dd>
<dt>蔬菜</dt>
<dd>提供矿物质和膳食纤维</dd>
</dl>2.5.4 列表样式定制
<style>
/* 自定义列表标记 */
ul.custom {
list-style-type: none; /* 移除默认标记 */
padding-left: 0;
}
ul.custom li {
position: relative;
padding-left: 20px;
}
ul.custom li::before {
content: "→"; /* 自定义标记 */
position: absolute;
left: 0;
color: #ff6b6b;
}
/* 罗马数字列表 */
ol.roman {
list-style-type: upper-roman;
}
/* 方形标记列表 */
ul.square {
list-style-type: square;
}
</style>2.6 表格(Tables)
表格用于展示结构化的数据,适合二维关系的信息展示。
2.6.1 基础表格结构
<table>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>职业</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>28</td>
<td>工程师</td>
</tr>
<tr>
<td>李四</td>
<td>32</td>
<td>设计师</td>
</tr>
</tbody>
</table>2.6.2 完整表格结构
<table>
<caption>员工信息表</caption>
<colgroup>
<col class="name-column">
<col class="age-column">
<col class="job-column">
</colgroup>
<thead>
<tr>
<th scope="col">姓名</th>
<th scope="col">年龄</th>
<th scope="col">职业</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">张三</th>
<td>28</td>
<td>工程师</td>
</tr>
<tr>
<th scope="row">李四</th>
<td>32</td>
<td>设计师</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">总计</th>
<td colspan="2">2名员工</td>
</tr>
</tfoot>
</table>2.6.3 表格高级功能
<table class="responsive-table">
<caption>复杂表格示例</caption>
<!-- 合并单元格 -->
<tr>
<td rowspan="2">部门</td>
<td>前端组</td>
<td>5人</td>
</tr>
<tr>
<td>后端组</td>
<td>3人</td>
</tr>
<!-- 合并列 -->
<tr>
<td>备注</td>
<td colspan="2">共8名开发人员</td>
</tr>
</table>
<style>
/* 响应式表格 */
.responsive-table {
width: 100%;
border-collapse: collapse;
}
.responsive-table th,
.responsive-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.responsive-table th {
background-color: #f2f2f2;
font-weight: bold;
}
</style>2.7 表单(Forms)
表单用于收集用户输入,是 Web 应用中最重要的交互元素之一。
2.7.1 基础表单结构
<form action="/submit" method="POST" enctype="multipart/form-data">
<!-- 表单字段 -->
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password" required minlength="8">
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<button type="submit">提交</button>
<button type="reset">重置</button>
</div>
</form>2.7.2 输入类型详解
<!-- 文本输入 -->
<input type="text" placeholder="请输入文本">
<input type="password" placeholder="密码">
<input type="email" placeholder="邮箱地址">
<input type="url" placeholder="网址">
<input type="tel" placeholder="电话号码">
<!-- 数值输入 -->
<input type="number" min="1" max="100" step="1" value="50">
<input type="range" min="0" max="100" step="5" value="50">
<!-- 日期时间 -->
<input type="date" min="2023-01-01" max="2023-12-31">
<input type="time" value="09:00">
<input type="datetime-local">
<input type="month">
<input type="week">
<!-- 选择输入 -->
<input type="checkbox" name="agree" id="agree">
<input type="radio" name="gender" value="male" id="male">
<input type="radio" name="gender" value="female" id="female">
<!-- 文件上传 -->
<input type="file" accept=".jpg,.png,.pdf" multiple>
<!-- 特殊输入 -->
<input type="color" value="#ff6b6b">
<input type="search" placeholder="搜索...">
<input type="hidden" name="csrf_token" value="abc123">2.7.3 下拉选择
<!-- 基础选择框 -->
<select name="city" id="city">
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
</select>
<!-- 分组选择框 -->
<select name="department">
<optgroup label="技术部门">
<option value="frontend">前端组</option>
<option value="backend">后端组</option>
<option value="qa">测试组</option>
</optgroup>
<optgroup label="业务部门">
<option value="sales">销售组</option>
<option value="marketing">市场组</option>
</optgroup>
</select>
<!-- 多选下拉框 -->
<select name="skills" multiple size="4">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="javascript">JavaScript</option>
<option value="react">React</option>
<option value="vue">Vue</option>
</select>2.7.4 文本区域
<textarea name="message" rows="4" cols="50" placeholder="请输入留言..." maxlength="500"></textarea>
<!-- 带字符计数的文本区域 -->
<div class="char-counter">
<textarea name="bio" rows="3" maxlength="200" placeholder="个人简介..."></textarea>
<span class="counter">0/200</span>
</div>2.7.5 表单验证
<form novalidate>
<!-- HTML5 验证属性 -->
<input type="text" required minlength="2" maxlength="20" pattern="[A-Za-z]{2,20}"
title="请输入2-20个字母">
<input type="email" required placeholder="example@domain.com">
<input type="number" min="18" max="100" required>
<!-- 自定义验证消息 -->
<input type="text" id="custom-input" required>
<div class="error-message" id="custom-error"></div>
</form>
<script>
const input = document.getElementById('custom-input');
const errorMessage = document.getElementById('custom-error');
input.addEventListener('invalid', (e) => {
e.preventDefault();
errorMessage.textContent = '请输入正确的信息';
});
</script>3. HTML5 新特性
3.1 HTML5 概述
HTML5 是最新的 HTML 标准,带来了革命性的改进:
- 丰富的内容支持:无需插件即可承载丰富的 Web 内容
- 语义化改进:新的语义化元素提升文档结构
- 多媒体支持:原生音视频支持
- 图形能力:Canvas 2D、WebGL、SVG
- 数据存储:本地存储、会话存储、IndexedDB
- 跨平台性:在 PC、平板、手机、电视等多种设备上运行
- 性能提升:更快的解析和渲染
- API 丰富:地理定位、Web Sockets、Web Workers 等
3.2 新增语义化元素
3.2.1 文档结构元素
<!DOCTYPE html>
<html lang="zh-CN">
<body>
<header>
<h1>网站标题</h1>
<nav>主导航</nav>
</header>
<main>
<article>
<header>
<h2>文章标题</h2>
<time datetime="2023-01-01">2023年1月1日</time>
</header>
<section>
<h3>第一节</h3>
<p>第一部分内容...</p>
</section>
<section>
<h3>第二节</h3>
<p>第二部分内容...</p>
</section>
</article>
<aside>
<h3>相关链接</h3>
<ul>
<li><a href="#">链接1</a></li>
<li><a href="#">链接2</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2023 版权信息</p>
</footer>
</body>
</html>3.2.2 文本级语义元素
<p>
这是一段包含<mark>高亮文本</mark>的段落。
我们可以使用<time datetime="2023-12-25">圣诞节</time>来标记时间。
<abbr title="World Wide Web">WWW</abbr>是万维网的缩写。
<bdo dir="rtl">这段文字会从右向左显示</bdo>
</p>
<figure>
<img src="chart.png" alt="销售图表">
<figcaption>图1:2023年销售数据</figcaption>
</figure>3.3 多媒体支持
3.3.1 音频(Audio)
<!-- 基础音频 -->
<audio controls>
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
<p>您的浏览器不支持音频播放。</p>
</audio>
<!-- 带字幕的音频 -->
<audio controls>
<source src="audio.mp3" type="audio/mpeg">
<track src="subtitles.vtt" kind="subtitles" srclang="zh-CN" label="中文字幕">
</audio>
<!-- 自动播放音频(注意用户体验) -->
<audio autoplay loop muted>
<source src="background.mp3" type="audio/mpeg">
</audio>3.3.2 视频(Video)
<!-- 基础视频 -->
<video controls width="640" height="360" poster="poster.jpg">
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<p>您的浏览器不支持视频播放。</p>
</video>
<!-- 响应式视频 -->
<div class="video-container">
<video controls>
<source src="video.mp4" type="video/mp4">
</video>
</div>
<style>
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 比例 */
height: 0;
overflow: hidden;
}
.video-container video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>3.4 Canvas 绘图
<canvas id="myCanvas" width="400" height="300">
您的浏览器不支持 Canvas。
</canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 绘制矩形
ctx.fillStyle = '#ff6b6b';
ctx.fillRect(10, 10, 100, 50);
// 绘制圆形
ctx.beginPath();
ctx.arc(200, 100, 50, 0, 2 * Math.PI);
ctx.fillStyle = '#4ecdc4';
ctx.fill();
// 绘制文字
ctx.font = '20px Arial';
ctx.fillStyle = '#333';
ctx.fillText('Hello Canvas!', 100, 200);
</script>3.5 SVG 矢量图形
<!-- 内联 SVG -->
<svg width="200" height="200" viewBox="0 0 200 200">
<circle cx="100" cy="100" r="50" fill="#ff6b6b" />
<rect x="50" y="50" width="100" height="100" fill="#4ecdc4" opacity="0.5" />
<text x="100" y="150" text-anchor="middle" font-family="Arial" font-size="16" fill="#333">
SVG 文本
</text>
</svg>3.6 数据存储 API
<script>
// LocalStorage 示例
localStorage.setItem('username', '张三');
localStorage.setItem('preferences', JSON.stringify({
theme: 'dark',
language: 'zh-CN'
}));
const username = localStorage.getItem('username');
const preferences = JSON.parse(localStorage.getItem('preferences'));
// SessionStorage 示例(页面关闭后清除)
sessionStorage.setItem('tempData', '临时数据');
const tempData = sessionStorage.getItem('tempData');
</script>3.7 新的表单元素
<!-- 新的输入类型 -->
<input type="date" min="2023-01-01" max="2023-12-31">
<input type="time" step="60">
<input type="datetime-local">
<input type="month">
<input type="week">
<input type="color" value="#ff6b6b">
<input type="range" min="0" max="100" value="50">
<input type="number" step="0.1">
<!-- 新的表单元素 -->
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
</datalist>
<input list="browsers" placeholder="选择浏览器">
<progress value="70" max="100">70%</progress>
<meter value="6" min="0" max="10" low="3" high="8">6/10</meter>3.8 其他重要特性
- 地理定位 API:获取用户地理位置
- Web Workers:后台线程处理
- Web Sockets:实时双向通信
- 拖放 API:原生拖放功能
- 历史 API:浏览器历史记录管理
- 通知 API:系统通知
- 全屏 API:全屏显示
4. HTML 语义化
4.1 语义化定义
HTML 语义化是指根据内容的结构化选择合适的标签,使得:
- 内容语义化:使用能够表达内容含义的标签
- 代码语义化:编写清晰、可读、可维护的代码
<!-- 不语义化的代码 -->
<div class="header">...</div>
<div class="content">
<div class="article">
<div class="title">文章标题</div>
<div class="meta">发布时间:2023-01-01</div>
<div class="text">文章内容...</div>
</div>
</div>
<div class="footer">...</div>
<!-- 语义化的代码 -->
<header>...</header>
<main>
<article>
<h1>文章标题</h1>
<time datetime="2023-01-01">发布时间:2023-01-01</time>
<p>文章内容...</p>
</article>
</main>
<footer>...</footer>4.2 语义化原则
4.2.1 语义化标签选择指南
<!-- 文档结构语义化 -->
<header> <!-- 页面或区域头部 -->
<nav> <!-- 导航链接集合 -->
<main> <!-- 主要内容区域 -->
<article> <!-- 独立的内容单元 -->
<section> <!-- 内容的章节或部分 -->
<aside> <!-- 侧边栏或相关内容 -->
<footer> <!-- 页面或区域底部 -->
<!-- 文本内容语义化 -->
<h1>-<h6> <!-- 标题层级,重要性递减 -->
<p> <!-- 段落文本 -->
<strong> <!-- 重要内容,语气强调 -->
<em> <!-- 强调内容,语气改变 -->
<mark> <!-- 高亮标记的文本 -->
<blockquote> <!-- 长段引用 -->
<q> <!-- 短句引用 -->
<code> <!-- 代码片段 -->
<pre> <!-- 预格式化文本 -->
<cite> <!-- 作品标题引用 -->
<abbr> <!-- 缩写词 -->
<dfn> <!-- 术语定义 -->
<!-- 列表语义化 -->
<ul> <!-- 无序列表 -->
<ol> <!-- 有序列表 -->
<li> <!-- 列表项 -->
<dl> <!-- 定义列表 -->
<dt> <!-- 定义术语 -->
<dd> <!-- 定义描述 -->
<!-- 表格语义化 -->
<table> <!-- 表格容器 -->
<caption> <!-- 表格标题 -->
<thead> <!-- 表格头部 -->
<tbody> <!-- 表格主体 -->
<tfoot> <!-- 表格底部 -->
<th> <!-- 表头单元格 -->
<td> <!-- 数据单元格 -->
<!-- 表单语义化 -->
<form> <!-- 表单容器 -->
<fieldset> <!-- 相关表单字段组 -->
<legend> <!-- 字段组标题 -->
<label> <!-- 表单控件标签 -->
<button> <!-- 按钮 -->
<input> <!-- 输入控件 -->
<select> <!-- 下拉选择 -->
<textarea> <!-- 多行文本输入 -->4.2.2 语义化最佳实践
<!-- ✅ 正确的语义化实践 -->
<article class="blog-post">
<header class="post-header">
<h1 class="post-title">如何编写语义化 HTML</h1>
<div class="post-meta">
<time datetime="2023-01-01" class="post-date">2023年1月1日</time>
<address class="post-author">作者:张三</address>
</div>
</header>
<div class="post-content">
<section>
<h2>什么是语义化</h2>
<p>语义化是指使用正确的 HTML 标签来表达内容的含义...</p>
<blockquote cite="https://www.w3.org">
<p>"Semantic HTML is the use of HTML markup to reinforce the semantics, or meaning, of the information in webpages."</p>
</blockquote>
</section>
<section>
<h2>语义化的好处</h2>
<ul>
<li><strong>可访问性提升</strong>:屏幕阅读器能够正确理解页面结构</li>
<li><strong>SEO 优化</strong>:搜索引擎更好地理解页面内容</li>
<li><strong>代码可维护性</strong>:代码结构清晰,易于理解和维护</li>
</ul>
</section>
</div>
<footer class="post-footer">
<nav class="post-navigation">
<a href="#previous" rel="prev">上一篇</a>
<a href="#next" rel="next">下一篇</a>
</nav>
</footer>
</article>4.3 语义化的好处
4.3.1 可访问性改善
<!-- 为屏幕阅读器提供更好的结构 -->
<form>
<fieldset>
<legend>用户信息</legend>
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required
aria-required="true" aria-describedby="username-help">
<small id="username-help">请输入3-20个字符的用户名</small>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password" required
aria-required="true">
</div>
<button type="submit" aria-label="提交用户注册表单">注册</button>
</fieldset>
</form>4.3.2 SEO 优化
<!-- 搜索引擎友好的结构 -->
<article itemscope itemtype="https://schema.org/Article">
<header>
<h1 itemprop="headline">HTML5 语义化最佳实践</h1>
<time itemprop="datePublished" datetime="2023-01-01">2023年1月1日</time>
<address itemprop="author" itemscope itemtype="https://schema.org/Person">
<span itemprop="name">张三</span>
</address>
</header>
<div itemprop="articleBody">
<p>文章内容...</p>
</div>
<footer>
<nav>
<a href="#comments" itemprop="discussionUrl">查看评论 (15)</a>
</nav>
</footer>
</article>4.3.3 代码可维护性
<!-- 清晰的代码结构,易于理解和维护 -->
<body>
<!-- 头部区域 -->
<header role="banner">
<h1>网站标题</h1>
<nav role="navigation" aria-label="主导航">
<ul>
<li><a href="#home">首页</a></li>
<li><a href="#about">关于</a></li>
<li><a href="#contact">联系</a></li>
</ul>
</nav>
</header>
<!-- 主要内容 -->
<main role="main">
<article role="article">
<h2>文章标题</h2>
<p>文章内容...</p>
</article>
</main>
<!-- 侧边栏 -->
<aside role="complementary">
<h3>相关链接</h3>
<nav aria-label="相关导航">
<ul>
<li><a href="#">链接1</a></li>
<li><a href="#">链接2</a></li>
</ul>
</nav>
</aside>
<!-- 页脚 -->
<footer role="contentinfo">
<p>© 2023 版权信息</p>
</footer>
</body>4.4 语义化检查工具
4.4.1 浏览器开发者工具
- Elements 面板:检查 HTML 结构
- Accessibility 面板:检查可访问性
- Lighthouse:综合性能和可访问性检查
4.4.2 在线验证工具
- W3C Markup Validation Service:HTML 语法验证
- HTML5 Outliner:文档大纲结构检查
- axe DevTools:可访问性检查
- WAVE Web Accessibility Evaluation Tool:可访问性评估
4.4.3 语义化常见误区
<!-- ❌ 误区1:过度使用 div -->
<div class="article">
<div class="title">标题</div>
<div class="content">内容</div>
<div class="date">日期</div>
</div>
<!-- ✅ 正确做法:使用语义化标签 -->
<article>
<h2>标题</h2>
<p>内容</p>
<time datetime="2023-01-01">2023年1月1日</time>
</article>
<!-- ❌ 误区2:错误使用标题层级 -->
<h3>主标题</h3>
<h5>子标题</h5>
<h2>另一个主标题</h2>
<!-- ✅ 正确做法:保持标题层级连续 -->
<h1>主标题</h1>
<h2>子标题</h2>
<h3>子子标题</h3>
<!-- ❌ 误区3:忽略 alt 属性 -->
<img src="photo.jpg">
<!-- ✅ 正确做法:提供有意义的 alt 文本 -->
<img src="photo.jpg" alt="一位程序员在电脑前工作的照片">4.5 语义化发展趋势
HTML 的发展趋势是更加语义化和结构化:
- HTML5 语义化标签:
<article>,<section>,<nav>,<header>,<footer>等 - 微数据(Microdata):结构化数据标记
- JSON-LD:基于 JSON 的链接数据
- Web Components:自定义语义化组件
- ARIA 属性:增强可访问性的语义化
语义化是现代 Web 开发的核心原则之一,它不仅影响代码质量,还直接影响用户体验、搜索引擎优化和可访问性。
5. 响应式 HTML
5.1 视口配置
响应式设计的基础是正确的视口配置:
<meta name="viewport" content="width=device-width, initial-scale=1.0">视口参数说明:
width=device-width:视口宽度等于设备宽度initial-scale=1.0:初始缩放比例minimum-scale=1.0:最小缩放比例maximum-scale=1.0:最大缩放比例user-scalable=no:禁止用户缩放(不推荐)
5.2 响应式图片
<!-- 使用 srcset 实现响应式图片 -->
<img src="image-small.jpg"
srcset="image-small.jpg 480w,
image-medium.jpg 768w,
image-large.jpg 1024w,
image-xlarge.jpg 1200w"
sizes="(max-width: 480px) 480px,
(max-width: 768px) 768px,
(max-width: 1024px) 1024px,
1200px"
alt="响应式图片示例">
<!-- 使用 picture 元素 -->
<picture>
<source media="(max-width: 600px)" srcset="image-mobile.webp" type="image/webp">
<source media="(max-width: 600px)" srcset="image-mobile.jpg" type="image/jpeg">
<source srcset="image-desktop.webp" type="image/webp">
<img src="image-desktop.jpg" alt="图片描述">
</picture>5.3 响应式表格
<style>
/* 基础响应式表格 */
.responsive-table {
width: 100%;
border-collapse: collapse;
}
.responsive-table th,
.responsive-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
/* 小屏幕设备 */
@media screen and (max-width: 600px) {
.responsive-table {
display: block;
overflow-x: auto;
}
.responsive-table thead {
display: none;
}
.responsive-table tbody,
.responsive-table tr,
.responsive-table td {
display: block;
width: 100%;
}
.responsive-table tr {
margin-bottom: 15px;
border: 1px solid #ddd;
}
.responsive-table td {
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
}
.responsive-table td:before {
position: absolute;
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
font-weight: bold;
content: attr(data-label);
}
}
</style>
<table class="responsive-table">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>职业</th>
<th>城市</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="姓名">张三</td>
<td data-label="年龄">28</td>
<td data-label="职业">工程师</td>
<td data-label="城市">北京</td>
</tr>
</tbody>
</table>6. HTML 性能优化
6.1 资源加载优化
<!-- 预加载关键资源 -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="hero-image.jpg" as="image">
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<!-- 预连接外部域名 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://cdn.example.com">
<!-- 延迟加载图片 -->
<img src="placeholder.jpg"
data-src="real-image.jpg"
loading="lazy"
alt="延迟加载的图片"
class="lazy-load">
<script>
// 延迟加载实现
document.addEventListener('DOMContentLoaded', function() {
const lazyImages = document.querySelectorAll('img.lazy-load');
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy-load');
imageObserver.unobserve(img);
}
});
});
lazyImages.forEach(img => imageObserver.observe(img));
} else {
// 兼容回退
lazyImages.forEach(img => {
img.src = img.dataset.src;
img.classList.remove('lazy-load');
});
}
});
</script>6.2 关键资源优化
<!-- 关键 CSS 内联 -->
<style>
/* 首屏关键样式 */
body { margin: 0; font-family: Arial, sans-serif; }
.hero { height: 100vh; background: linear-gradient(45deg, #4ecdc4, #44a08d); }
.hero-content { display: flex; align-items: center; justify-content: center; }
</style>
<!-- 非关键 CSS 异步加载 -->
<link rel="preload" href="non-critical.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>
<!-- JavaScript 延迟执行 -->
<script src="analytics.js" defer></script>
<script src="non-critical.js" async></script>6.3 缓存策略
<!-- 静态资源缓存 -->
<link rel="stylesheet" href="styles.v123456.css">
<script src="script.v123456.js"></script>
<!-- Service Worker 缓存 -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('SW registered: ', registration);
})
.catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}
</script>7. HTML 可访问性
7.1 基础可访问性
<!-- 语义化标签 -->
<header role="banner">
<nav role="navigation" aria-label="主导航">
<ul>
<li><a href="#home" aria-current="page">首页</a></li>
<li><a href="#about">关于</a></li>
</ul>
</nav>
</header>
<main role="main">
<article aria-labelledby="article-title">
<h2 id="article-title">文章标题</h2>
<p>文章内容...</p>
</article>
</main>
<!-- 跳转链接 -->
<a href="#main-content" class="skip-link">跳转到主要内容</a>
<a href="#navigation" class="skip-link">跳转到导航</a>
<!-- 键盘导航支持 -->
<button onclick="toggleMenu()"
onkeydown="handleMenuKeydown(event)"
aria-expanded="false"
aria-controls="menu"
aria-haspopup="true">
菜单
</button>7.2 表单可访问性
<form role="form" aria-labelledby="form-title">
<h2 id="form-title">用户注册</h2>
<fieldset>
<legend>个人信息</legend>
<div class="form-group">
<label for="username" id="username-label">
用户名 <span aria-label="必填字段">*</span>
</label>
<input type="text"
id="username"
name="username"
required
aria-required="true"
aria-describedby="username-help username-error"
aria-invalid="false">
<small id="username-help">请输入3-20个字符的用户名</small>
<div id="username-error" class="error-message" role="alert" aria-live="polite"></div>
</div>
<div class="form-group">
<label for="password">密码 <span aria-label="必填字段">*</span></label>
<input type="password"
id="password"
name="password"
required
aria-required="true"
aria-describedby="password-help">
<small id="password-help">密码长度至少8位</small>
</div>
</fieldset>
<button type="submit" aria-label="提交用户注册表单">注册</button>
</form>7.3 媒体可访问性
<!-- 图片可访问性 -->
<img src="team-photo.jpg"
alt="团队成员在公司会议室的合影,5个人围坐在会议桌旁"
longdesc="team-photo-description.html"
width="600"
height="400">
<!-- 视频可访问性 -->
<video controls>
<source src="video.mp4" type="video/mp4">
<track src="subtitles-chinese.vtt"
kind="subtitles"
srclang="zh-CN"
label="中文字幕">
<track src="captions-chinese.vtt"
kind="captions"
srclang="zh-CN"
label="中文字幕(音效描述)">
<track src="descriptions-chinese.vtt"
kind="descriptions"
srclang="zh-CN"
label="音频描述">
</video>
<!-- 音频可访问性 -->
<audio controls>
<source src="podcast.mp3" type="audio/mpeg">
<track src="podcast-transcript.vtt"
kind="captions"
srclang="zh-CN"
label="文字稿">
</audio>8. HTML 最佳实践总结
8.1 代码质量
- 使用语义化标签:选择合适的 HTML5 语义化元素
- 保持代码整洁:适当的缩进、注释和空格
- 验证 HTML 代码:使用 W3C 验证器检查语法
- 遵循标准规范:遵循 W3C HTML 标准
- 编写可维护代码:结构清晰,易于理解和修改
8.2 性能考虑
- 优化资源加载:合理使用 preload、prefetch
- 图片优化:选择合适的格式,实施延迟加载
- 减少 HTTP 请求:合并文件,使用图标字体
- 启用缓存:设置合适的缓存策略
- 压缩资源:压缩 HTML、CSS、JavaScript
8.3 可访问性
- 提供替代文本:为图片、视频提供 alt 文本和字幕
- 支持键盘导航:确保所有功能可通过键盘访问
- 使用 ARIA 属性:增强可访问性
- 提供跳转链接:帮助用户快速导航到主要内容
- 确保颜色对比:保证足够的颜色对比度
8.4 SEO 优化
- 合理使用标题:保持标题层级结构
- 提供元数据:完善 title、description、keywords
- 使用结构化数据:Schema.org 微数据标记
- 优化 URL 结构:语义化、简洁的 URL
- 内部链接优化:合理的锚文本和链接结构
9. 常见问题和解决方案
9.1 跨浏览器兼容性
<!-- HTML5 兼容性 -->
<!--[if lt IE 9]>
<script src="html5shiv.min.js"></script>
<![endif]-->
<!-- 条件注释 -->
<!--[if IE]>
<link rel="stylesheet" href="ie.css">
<![endif]-->
<!-- Meta 标签兼容 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">9.2 常见错误及修正
<!-- ❌ 错误:忘记 alt 属性 -->
<img src="photo.jpg">
<!-- ✅ 正确:提供有意义的 alt 文本 -->
<img src="photo.jpg" alt="一张展示产品特点的图片">
<!-- ❌ 错误:不正确的嵌套 -->
<p><div>错误嵌套</div></p>
<!-- ✅ 正确:合理嵌套 -->
<div><p>正确嵌套</p></div>
<!-- ❌ 错误:重复的 ID -->
<div id="content">内容1</div>
<div id="content">内容2</div>
<!-- ✅ 正确:使用唯一的 ID -->
<div id="content1">内容1</div>
<div id="content2">内容2</div>
<!-- 或者使用 class -->
<div class="content">内容1</div>
<div class="content">内容2</div>参考资料与更多内容:
