跳到主要内容

HTML 空标签(Void Elements)

什么是空标签?

在 HTML 中,大多数标签都是成对出现的,有开始标签和结束标签,比如 <div></div><p></p>。但有一类特殊的标签没有结束标签、也不能包含任何子内容,它们就是空标签(Void Elements)。

<!-- 普通标签:成对出现,可以包含内容 -->
<p>这是一段文字</p>

<!-- 空标签:没有结束标签,不包含内容 -->
<br>
<img src="logo.png" alt="Logo">
<input type="text">
名称说明

空标签在不同场景下有多种叫法:

  • Void Elements(W3C / WHATWG 官方术语)
  • 空标签 / 空元素(中文社区常用)
  • 自闭合标签(Self-closing Tags,严格来说是 XHTML 的写法)

本文统一使用"空标签"来称呼。


为什么需要空标签?

空标签存在的核心原因是:它们表示的内容本身就不需要"包裹"子元素

比如:

  • <img> 本身就是一张图片,不需要在里面再放其他元素
  • <br> 就是一个换行,换行这个动作不需要"包裹"任何内容
  • <input> 是一个表单控件,内容由 value 属性控制,而不是子元素

完整的空标签列表

HTML5 规范中定义了以下空标签:

标签用途常用程度
<area>图像映射区域较少
<base>文档基准 URL较少
<br>换行高频
<col>表格列属性一般
<embed>嵌入外部内容一般
<hr>水平分割线高频
<img>图片高频
<input>表单输入控件高频
<link>外部资源链接(CSS 等)高频
<meta>文档元信息高频
<param>对象参数(已废弃)极少
<source>媒体资源一般
<track>字幕轨道较少
<wbr>可选换行点较少
记忆技巧

高频空标签可以用这句话记住:"BIL MIH S"

  • Br, Img, Link
  • Meta, Input, Hr
  • Source

日常开发中,掌握这 7 个就覆盖了绝大多数场景。


逐个详解常用空标签

<br> — 换行

在文本中插入一个换行符。

<p>
第一行文字<br>
第二行文字<br>
第三行文字
</p>

注意事项

  • 不要用多个 <br> 来制造间距,应该用 CSS 的 marginpadding
  • <br> 适用于诗歌、地址等内容确实需要换行的场景
<!-- ❌ 错误用法:用 br 制造间距 -->
<p>标题</p>
<br><br><br>
<p>内容</p>

<!-- ✅ 正确用法:用 CSS 控制间距 -->
<p style="margin-bottom: 2rem;">标题</p>
<p>内容</p>

<img> — 图片

在页面中嵌入一张图片。

<img src="photo.jpg" alt="一张风景照" width="800" height="600">

关键属性

属性说明是否必须
src图片路径
alt替代文本(图片加载失败或屏幕阅读器使用)是(语义必须)
width宽度建议设置(防止布局偏移)
height高度建议设置(防止布局偏移)
loading懒加载,值为 lazyeager可选
<!-- 响应式图片 + 懒加载 -->
<img
src="photo.jpg"
alt="风景照"
width="800"
height="600"
loading="lazy"
>

<input> — 表单输入

HTML 中最多变的空标签,通过 type 属性变成不同的表单控件。

<!-- 文本框 -->
<input type="text" placeholder="请输入用户名">

<!-- 密码框 -->
<input type="password" placeholder="请输入密码">

<!-- 复选框 -->
<input type="checkbox" id="agree">

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

<!-- 文件上传 -->
<input type="file" accept="image/*">

<!-- 提交按钮 -->
<input type="submit" value="提交">
提示

<input>type 属性支持超过 20 种值,包括 textpasswordemailnumberdatecolorrange 等。

<hr> — 水平分割线

表示主题内容之间的分隔。

<h2>第一章</h2>
<p>第一章的内容...</p>

<hr>

<h2>第二章</h2>
<p>第二章的内容...</p>

<hr> 是有语义的,表示"话题转换",不仅仅是一条视觉线条。

<meta> — 文档元信息

<head> 中提供页面的元数据。

