Veloris.
返回索引
概念基础 2026-03-08

为什么不能全用 div?HTML 语义化的真正价值

7 分钟
2.1k words

为什么不能全用 div?HTML 语义化的真正价值

前言

上一篇我们搞清楚了浏览器和服务器的”对话”方式。现在问题来了:服务器返回的那一大段 HTML 文本,到底该怎么写?

HTML(HyperText Markup Language,超文本标记语言) 不是编程语言,而是一种标记语言——用标签(tag)来描述内容的结构和含义。如果你有 C 语言基础,可以这样理解:C 语言告诉计算机”怎么做”,HTML 告诉浏览器”这是什么”。

刚开始学 HTML 时,很多人(包括我)会觉得:反正 <div> 能装一切,为什么要记那么多标签?这篇文章会回答这个问题,同时带你掌握 HTML 的文档结构和最常用的标签。

正文

1. HTML 文档的基本骨架

每个 HTML 文件都遵循相同的基本结构:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>页面标题</title>
</head>
<body>
  <!-- 页面的可见内容放在这里 -->
</body>
</html>

逐行解释:

代码作用
<!DOCTYPE html>声明文档类型为 HTML5,告诉浏览器用最新标准解析
<html lang="zh-CN">根元素,lang 属性指定页面语言(影响搜索引擎和屏幕阅读器)
<head>头部区域,存放元数据(不直接显示在页面上)
<meta charset="UTF-8">字符编码,UTF-8 支持中文和各种特殊字符
<meta name="viewport" ...>视口设置,确保在手机上正确显示
<title>页面标题,显示在浏览器标签页上
<body>主体区域,所有可见内容都在这里

用 C 语言的思路理解:<head> 相当于文件顶部的 #include 和宏定义(声明但不直接显示),<body> 相当于 main() 函数(用户真正看到的内容)。

2. 标签的基本语法

HTML 标签的通用格式:

<标签名 属性名="属性值">内容</标签名>

两种标签类型:

<!-- 双标签(有开始和结束) -->
<p>这是一个段落</p>
<a href="https://example.com">这是一个链接</a>

<!-- 单标签(自闭合,没有内容) -->
<img src="photo.jpg" alt="照片描述">
<br>
<hr>
<input type="text">

标签可以嵌套,形成树形结构(这就是 DOM 树的由来):

<div>
  <h1>标题</h1>
  <p>这是一段文字,包含一个<a href="#">链接</a>。</p>
</div>

对应的树形结构:

div
├── h1
│   └── "标题"
└── p
    ├── "这是一段文字,包含一个"
    ├── a
    │   └── "链接"
    └── "。"

💡 工程师手记:HTML 的嵌套结构让我想起 Verilog 中模块的层次化实例化——顶层模块包含子模块,子模块还能再包含更小的模块。DOM 树就是 HTML 标签的”层次化结构图”,后续学 JavaScript 时你会频繁和它打交道。

(建议替换为你自己第一次理解 DOM 树时的感受)

3. 常用 HTML 标签速查

HTML 标签有上百个,但日常开发中常用的也就二十几个。下面按类别快速过一遍,不需要记住所有细节——用到的时候查文档就行,重要的是知道有哪些”工具”可用。

3.1 文本内容标签

<!-- 标题:h1 最大最重要,h6 最小,一个页面通常只有一个 h1 -->
<h1>一级标题</h1>
<h2>二级标题</h2>
<h3>三级标题</h3>

<!-- 段落 -->
<p>这是一个段落。段落之间会自动产生间距。</p>

<!-- 强调 -->
<strong>加粗强调(语义:重要)</strong>
<em>斜体强调(语义:着重)</em>

<!-- 换行和分隔线 -->
<br>  <!-- 换行 -->
<hr>  <!-- 水平分隔线 -->

<!-- 预格式化文本(保留空格和换行,常用于代码展示) -->
<pre>
  int main() {
      return 0;
  }
</pre>

<!-- 行内代码 -->
<code>printf("hello")</code>

3.2 链接与图片

<!-- 超链接 -->
<a href="https://www.baidu.com">访问百度</a>
<a href="https://example.com" target="_blank">在新标签页打开</a>
<a href="#section2">跳转到页面内的 section2(锚点链接)</a>
<a href="mailto:[email protected]">发送邮件</a>

<!-- 图片 -->
<img src="images/photo.jpg" alt="这张图片的文字描述" width="300">
<!--
  src:图片路径(可以是相对路径或 URL)
  alt:替代文本(图片加载失败时显示,也用于无障碍访问)
  width/height:尺寸(建议只设一个,另一个自动等比缩放)
-->

3.3 列表

<!-- 无序列表(圆点) -->
<ul>
  <li>HTML</li>
  <li>CSS</li>
  <li>JavaScript</li>
</ul>

<!-- 有序列表(数字) -->
<ol>
  <li>第一步:安装编辑器</li>
  <li>第二步:创建文件</li>
  <li>第三步:编写代码</li>
</ol>

<!-- 定义列表(术语 + 解释) -->
<dl>
  <dt>HTML</dt>
  <dd>超文本标记语言,用于定义网页结构</dd>
  <dt>CSS</dt>
  <dd>层叠样式表,用于控制网页样式</dd>
