替换元素

4 阅读8分钟

替换元素(replaced elements)是什么?为什么 img / input 和普通行内元素不一样

很多前端初学者都会困惑:
为什么 span 这种行内元素设置 width / height 不太生效,
imginputbutton 却又常常可以设置宽高?
这背后其实就是一个很重要的概念:替换元素(replaced elements)


目录


一、什么是替换元素

替换元素,英文叫 replaced elements

你可以先记住一个最直白的定义:

替换元素的显示内容,不是由普通 HTML 文本直接决定的,而是由元素本身的外部资源或内部机制“替换”出来的。

也就是说,这类元素的内容并不是像 divspan 那样由你写在标签里面的文本直接渲染出来,而是浏览器根据它自己的规则来显示。

例如:

<img src="cat.jpg" alt="一只猫">

这里页面上显示出来的不是 <img> 标签内部的文本,而是 src 指向的图片资源。

再比如:

<input type="text" value="hello">

这个输入框显示出来的样子,也不是标签内部的文字节点,而是浏览器实现的表单控件。

这就是“替换”的意思。


二、为什么叫“替换”元素

这个名字第一次听会有点抽象,其实可以这样理解:

浏览器拿到一个元素后,一般有两种渲染方式:

1. 普通元素

比如:

<span>Hello</span>
<div>World</div>

它们显示的内容,直接来自标签里面写的文本或子元素。

也就是说,HTML 里写什么,页面里就按普通文档流去渲染什么。


2. 替换元素

比如:

<img src="a.png">
<input type="text">
<textarea></textarea>
<iframe src="https://example.com"></iframe>

这类元素的最终显示内容,不是靠普通子节点直接渲染,而是由浏览器“替换”为另一种内容:

  • 图片资源
  • 输入控件
  • 内嵌页面
  • 视频播放器
  • 音频播放器

所以叫 replaced elements

你可以把它理解成:

浏览器看到这个标签,不是按普通文本盒子来画,而是把它“换成”一个特殊内容来显示。


三、常见的替换元素有哪些

常见替换元素包括:

  • img
  • input
  • textarea
  • select
  • option
  • button(通常在讨论里也常按特殊表单控件理解)
  • iframe
  • video
  • audio
  • embed
  • object

其中前端开发最常接触的是:

  • img
  • input
  • textarea
  • select
  • iframe
  • video

四、普通元素和替换元素的本质区别

这一部分最重要。

1. 普通元素:内容来自 DOM 子节点

例如:

<div>我是内容</div>
<span>我是内容</span>

这些元素的内容来自:

  • 文本节点
  • 子元素节点
  • 普通文档流布局

它们本质上是一个“容器”。


2. 替换元素:内容来自外部资源或浏览器控件

例如:

<img src="dog.png">
<input type="text">
<iframe src="https://example.com"></iframe>

这些元素显示出来的内容不是普通子节点决定的,而是:

  • 外部资源
  • 浏览器内建控件
  • 特殊渲染机制

它们更像“嵌入一个对象”,而不是普通内容容器。


3. 所以它们的布局行为也会不同

这就是关键:

因为替换元素不是普通文本流内容,所以浏览器在计算它们尺寸、对齐方式、盒模型行为时,规则会和普通元素不完全一样。

这也是为什么 img / input 明明常常是“行内”的,却又跟 span 完全不是一种感觉。


五、为什么 img / input 和普通行内元素不一样

这是初学者最常见的疑问。

1. span 是普通行内元素

例如:

<span>hello</span>

span 的特点是:

  • 默认 display: inline
  • 像文字一样参与行内排版
  • width / height 通常不直接生效
  • 更像一句话中的某个词

它本质上是一个普通行内盒子。


2. img / input 常常也是行内参与排版,但它们是替换元素

例如:

<img src="a.png" alt="">
<input type="text">

它们虽然经常也能和文字排在一行,看起来像“行内元素”,但它们本质上不是普通文字盒子,而是:

  • 图片对象
  • 输入控件对象

所以浏览器会把它们当成一种特殊的行内盒子来处理。

这类元素通常属于:

行内替换元素