<head>
<!-- 字符编码 -->
<meta charset="UTF-8">

<!-- 响应式视口 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!-- 页面描述(SEO 重要) -->
<meta name="description" content="这是一个学习 HTML 空标签的教程">

<!-- Open Graph(社交分享) -->
<meta property="og:title" content="HTML 空标签详解">
</head>

<head> 中引入外部资源,最常见的是 CSS 样式表。

<head>
<!-- 引入 CSS -->
<link rel="stylesheet" href="styles.css">

<!-- 网站图标 -->
<link rel="icon" href="favicon.ico">

<!-- 预加载字体 -->
<link rel="preload" href="font.woff2" as="font" crossorigin>
</head>

<source> — 媒体资源

<video><audio><picture> 提供多个备选资源。

<!-- 视频多格式兼容 -->
<video controls>
<source src="movie.webm" type="video/webm">
<source src="movie.mp4" type="video/mp4">
您的浏览器不支持 video 标签。
</video>

<!-- 响应式图片 -->
<picture>
<source media="(min-width: 800px)" srcset="large.jpg">
<source media="(min-width: 400px)" srcset="medium.jpg">
<img src="small.jpg" alt="响应式图片">
</picture>

空标签的写法:<br> vs <br/> vs <br />

这是前端开发中经常引起困惑的问题。我们来理清三种写法的背景:

写法在 HTML5 中是否合法说明
<br>合法HTML5 推荐写法
<br/>合法兼容写法
<br />合法XHTML 风格,斜杠前有空格
<br></br>不合法空标签不允许有结束标签
重要规则

在 HTML5 中,空标签不允许写结束标签。以下写法是错误的:

<!-- ❌ 错误!空标签不能有结束标签 -->
<br></br>
<img src="a.png"></img>
<input type="text"></input>

浏览器虽然不会报错(容错机制),但这不符合规范,可能导致意想不到的解析问题。

各框架中的惯例

环境推荐写法原因
纯 HTML5<br>规范推荐,最简洁
React / JSX<br />JSX 要求所有标签必须闭合
Vue 模板<br><br />两者均可
XHTML<br />XML 语法要求

空标签 vs 空内容标签

空标签和"内容为空的普通标签"是两个不同的概念,不要混淆。

<!-- 空标签(Void Element):规范规定不能有子内容 -->
<br>
<img src="a.png" alt="">

<!-- 空内容标签:普通标签,只是碰巧没写内容 -->
<div></div>
<p></p>
<span></span>

关键区别

对比项空标签(Void Element)空内容标签
结束标签不允许有必须有
子内容永远不能有可以有,只是当前为空
示例<br> <img> <input><div></div> <span></span>
innerHTML无意义为空字符串

浏览器如何解析空标签

浏览器的 HTML 解析器对空标签有特殊处理逻辑:

来看一个实际的例子:

<!-- 你写的代码 -->
<img src="a.png">这段文字会怎样?</img>

<!-- 浏览器实际解析为 -->
<img src="a.png">
这段文字会怎样?

浏览器会忽略 </img> 结束标签,把"这段文字会怎样?"当作 <img>兄弟节点而非子节点。


使用 JavaScript 操作空标签

空标签在 DOM 操作中有一些特殊行为:

const img = document.querySelector('img');
const div = document.querySelector('div');

// children 和 innerHTML
console.log(img.children.length); // 0 —— 永远为 0
console.log(div.children.length); // 可能为 0,也可能有子元素

// 尝试给空标签添加子元素(不会报错,但没有视觉效果)
img.innerHTML = '<span>test</span>';
console.log(img.innerHTML); // '<span>test</span>' —— 虽然设置了,但不会渲染

// 通过 appendChild 添加子节点
const span = document.createElement('span');
img.appendChild(span);
// DOM 中 img 确实有了子节点,但浏览器不会渲染它
注意

虽然 JavaScript 允许你向空标签中插入子节点(不会抛出错误),但浏览器不会渲染空标签内的子内容。这是 HTML 规范层面的限制,而非 DOM API 的限制。