</dl>

3.4 表格

<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>25</td>
      <td>设计师</td>
    </tr>
  </tbody>
</table>

<thead> 表头、<tbody> 表体、<th> 表头单元格、<td> 普通单元格、<tr> 表格行。

3.5 表单元素

<form action="/submit" method="POST">
  <!-- 文本输入 -->
  <label for="username">用户名:</label>
  <input type="text" id="username" name="username" placeholder="请输入用户名">

  <!-- 密码输入 -->
  <label for="password">密码:</label>
  <input type="password" id="password" name="password">

  <!-- 邮箱(自带格式验证) -->
  <input type="email" name="email" placeholder="[email protected]">

  <!-- 数字 -->
  <input type="number" name="age" min="0" max="150">

  <!-- 下拉选择 -->
  <select name="city">
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
    <option value="shenzhen">深圳</option>
  </select>

  <!-- 多行文本 -->
  <textarea name="bio" rows="4" cols="50" placeholder="自我介绍"></textarea>

  <!-- 复选框 -->
  <input type="checkbox" id="agree" name="agree">
  <label for="agree">我同意用户协议</label>

  <!-- 单选按钮 -->
  <input type="radio" name="gender" value="male"> 男
  <input type="radio" name="gender" value="female"> 女

  <!-- 提交按钮 -->
  <button type="submit">提交</button>
</form>

关键概念<label>for 属性要与对应 <input>id 匹配,这样点击标签文字也能聚焦到输入框(提升用户体验和无障碍访问)。

4. 容器标签:div 与 span

<!-- div:块级容器,独占一行,用于组合多个元素 -->
<div>
  <h2>文章标题</h2>
  <p>文章内容...</p>
</div>

<!-- span:行内容器,不换行,用于包裹文本片段 -->
<p>价格:<span style="color: red;">¥99</span> 元</p>

<div><span> 本身没有语义含义,它们是”通用容器”——什么都能装,但不告诉浏览器”装的是什么”。

在 HTML5 之前,页面布局几乎全靠 <div> 嵌套,这就是所谓的 “div 汤”(div soup)

💡 工程师手记:我写的第一个 HTML 页面就是典型的 div 汤——一个 <div> 套另一个 <div>,嵌套了七八层。三天后回来改 bug,看着满屏的 </div> 完全分不清哪个对应哪个。那时候我就想:有没有更有意义的标签名?

(建议替换为你自己第一次写 HTML 时的真实经历)

5. ★ 从 div 汤到语义化:HTML5 语义标签

这是本文的核心内容。先看一个对比——同一个页面结构,两种写法:

div 汤写法(HTML5 之前的主流做法):

<div class="header">
  <div class="nav">...</div>
</div>
<div class="main">
  <div class="article">
    <div class="section">...</div>
  </div>
  <div class="sidebar">...</div>
</div>
<div class="footer">...</div>

语义化写法(HTML5 推荐):

<header>
  <nav>...</nav>
</header>
<main>
  <article>
    <section>...</section>
  </article>
  <aside>...</aside>
</main>
<footer>...</footer>

两种写法在浏览器里显示效果完全一样。那为什么要用语义标签?

语义化的四重价值

  1. 可读性:代码一目了然。看到 <nav> 就知道是导航,看到 <div class="nav"> 还得去查 CSS 确认
  2. 无障碍(Accessibility):屏幕阅读器会告诉视障用户”这是导航区域""这是主要内容”——用 <div> 它什么都不知道
  3. SEO(搜索引擎优化):搜索引擎能通过 <article><main> 识别页面的核心内容,给予更准确的排名
  4. 可维护性:团队协作时,语义标签就是天然的代码文档

💬 你可能会问:语义化听起来很好,但不用语义标签页面不也能正常显示吗?为什么要费这个劲?

确实,纯视觉层面没有区别。但 Web 的用户不只是”看得见的人用鼠标点击”——还有视障用户用屏幕阅读器、搜索引擎爬虫、各种自动化工具。语义标签是你和这些”非人类用户”沟通的唯一渠道。就像给代码写注释——不写也能跑,但维护起来是噩梦。

语义标签速查表

标签语义替代了什么
<header>页面或区域的头部<div class="header">
<nav>导航链接区域<div class="nav">
<main>页面主要内容(唯一)<div class="main">
<article>独立的内容块(文章、帖子)<div class="article">
<section>主题性的内容分组<div class="section">
<aside>侧边栏、附属信息<div class="sidebar">
<footer>页面或区域的底部<div class="footer">
<figure>图片/图表及其说明<div class="image-wrapper">
<figcaption><figure> 的标题<p class="caption">

💬 你可能会问:div 和 section 到底有什么区别?什么时候该用哪个?

简单判断:如果这块内容有一个明确的主题(能给它起个小标题),用 <section>;如果只是为了布局或样式把几个元素组合在一起,用 <div><section> = “有主题的内容分组”,<div> = “无语义的通用容器”。

一个完整的语义化页面示例

