可替换元素(英文: replaced element), 起初只是想了解什么是"可替换元素", 但是看了几个解释也理解不了, 所以接着又查了不少资料, 最终结果是本文有钻牛角尖的嫌疑.
先看MDN的解释:
CSS 里,可替换元素(replaced element)的展现不是由CSS来控制的。这些元素是一类外观渲染独立于CSS的外部对象。 典型的可替换元素有
<img>
、<object>
、<video>
和 表单元素,如<textarea>
、<input>
。 某些元素只在一些特殊情况下表现为可替换元素,例如<audio>
和<canvas>
。 通过 CSScontent
属性来插入的对象 被称作 匿名可替换元素(anonymous replaced elements)。
"这些元素是一类外观渲染独立于CSS的外部对象"是什么意思? 理解不了. 后面又找到 CSS2.1规范中的定义
An element whose content is outside the scope of the CSS formatting model, such as an image, embedded document, or applet. For example, the content of the HTML IMG element is often replaced by the image that its "src" attribute designates. Replaced elements often have intrinsic dimensions: an intrinsic width, an intrinsic height, and an intrinsic ratio. For example, a bitmap image has an intrinsic width and an intrinsic height specified in absolute units (from which the intrinsic ratio can obviously be determined). On the other hand, other documents may not have any intrinsic dimensions (for example, a blank HTML document).
User agents may consider a replaced element to not have any intrinsic dimensions if it is believed that those dimensions could leak sensitive information to a third party. For example, if an HTML document changed intrinsic size depending on the user's bank balance, then the UA might want to act as if that resource had no intrinsic dimensions.
The content of replaced elements is not considered in the CSS rendering model.
最有用的当属第一句和最后一句, 第一句的"outside the scope of the CSS formatting model"和上面的"外观渲染独立于CSS"解释相似, 那所谓的"CSS formatting model"是什么东西? 规范里面有两章描述这个 Visual formatting model 和 Visual formatting model details, 这就脱离了本文讨论的东西了(实际上是我看不懂...). 不过最后一句还是好懂的, CSS"不干预"可替换元素的内容, 那也就是说CSS里面设置的content对可替换元素无效. 在 stackoverflow 上也找到一个关于这个问题的回答 Is HTML label a replaced element?, 里面提到这么一种验证思路:
You cannot apply generated content to replaced elements. That is, you cannot apply the pseudo-element selectors :before or :after to them.
既然这样, 就写份 HTML 验证一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Replaced Elements</title>
<style>
tbody td {
padding: 10px 20px;
}
tbody > tr > td:nth-child(2) > *:before {
content: "«";
color: blue;
}
tbody > tr > td:nth-child(2) > *:after {
content: "»";
color: red;
}
</style>
</head>
<body>
<table border="1">
<thead>
<tr>
<th>元素</th>
<th>表现</th>
</tr>
</thead>
<tbody>
<tr>
<td>label</td>
<td><label for="">标签</label></td>
</tr>
<tr>
<td>button</td>
<td>
<button>按钮</button>
</td>
</tr>
<tr>
<td>img</td>
<td><img src="https://iph.href.lu/200x50?text=img" alt=""></td>
</tr>
<tr>
<td>select</td>
<td>
<select name="" id="">
<option value="1">选项 1</option>
<option value="2">选项 2</option>
<option value="3">选项 3</option>
</select>
</td>
</tr>
<tr>
<td>meter</td>
<td>
<meter value="0.3"></meter>
</td>
</tr>
<tr>
<td>progress</td>
<td>
<progress value="0.3"></progress>
</td>
</tr>
<tr>
<td>textarea</td>
<td><textarea name="" id="" cols="30" rows="3">文本</textarea></td>
</tr>
<tr>
<td>input[type=text]</td>
<td><input type="text" value="输入框"></td>
</tr>
<tr>
<td>input[type=radio]</td>
<td><input type="radio"></td>
</tr>
<tr>
<td>input[type=checkbox]</td>
<td><input type="checkbox"></td>
</tr>
<tr>
<td>input[type=range]</td>
<td><input type="range"></td>
</tr>
<tr>
<td>input[type=file]</td>
<td><input type="file"></td>
</tr>
<tr>
<td>input[type=image]</td>
<td><input type="image" src="https://iph.href.lu/200x50?text=input[type=image]"></td>
</tr>
<tr>
<td>input[type=submit]</td>
<td><input type="submit" value="提交"></td>
</tr>
<tr>
<td>iframe</td>
<td>
<iframe src="http://www.baidu.com" frameborder="1"></iframe>
</td>
</tr>
<tr>
<td>object[type=image/png]</td>
<td>
<object data="httpshttps://iph.href.lu/200x50?text=object" type="image/png"></object>
</td>
</tr>
<tr>
<td>embed[type=image/png]</td>
<td>
<embed type="image/png" src="https://iph.href.lu/200x50?text=embed">
</td>
</tr>
<tr>
<td>hr</td>
<td>
<hr>
</td>
</tr>
<tr>
<td>br</td>
<td>换行前<br>换行后</td>
</tr>
</tbody>
</table>
</body>
</html>
下面两张图是 Win7 分别在 Chrome68 和 Firefox62 的渲染效果.
两个浏览器渲染结果是不同的, 差异集中在 input 那块. 这里有一篇关于这个问题的讨论: CSS generated content on replaced elements, 文章中有几个开发者表达了自己的看法(主要是对 Chrome 的渲染结果), 有说是 bug 的, 也有说是 feature 的. 不过这貌似还是没解决问题.
后面又找到了 W3C 文档里面提供的浏览器对元素和控件的渲染参考, 里面有两个小节值得注意: 可替换元素 和 非可替换元素, 按照里面的分类, 属于可替换元素的有: embed, iframe, video, img, input[type=image](即 Image Button), 特定情况下的 audio, canvas, object, 其他的都属于非可替换元素.
一路下来, 实际上也并没有找到一个规范或定义, 可以严格分类可替换元素和非可替换元素, 倘若一定要选出最靠谱, 那我认为是 W3C 给出的渲染参考里面的分类. 不过文章开头也说了, 本文有钻牛角尖的嫌疑, 实际上弄清楚哪些元素是可替换元素并不应该成为目的, 更多是为学习(写) CSS 服务的, 所以其实更应该花时间弄清楚 "CSS rendering model" .