也就是说:

  • 它们在外部排版上经常是行内参与
  • 但在内部本质上不是普通文本盒子

所以它们常常会有这些表现:

  • 可以设置宽高
  • 有自己的天然尺寸
  • 有特殊的基线对齐行为
  • 和文字对齐时容易出现“底部空隙”问题

六、行内替换元素和普通行内元素的区别

1. 普通行内元素

例如:

<span>text</span>
<a href="#">link</a>
<strong>strong</strong>

特点:

  • 参与文本流排版
  • 更像一个“文字片段”
  • 宽高通常不好直接控制
  • 上下 margin 行为不如块级明显

2. 行内替换元素

例如:

<img src="a.jpg">
<input type="text">

特点:

  • 也能出现在一行中
  • 但不是普通文字片段
  • 通常可以设置宽高
  • 有固有尺寸(intrinsic size)
  • 受基线、行框、垂直对齐等规则影响明显

3. 最直白的区别

可以这么记:

  • span:像字
  • img:像一个嵌入进句子里的“小物件”
  • input:像一个嵌入进句子里的“控件”

它们虽然都能出现在一行,但绝对不是同一种东西。


七、几个最容易踩坑的点

1. 为什么 img 底部总有一点空白

这是一个非常经典的问题。

例如:

<div class="box">
  <img src="a.jpg" alt="">
</div>

很多人会发现图片底下总有一点缝。

这通常不是 margin,也不是 padding,而是因为:

img 默认是行内替换元素,会按文本基线参与对齐。

而文字排版时,基线下面会给字母的下行部分预留空间,所以图片也会受这个规则影响,看起来底下多了一点空白。

常见解决方法:

img {
  display: block;
}

或者:

img {
  vertical-align: middle;
}

或者:

img {
  vertical-align: bottom;
}

2. 为什么 span 不能好好设宽高,但 img 可以

因为 span 是普通非替换行内元素,img 是行内替换元素。

  • 普通行内元素更像文字
  • 替换元素更像嵌入对象

浏览器对它们的尺寸规则不同。


3. 为什么 input 看起来像行内,但尺寸又很好控制

也是因为它不是普通行内文本盒子,而是浏览器实现的表单控件。

所以:

  • 它常常能和文字在一行
  • 但又能像一个小盒子一样设置宽高

4. 替换元素不是“特殊块级元素”

这一点要注意。

很多初学者会误以为:

能设置宽高 = 块级元素

这是错的。

imginput 往往仍然是行内参与布局,只不过它们属于替换元素,所以尺寸行为和普通行内元素不同。


八、真实开发里怎么理解最实用

真正开发时,你不需要背一大堆规范术语,但你一定要形成下面这个判断方式:

判断第一步:它是不是普通文本盒子?

  • 是:那就按普通块级 / 行内元素来理解
  • 不是:那很可能是替换元素或特殊控件

判断第二步:它是不是“嵌入对象”?

如果一个元素更像:

  • 图片
  • 输入框
  • 下拉框
  • 视频播放器
  • 内嵌页面

那你就应该立刻想到:

这不是普通文字流里的盒子,而是浏览器嵌进去的特殊对象。


判断第三步:遇到布局怪异时,优先检查这些

对于 img / input / iframe 之类元素,优先检查:

  • display
  • vertical-align
  • 宽高
  • 行高 line-height
  • 是否受基线对齐影响

九、一张表总结

对比项普通行内元素行内替换元素
例子spanastrongimginput
是否像文字片段不是
内容来源DOM 文本 / 子节点外部资源或浏览器控件
是否常在一行
是否容易设置宽高通常不行通常可以
是否有固有尺寸通常没有通常有
是否容易受基线影响更明显

十、结论

理解替换元素之后,很多以前觉得奇怪的现象都会一下子顺:

  • 为什么 spanimg 明明都能在一行里,却表现完全不同
  • 为什么 img 会有底部空白
  • 为什么 input 像行内元素,却又能设置宽高
  • 为什么表单控件总有点“不像普通标签”

最后用一句话收尾:

普通行内元素更像文字的一部分,而替换元素更像嵌入到页面中的一个对象。

这就是它们行为差异的根本原因。