<body>
  <header>
    <nav>
      <a href="/">首页</a>
      <a href="/blog">博客</a>
      <a href="/about">关于</a>
    </nav>
  </header>

  <main>
    <article>
      <h1>文章标题</h1>
      <p>文章内容...</p>

      <section>
        <h2>第一节</h2>
        <p>内容...</p>
      </section>

      <section>
        <h2>第二节</h2>
        <p>内容...</p>
      </section>
    </article>

    <aside>
      <h3>侧边栏</h3>
      <p>相关推荐、广告等</p>
    </aside>
  </main>

  <footer>
    <p>&copy; 2026 我的网站</p>
  </footer>
</body>

6. 块级元素 vs 行内元素

HTML 元素分为两大显示类型,理解这个区别对后续学 CSS 很重要:

特性块级元素(Block)行内元素(Inline)
换行独占一行不换行,与其他行内元素同行
宽度默认占满父容器宽度由内容决定宽度
嵌套可以包含块级和行内元素通常只包含行内元素或文本
代表div, p, h1-h6, ul, ol, table, formspan, a, strong, em, img, input
<!-- 块级元素:各占一行 -->
<p>第一段</p>
<p>第二段</p>

<!-- 行内元素:同一行显示 -->
<span>姓名</span>
<span>年龄</span>
<a href="#">链接</a>

💡 工程师手记:这个区分刚开始让我很困惑——为什么有的标签自动换行、有的不换行?后来发现关键在于:块级元素像”一整行货架”(不管放多少东西都独占一行),行内元素像”货架上的商品”(挨着排列)。下一篇学 CSS 的 display 属性时,你会发现这个行为是可以改的。

(建议替换为你自己理解块级/行内区别的过程)

7. 动手实践

创建一个 index.html 文件,搭建一个简单的个人介绍页面。注意:这次要用语义化标签,不要写 div 汤。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>关于我 - 前端学习者</title>
</head>
<body>
  <header>
    <nav>
      <a href="#about">关于我</a> |
      <a href="#skills">技能</a> |
      <a href="#projects">项目</a>
    </nav>
  </header>

  <main>
    <section id="about">
      <h1>你好,我是一名前端学习者</h1>
      <p>我有 <strong>C 语言</strong>和<strong>嵌入式</strong>背景,正在学习前端开发。</p>
      <img src="https://via.placeholder.com/200" alt="我的头像">
    </section>

    <section id="skills">
      <h2>技能清单</h2>
      <ul>
        <li>C / Python</li>
        <li>FPGA / Verilog</li>
        <li>HTML / CSS(学习中)</li>
        <li>JavaScript(即将学习)</li>
      </ul>
    </section>

    <section id="projects">
      <h2>项目经历</h2>
      <table>
        <thead>
          <tr>
            <th>项目</th>
            <th>技术栈</th>
            <th>状态</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>串口收发器</td>
            <td>Verilog</td>
            <td>已完成</td>
          </tr>
          <tr>
            <td>个人博客</td>
            <td>Astro + React</td>
            <td>进行中</td>
          </tr>
        </tbody>
      </table>
    </section>
  </main>

  <footer>
    <hr>
    <p>&copy; 2026 前端学习笔记 | <a href="mailto:[email protected]">联系我</a></p>
  </footer>
</body>
</html>

用浏览器打开这个文件,你会看到一个没有任何样式的”裸页面”——这就是纯 HTML 的样子。然后打开 DevTools 的 Elements 面板,展开 DOM 树,对照你写的标签看看结构是否和你预期一致。

常见问题

💬 你可能会问:HTML 标签这么多,我需要全部记住吗?

完全不需要。日常开发用到的标签不超过 20 个。记住文档骨架(html/head/body)、基础内容(h1-h6/p/a/img/ul/ol)、语义结构(header/nav/main/article/section/aside/footer)就足够了。其他的用到时查 MDN 文档 即可。

💬 你可能会问:表单那么多 input 类型,实际开发中最常用的是哪几个?

textpasswordemailnumber 这四个覆盖 80% 的场景。checkboxradio 也常用。其他类型(如 daterangecolor)根据需求再学。

总结

知识点核心要点
文档骨架<!DOCTYPE html> + <html> + <head> + <body>
常用标签标题 h1-h6、段落 p、链接 a、图片 img、列表 ul/ol、表格 table、表单 form
容器标签div(块级通用容器)、span(行内通用容器)——无语义
语义化标签header / nav / main / article / section / aside / footer
语义化价值可读性、无障碍访问、SEO、可维护性——不只是”显示”,更是”沟通”
块级 vs 行内块级独占一行,行内不换行(CSS 可以改变)

下一步行动:用语义化标签重新搭建你的个人介绍页面,然后用 Chrome DevTools 的 Elements 面板检查 DOM 树结构。下一篇我们开始给这个”裸页面”穿上漂亮的衣服——CSS。

参考资料


📖 系列导航:本文是「FPGA 工程师的前端学习笔记」系列的第 2 篇 上一篇:从嵌入式到 Web:浏览器和服务器是怎么”对话”的 下一篇:CSS 入门:选择器与盒模型

End of file.