可替換元素(英文: replaced element), 起初只是想了解什么是"可替換元素", 但是看了幾個(gè)解釋也理解不了, 所以接著又查了不少資料, 最終結(jié)果是本文有鉆牛角尖的嫌疑.
先看MDN的解釋:
CSS 里,可替換元素(replaced element)的展現(xiàn)不是由CSS來控制的。這些元素是一類外觀渲染獨(dú)立于CSS的外部對象。 典型的可替換元素有
<img>、<object>、<video>和 表單元素,如<textarea>、<input>。 某些元素只在一些特殊情況下表現(xiàn)為可替換元素,例如<audio>和<canvas>。 通過 CSScontent屬性來插入的對象 被稱作 匿名可替換元素(anonymous replaced elements)。
"這些元素是一類外觀渲染獨(dú)立于CSS的外部對象"是什么意思? 理解不了. 后面又找到 CSS2.1規(guī)范中的定義
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.
最有用的當(dāng)屬第一句和最后一句, 第一句的"outside the scope of the CSS formatting model"和上面的"外觀渲染獨(dú)立于CSS"解釋相似, 那所謂的"CSS formatting model"是什么東西? 規(guī)范里面有兩章描述這個(gè) Visual formatting model 和 Visual formatting model details, 這就脫離了本文討論的東西了(實(shí)際上是我看不懂...). 不過最后一句還是好懂的, CSS"不干預(yù)"可替換元素的內(nèi)容, 那也就是說CSS里面設(shè)置的content對可替換元素?zé)o效. 在 stackoverflow 上也找到一個(gè)關(guān)于這個(gè)問題的回答 Is HTML label a replaced element?, 里面提到這么一種驗(yàn)證思路:
You cannot apply generated content to replaced elements. That is, you cannot apply the pseudo-element selectors :before or :after to them.
既然這樣, 就寫份 HTML 驗(yàn)證一下
<!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>表現(xiàn)</th>
</tr>
</thead>
<tbody>
<tr>
<td>label</td>
<td><label for="">標(biāo)簽</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">選項(xiàng) 1</option>
<option value="2">選項(xiàng) 2</option>
<option value="3">選項(xiàng) 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 的渲染效果.


兩個(gè)瀏覽器渲染結(jié)果是不同的, 差異集中在 input 那塊. 這里有一篇關(guān)于這個(gè)問題的討論: CSS generated content on replaced elements, 文章中有幾個(gè)開發(fā)者表達(dá)了自己的看法(主要是對 Chrome 的渲染結(jié)果), 有說是 bug 的, 也有說是 feature 的. 不過這貌似還是沒解決問題.
后面又找到了 W3C 文檔里面提供的瀏覽器對元素和控件的渲染參考, 里面有兩個(gè)小節(jié)值得注意: 可替換元素 和 非可替換元素, 按照里面的分類, 屬于可替換元素的有: embed, iframe, video, img, input[type=image](即 Image Button), 特定情況下的 audio, canvas, object, 其他的都屬于非可替換元素.
一路下來, 實(shí)際上也并沒有找到一個(gè)規(guī)范或定義, 可以嚴(yán)格分類可替換元素和非可替換元素, 倘若一定要選出最靠譜, 那我認(rèn)為是 W3C 給出的渲染參考里面的分類. 不過文章開頭也說了, 本文有鉆牛角尖的嫌疑, 實(shí)際上弄清楚哪些元素是可替換元素并不應(yīng)該成為目的, 更多是為學(xué)習(xí)(寫) CSS 服務(wù)的, 所以其實(shí)更應(yīng)該花時(shí)間弄清楚 "CSS rendering model" .