实际开发中的注意事项

1. alt 属性不能省略

<img>alt 属性对可访问性至关重要:

<!-- ❌ 缺少 alt -->
<img src="banner.jpg">

<!-- ✅ 有 alt -->
<img src="banner.jpg" alt="网站首页横幅">

<!-- ✅ 装饰性图片使用空 alt -->
<img src="divider.png" alt="">

2. 设置图片尺寸防止 CLS

不设置宽高的图片会导致累积布局偏移(CLS)

<!-- ❌ 没有尺寸,加载时页面会跳动 -->
<img src="photo.jpg" alt="照片">

<!-- ✅ 设置尺寸,浏览器提前预留空间 -->
<img src="photo.jpg" alt="照片" width="800" height="600">

3. <input> 要配合 <label>

<!-- ❌ 没有关联 label,可访问性差 -->
<input type="text" placeholder="用户名">

<!-- ✅ 使用 label 关联 -->
<label for="username">用户名</label>
<input type="text" id="username" placeholder="请输入用户名">

4. 避免滥用 <br>

<!-- ❌ 用 br 做布局间距 -->
<div>
内容A
<br><br><br>
内容B
</div>

<!-- ✅ 用 CSS 控制间距 -->
<div>
<p class="mb-4">内容A</p>
<p>内容B</p>
</div>

面试高频问答

Q1:HTML 中有哪些空标签(Void Elements)?

:HTML5 规范中定义的空标签有:<area><base><br><col><embed><hr><img><input><link><meta><param>(已废弃)、<source><track><wbr>。日常开发中最常用的是 <br><img><input><hr><meta><link><source> 这 7 个。

Q2:<br><br /> 有什么区别?

:在 HTML5 中两者都是合法的,没有功能区别。<br> 是 HTML5 的推荐写法,<br /> 是 XHTML 的风格。在 JSX(React)中,由于 JSX 基于 XML 语法要求所有标签必须闭合,所以必须使用 <br />

Q3:空标签能不能写结束标签?

:在 HTML5 中,空标签不允许有结束标签。写 <br></br><img></img> 是不符合规范的。虽然浏览器的容错机制不会报错,但结束标签会被忽略,标签内的内容会被解析为兄弟节点而非子节点,可能导致意外行为。

Q4:空标签和自闭合标签是一回事吗?

:严格来说不完全是。"空标签"(Void Elements)是 HTML 规范定义的一类不能有子内容的元素。"自闭合标签"(Self-closing Tags)是一种书写形式(如 <br />)。在 HTML5 中,只有空标签可以使用自闭合写法,普通标签写成自闭合(如 <div />)在 HTML 中会被当作开始标签处理(不会自动关闭)。但在 JSX 中,<div /> 是合法的自闭合写法。

Q5:为什么 <img>alt 属性很重要?

alt 属性有三个重要作用:

  1. 可访问性:屏幕阅读器会朗读 alt 文本,让视障用户了解图片内容
  2. SEO:搜索引擎通过 alt 文本理解图片内容,有助于图片搜索排名
  3. 容错展示:图片加载失败时,浏览器会显示 alt 文本作为替代

如果图片是纯装饰性的,应设置 alt=""(空字符串),而非省略该属性。

Q6:用 JavaScript 能给空标签添加子元素吗?

:DOM API 层面是允许的,调用 appendChild 或设置 innerHTML 不会报错,空标签的 DOM 节点中也确实会有子节点。但浏览器不会渲染空标签中的子内容,这是 HTML 规范的渲染规则决定的,所以在实际开发中这样做没有意义。

Q7:<input> 为什么是空标签,而 <textarea> 不是?

:这是由元素的设计用途决定的:

  • <input> 的值通过 value 属性来设置,不需要在标签之间放内容
  • <textarea> 的默认值需要写在开始标签和结束标签之间,所以它不是空标签
<input type="text" value="通过属性设置值">
<textarea>通过标签内容设置默认值</textarea>

这也解释了为什么 <select> 不是空标签 —— 它需要在内部包含 <option> 子元素。