语义化 HTML 是什么
语义化 HTML 指的是根据内容是什么 来选择标签:导航放在 <nav> 中,主要内容放在 <main> 中,博客文章放在 <article> 中。这些标签看起来只是普通的盒子,但它们会告诉浏览器、屏幕阅读器和搜索引擎页面每个部分的作用。下面是一个完全用语义化布局标签搭建的页面,每个标签都加了轮廓和标注:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Semantic layout</title>
<style>
body { font-family: system-ui, sans-serif; margin: 12px; }
header, nav, main, article, aside, footer {
border: 2px dashed #2563eb; padding: 8px; margin: 6px 0;
}
header::before, nav::before, main::before,
article::before, aside::before, footer::before {
display: block; font: 12px monospace; color: #2563eb;
}
header::before { content: "<header>"; }
nav::before { content: "<nav>"; }
main::before { content: "<main>"; }
article::before { content: "<article>"; }
aside::before { content: "<aside>"; }
footer::before { content: "<footer>"; }
.cols { display: flex; gap: 8px; }
.cols article { flex: 2; }
.cols aside { flex: 1; }
</style>
</head>
<body>
<header>
<strong>My Blog</strong>
<nav><a href="#">Home</a> | <a href="#">Posts</a> | <a href="#">About</a></nav>
</header>
<main>
<div class="cols">
<article>
<h1>Learning HTML</h1>
<p>A post about semantic tags.</p>
</article>
<aside>Related posts</aside>
</div>
</main>
<footer>© 2026 My Blog</footer>
</body>
</html>Master HTML the hands-on way
Interactive lessons, real projects, and instant feedback.
START NOW
删掉 <style> 元素,页面看起来就只是普通文字,但结构依然存在,阅读代码的人能看到,不看像素、直接读取代码的软件也能看到。
语义化布局标签
标签 用途 屏幕阅读器地标 <header>页面或文章的开头:logo、标题、作者信息 banner(仅当它不在 article、aside、main、nav 或 section 内部时) <nav>一组主要的导航链接 navigation <main>这个页面独有的内容,每个页面一个 main <article>能独立成立的完整内容:一篇文章、一条评论、一张商品卡片 默认没有 <section>有自己标题的一组同主题内容 region,仅当它有可访问名称时 <aside>主线旁边的相关内容:侧边栏、注释 complementary <footer>页面或文章的结尾信息:版权、作者、链接 contentinfo(仅在页面层级)
每个标签都有自己的详细页面:header 、nav、section 和 footer。本页讲的是它们如何组合在一起。
为什么不直接用 div
只用 <div> 元素搭建的页面,可以和语义化的页面看起来一模一样。区别在于标记表达了什么。点击按钮,给每个版本中带有含义的元素加上轮廓:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>div vs semantic</title>
<style>
body { font-family: system-ui, sans-serif; margin: 12px; }
.page { border: 1px solid #e5e7eb; padding: 6px; margin-bottom: 10px; }
.page > * { padding: 4px 8px; background: #f3f4f6; margin: 4px 0; }
.on { outline: 3px solid #16a34a; }
</style>
</head>
<body>
<div class="page" id="divs">
<div class="header">Site name</div>
<div class="nav"><a href="#">Home</a> <a href="#">Posts</a></div>
<div class="main">Page content</div>
<div class="footer">Footer</div>
</div>
<div class="page" id="semantic">
<header>Site name</header>
<nav><a href="#">Home</a> <a href="#">Posts</a></nav>
<main>Page content</main>
<footer>Footer</footer>
</div>
<button onclick="mark('divs')">Outline meaning in div version</button>
<button onclick="mark('semantic')">Outline meaning in semantic version</button>
<p id="out"></p>
<script>
function mark(id) {
document.querySelectorAll('.on').forEach(el => el.classList.remove('on'));
const found = document.querySelectorAll('#' + id + ' :is(header, nav, main, aside, article, footer)');
found.forEach(el => el.classList.add('on'));
document.getElementById('out').textContent = found.length + ' semantic elements found';
}
</script>
</body>
</html>
div 版本找到 0 个,语义化版本找到 4 个。辅助技术看到的就是这些:在语义化页面上,屏幕阅读器用户可以直接跳到导航或主要内容;在 div 页面上,则必须从头读到尾。像 class="nav" 这样的类名对浏览器来说没有任何含义。
对于只为样式或布局而存在的盒子,比如第一个例子中的 .cols flex 包裹元素,<div> 仍然是正确的选择。
main、article 与 aside
<main> 包裹这个页面独有的内容,只出现一次。在它里面,<article> 标记那些单独复制到另一个网站也说得通的内容,<aside> 标记相关但删掉也不影响文章的内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>article and aside</title>
<style>
body { font-family: system-ui, sans-serif; margin: 12px; }
article { border: 2px solid #e5e7eb; padding: 0 12px; }
aside.note {
float: inline-end; width: 40%; margin: 0 0 8px 12px;
background: #fef3c7; border: 1px solid #f59e0b; padding: 8px; font-size: 14px;
}
time { color: #6b7280; }
</style>
</head>
<body>
<main>
<article>
<header>
<h1>Baking bread at home</h1>
<p>By Dana, <time datetime="2026-09-24">September 24, 2026</time></p>
</header>
<aside class="note">
<strong>Note:</strong> flour types vary, so adjust the water a little.
</aside>
<p>Mix flour, water, salt and yeast. Knead for ten minutes, then let the dough rise for an hour.</p>
<p>Shape the loaf and bake it at 230°C until the crust is dark.</p>
<footer>Filed under: cooking</footer>
</article>
</main>
</body>
</html>
这篇 article 有自己的 <header> 和 <footer>。它们并不局限于页面层级:每一个都用来开启或结束离它最近的 article 或 section。<time datetime> 元素以机器可读的形式给出日期,同时以人类易读的形式显示它。
检查标题大纲
标题是结构的另一半。屏幕阅读器用户常常按标题逐个浏览页面,所以各级标题应该读起来像一份目录,不跳过任何级别。下面这段脚本会打印出它所在页面的大纲:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Outline</title>
<style>
body { font-family: system-ui, sans-serif; margin: 12px; }
pre { background: #111827; color: #e5e7eb; padding: 10px; }
</style>
</head>
<body>
<h1>Coffee guide</h1>
<h2>Beans</h2>
<h3>Arabica</h3>
<h3>Robusta</h3>
<h2>Brewing</h2>
<h4>French press</h4>
<pre id="outline"></pre>
<script>
const lines = [...document.querySelectorAll('h1, h2, h3, h4, h5, h6')].map(h => {
const level = Number(h.tagName[1]);
return ' '.repeat(level - 1) + h.tagName + ' ' + h.textContent;
});
document.getElementById('outline').textContent = lines.join('\n');
</script>
</body>
</html>
“Brewing”下面的 h4 跳过了一级。把它改成 h3,大纲就清晰了。按结构选择标题级别,想让标题更大或更小,就用 CSS 改它的字号。
更多语义标签
语义不只关乎布局。下面这些文本级标签同样带有含义:
标签 含义 <strong>重要的文字(默认加粗) <em>需要强调语气的文字(默认斜体) <figure> 和 <figcaption>图片、图表或代码示例,以及它的说明文字 <time datetime="...">机器可读形式的日期或时间 <address>页面或文章作者的联系方式 <mark>高亮的文字,比如搜索匹配项 <abbr title="...">缩写及其完整形式 <button>执行某个操作的元素
<!DOCTYPE html>
<figure style="margin: 0; border: 1px solid #e5e7eb; padding: 8px; display: inline-block;">
<img alt="Blue square" width="120" height="80"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='80'%3E%3Crect width='120' height='80' fill='%232563eb'/%3E%3C/svg%3E">
<figcaption>Figure 1: a caption tied to its image.</figcaption>
</figure>
<p>Search results for <mark>semantic</mark>. The <abbr title="World Wide Web Consortium">W3C</abbr> writes web standards.</p>
把鼠标悬停在缩写“W3C”上,就能在提示框中看到它的完整形式。
常见错误
因为外观而使用某个标签 。<blockquote> 用于引用,不是用来缩进的;<h3> 表示标题级别,不是用来显示中等大小的粗体字的。样式请用 CSS 设置。
什么都用 <section> 包起来 。section 应该有标题和主题。如果你需要一个用于样式的盒子,就用 <div>。
有不止一个可见的 <main> 。每个页面只保留一个,并且绝不要把它嵌套在 <article>、<aside>、<header>、<nav> 或 <footer> 里面。
把每组链接都放进 <nav> 。只把它留给主要的导航区块,比如网站菜单或目录。页脚里的几个链接不需要它。
可点击的 <div> 元素 。<div onclick> 无法用键盘访问。操作请用 <button>,导航请用 <a href>。