HTML5 自閉標籤(Self-Closing Tag)誤用案例
0 | 3,574 |
踩到一個地雷。從舊專案搬了網頁到新專案,有些文字顯示不出來,花了點時間追查,發現是因為某 jQuery 元件用了 <span class="..." />
這種不合法寫法,舊專案為相容 IE 還在用 jQuery 用 1.12 版,搬到改用 jQuery 3.6 的新專案就壞掉了!
XML 語法中 <elementTag ...></elementTag>
與 <elementTag ... />
意義相同且可互換;但依據 HTML5 規範,Self-Closing Tag 只能用在 Void Element (包含 area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr) 以及 Foreign Element (MathML 及 SVG 元素)。因此,<span ... />
並不是合法寫法,可視為元件程式庫的 Bug。這次遇到出錯案例為 <span class="icon" /><span>xxx</span>
,被瀏覽器解讀為 <span class="icon"><span>xxx</span></span>
,等同 xxx 被包在 <span class="icon">
裡,而 .icon 樣式有設定固定寬高及超出範圍隱藏(overflow: hidden),導致包在其中 xxx 無法完整顯示。
但,既然有錯,這麼多年下來為什麼沒爆?是因為該元件靠 jQuery append('<span class="icon" /><span>xxx</span>')
將 HTML 轉成 DOM,在 jQuery 1.X 的執行結果是 <span class="icon"></span><span>xxx</span>
,陰錯陽差修正問題。但 jQuery 3.6 行為改變,會保留原有 <span class="icon" /><span>xxx</span>
格式,因而東窗事發。
找出問題根源,也確認 HTML5 對自閉標籤的規定,用下面的範例為本茶包劃上完美句點。
補充:程式包含一個較少用的技巧,網頁同時載入 jQuery 3.6 及 jQuery 1.12,靠 jQuery.noConflict() 讓二者並存,這個 API 十幾年前就學到,還真沒想過有派上用場的一天,哈。
<!DOCTYPE html>
<html>
<hea>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>var $jq36 = jQuery.noConflict();</script>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script>var $jq112 = jQuery.noConflict();</script>
<style>
.square {
display: inline-block;
width: 20px;
height: 20px;
background-color: lightseagreen;
overflow: hidden;
}
dd {
padding: 6px; margin-left: 20px;
}
</style>
</hea>
<body>
<dl>
<dt>Normal SPAN</dt>
<dd>
<span class="square"></span>
<span>Text</span>
</dd>
</dl>
<dl>
<dt>Self-Closed SPAN</dt>
<dd>
<span class="square" />
<span>Text</span>
</dd>
</dl>
<dl>
<dt>jQuery.append Self-Closed SPAN (v3.6)</dt>
<dd class="jqtest3">
</dd>
</dl>
<dl>
<dt>jQuery.append Self-Closed SPAN (v1.12)</dt>
<dd class="jqtest1">
</dd>
</dl>
<script>
$jq36('.jqtest3').append('<span class="square" /><span>Text</span>');
$jq112('.jqtest1').append('<span class="square" /><span>Text</span>');
</script>
</body>
</html>
由上到下分別測試:正常 Span、自閉 Sapn、使用 jQuery 3.6 append() 轉換自閉 Span、使用 jQuery 1.12 轉換自閉 Span:
[2022-10-18 更新] 感謝讀者 Nickchen Nick 補充,jQuery 於 3.5 版 修正 jQuery.htmlPrefilter HTML 標籤自動修正功能以防範 XSS 攻擊。透過 jQuery Migrate Plugin 可恢復舊版行為,但需酌斟風險。
A case of using invalid self-closing SPAN in HTML5 browser causes incorrect display.
Comments
Be the first to post a comment