在编程语言中,字符串 直接量(Literal Value,也叫字面量)需要用一对分隔符来定义, 比如 "author:harttle" 中前后的引号。 那么当字符串中要表示分隔符时就需要 转义,比如 "author:\"harttle\""

JavaScript 是一种 通用编程语言,这类语言的转义相对比较一致通常使用反斜线,比如 \n, \r 等。 但是在 HTML、CSS 这样的 领域特定语言 中为了在大多数场景中提供更简单的语法, 转义就会比较麻烦。下文中给出 HTML 和 CSS 中的字符串转义机制,以及如何进行转义的代码片段。

本文介绍的是 HTML 和 CSS 中的转义,不是 JavaScript 中的 escape 方法(它可以产生一个类似 URL 编码的结果)。 此外关于百分号编码请参考 百分号编码与 encodeURIComponent,关于表单编码请参考 HTTP 表单编码 enctype

HTML 中的转义字符

html 是一种标记语言,就像其他编程语言一样,它可以表示包括它的语法在内的所有字符。但 HTML 中反斜线不是转义字符,而是以 & 起始的字符串。 这里有一个 HTML 特殊字符码表HarttleLand 站的主题中就使用了很多的这些字符。

HTML 转义语法

  • & + ASCII 字母(ASCII Alphanumeric)。表示命名的字符引用,例如 &amp; 表示 &&lt; 表示 <。HTML5 发布了非常多 新的命名字符
  • &# + 数字。可以表示的字符包括 ASCII 字符、数学符号、希腊字母等。例如 &#38; 表示 &&#60; 表示 <
    • &#x + 16 进制数字。例如 &#x41; 表示大写字母 A
    • &# + 10 进制数字。例如 &#65; 也表示大写字母 A

哪些字符需要转义?

与通用编程语言中的转义一样,有许多字符都有转义的表示方式,但并不是所有字符都需要转义。 比如 C 语言中 \aa 的转义表示,但多数情况都不需要写成转义的形式。 HTML 也一样,

  • 标签所在的上下文(标签的内容)中需要转义(标签转义)的字符只有 &, <, >
  • 属性上下文(属性值的内容)中还需要转义(属性转义"'

参考 https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-on-html

JavaScript 中转义 HTML (消毒)

明确 HTML 转义机制后事情就好办了,下面的实现来自 StackOverflow, 其中单引号转义使用 &#039; 而非 &apos; 是由于 HTML4 的兼容性原因

// 转义结果可用于拼接标签内容,也可用于拼接属性值
function escapeHtml(str) {
    return str
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
}

在浏览器中,我们还可以利用浏览器的 HTML Fragment 序列化算法 来帮我们实现:

// 转义结果只可用于拼接标签内容
function escapeHtml(str) {
    var div = document.createElement('div')
    div.innerText = str;
    return div.innerHTML;
}

上述实现运行在标签的上线文中,因此不会转义 "'。转义后的属性不可直接拼接到属性上下文中。

CSS 中的转义字符

有时我们需要 CSS 字符串,而字符串中可能包含 CSS 特殊字符。 比如 伪元素content 属性值, 比如传给 getElementsByClassName() 的类名 (当然一般也不会把 class 命名为 CSS 特殊字符)。CSS 使用反斜线(\)转义,规则是:

  • ASCII 字符可以使用 \ + 一个 ASCII 字符来转义,例如 \; 表示分号。
  • Unicode 字符(包括与上述 ASCII 码表重合的部分)使用 \ + 6 位数字表示,例如 \000030 表示字符 "1"
  • 对于第二种情况,不足 6 位时为避免歧义后面可加空格分隔,这个空格总会被当做分隔符,不会被当做内容。

例如 \30 a 表示 "0a",相当于 \000030a\30a 则表示单个 Unicode 字符 U+030A

JavaScript 中转义 CSS

CSS Object Model 中提供了 CSS.escape() 方法来转义 CSS 字符串。例如:

var escaped = CSS.escape(';:"\'[]{}')
console.log(escaped)
// 输出 \;\:\"\'\[\]\{\}

另一个常用的场景是 iconfont 中设置 ::before 伪元素的 content

.icon::before {
    font-family: 'icon-by-harttle';
    content: '\e622';
}

本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2018/05/15/html-css-escape.html。如有疏漏、谬误、侵权请通过评论或 邮件 指出。