Unicode Variation Selector-15 and some of my tears
Unicode Variation Selector-15 and some of my tears
Unicode 变体选择符-15 与我的一些眼泪
July 13, 2026 2026年7月13日
From my phone, I noticed that my website was displaying footnote backlink glyphs as emoji in my RSS reader. It had not always been this way. I opened the same page from a desktop browser and saw what I expected to see: a text-like pictograph, in my article body’s font face. No emoji to be found. 在手机上,我注意到我的网站在 RSS 阅读器中将脚注回链符号显示为了 Emoji。以前并非如此。我在桌面浏览器中打开同一页面,看到了我预期的效果:一个文本样式的象形符号,显示为我文章正文的字体。完全没有 Emoji 的踪影。
I checked the HTML document source: <a href="#fnref:1" class="reversefootnote" role="doc-backlink"> ↩ </a> The RSS feed XML contained the same. So, that can be presented as either text or an emoji? ↩ is an HTML representation of the Unicode codepoint U+21A9, Leftwards Arrow with Hook.
我检查了 HTML 文档源码:<a href="#fnref:1" class="reversefootnote" role="doc-backlink"> ↩ </a>。RSS 订阅源的 XML 中也包含同样的内容。所以,同一个符号既可以呈现为文本,也可以呈现为 Emoji?↩ 是 Unicode 码位 U+21A9(带钩左箭头)的 HTML 表示形式。
This led me to many relevant threads, pastes, and blog posts in which others had observed similar issues with Leftwards Arrow with Hook and other, similar navigation-decoration characters. We were all reacting to U+21A9 as rendered without a Unicode standardized variation sequence specified. So it’s up to whatever program is rendering U+21A9 to decide what to do. Which version, the text or the emoji, should U+21A9 render. 这引导我找到了许多相关的讨论串、代码片段和博客文章,其他人也观察到了带钩左箭头以及其他类似的导航装饰字符存在类似问题。我们遇到的情况都是 U+21A9 在没有指定 Unicode 标准化变体序列的情况下被渲染。因此,决定权取决于渲染 U+21A9 的程序——它决定该渲染文本版本还是 Emoji 版本。
I found the correct solution and some less correct solutions to this issue. Before I describe them, I want to explore a slightly larger problem introduced by variation selectors. 我找到了解决此问题的正确方案以及一些不太完美的方案。在描述它们之前,我想探讨一下由变体选择符(Variation Selectors)引入的一个更大的问题。
The downstream effects
下游影响
For meta-ish content characters like backlink glyphs, the way forward is clear for people who are technical: fix and/or configure the thing that builds your web pages. Or complain in the direction of the people who can fix and/or configure the thing. For many of the other characters, it’s more complicated. Many of these characters are used in body content to be expressive. Rendering the text presentation instead of the emoji presentation, at worst, could be a mistranslation. 对于像回链符号这类元数据性质的字符,技术人员的处理方式很明确:修复或配置构建网页的工具。或者向能够修复或配置该工具的人反馈。但对于许多其他字符,情况就复杂多了。这些字符中有许多被用于正文中以表达情感。将文本呈现方式渲染为 Emoji 呈现方式,往坏了说,可能会导致语义误传。
The technical standard (see the emoji-data links, and specifically emoji-data.txt) lists over 1,000 Unicode codepoints that have both text and emoji presentations. 技术标准(参见 emoji-data 链接,特别是 emoji-data.txt)列出了超过 1,000 个同时拥有文本和 Emoji 呈现方式的 Unicode 码位。
| Codepoint | Glyph | As text(+U+FE0E) | As emoji(+U+FE0F) |
|---|---|---|---|
| U+00A9 | © | ©︎ | ©️ |
| U+00AE | ® | ®︎ | ®️ |
| U+2328 | ⌨ | ⌨︎ | ⌨️ |
| U+25B6 | ▶ | ▶︎ | ▶️ |
| U+2603 | ☃ | ☃︎ | ☃️ |
| U+2620 | ☠ | ☠︎ | ☠️ |
| U+267B | ♻ | ♻︎ | ♻️ |
| U+1F310 | 🌐 | 🌐︎ | 🌐️ |
| U+1F312 | 🌒 | 🌒︎ | 🌒️ |
| U+1F37C | 🍼 | 🍼︎ | 🍼️ |
| U+1F441 | 👁 | 👁︎ | 👁️ |
| U+1F509 | 🔉 | 🔉︎ | 🔉️ |
| U+1F590 | 🖐 | 🖐︎ | 🖐️ |
| U+1F635 | 😵 | 😵︎ | 😵️ |
| U+1F636 | 😶 | 😶︎ | 😶️ |
Table 1: A small sampling of the 1,000+ Unicode codepoints that have both text and emoji presentations. 表 1:1,000 多个同时拥有文本和 Emoji 呈现方式的 Unicode 码位的一小部分采样。
The Glyph column may look different to you, depending on the application you’re using to read this article. I would hope the +U+FE0E and +U+FE0F columns do render the same way for everyone. “Glyph”(字形)列在您看来可能有所不同,这取决于您阅读本文所使用的应用程序。我希望 +U+FE0E 和 +U+FE0F 列对每个人都能呈现出相同的效果。
There is no obvious, cut-and-dry user experience for writers here. Pictographs and emoji are regular text as far as most programs are concerned, and variation selectors remain invisible unless you go looking. Did the author mean to present an umbrella ⛱︎ or an umbrella ⛱️ ? We don’t know what their writing tool presented to them during editing. They don’t know that we don’t see what they think we see when we’re reading the thing. 对于作者来说,这里没有显而易见、一刀切的用户体验。对于大多数程序而言,象形符号和 Emoji 就是普通文本,除非你刻意去寻找,否则变体选择符是不可见的。作者是想表达一把伞 ⛱︎ 还是另一把伞 ⛱️?我们不知道他们的写作工具在编辑时向他们展示了什么。他们也不知道,当我们阅读时,我们看到的与他们以为我们看到的并不一样。
In a perfect world, all software knows about and inserts variation selectors for the user. In reality, we know that software is bad. I found documentation that indicates that the Unicode Technical Committee is aware that variation selectors are complicated, and maybe weren’t the best strategy. But what’s done is done and can’t be undone when it comes to the Unicode Standard. 在理想世界中,所有软件都能识别并为用户插入变体选择符。但在现实中,我们知道软件往往不尽如人意。我找到的文档显示,Unicode 技术委员会意识到变体选择符很复杂,或许并不是最佳策略。但 Unicode 标准一旦确立,覆水难收。
The most correct solution
最正确的解决方案
You can specify, in your source document, which version you want rendered. You do this by combining the variation selector codepoint with the preceding codepoint you want to render. In my case, that’s U+FE0E, Variation Selector-15. 你可以在源文档中指定你想要渲染的版本。方法是将变体选择符码位与你想要渲染的前置码位结合起来。就我而言,即使用 U+FE0E,即变体选择符-15。
Using my source document’s backlink HTML markup as an example:
以我的源文档中的回链 HTML 标记为例:
<a href="#fnref:1" class="reversefootnote" role="doc-backlink"> ↩︎ </a>
And, if I wanted, I could do the opposite: force the emoji presentation, using U+FE0F, Variation Selector-16. 如果我愿意,也可以反其道而行之:使用 U+FE0F(变体选择符-16)强制显示为 Emoji 版本。
(Fig. 1, 2, 3 omitted for brevity) (图 1、2、3 省略)
As I’ve already mentioned, which variant you see sans-selector can differ per application. So, I can fix this issue for myself. I’m fortunate that I build the software that generates this website; and I’m fortunate that the library I use to generate HTML from my Markdown source documents (Kramdown) has a configurable footnote backlink glyph. There are authors using the Mistune library (for example, via the Bear blogging platform), or perhaps some other niche content rendering library, that don’t have the same luxury as of this writing. 正如我之前提到的,在没有选择符的情况下,你看到的变体取决于具体的应用程序。因此,我可以自行修复这个问题。我很幸运,因为我构建了生成该网站的软件;我也很幸运,我用来从 Markdown 源文档生成 HTML 的库(Kramdown)支持配置脚注回链符号。而截至本文撰写时,使用 Mistune 库(例如通过 Bear 博客平台)或其他小众内容渲染库的作者,可能就没有这样的便利了。
Some less reliable solutions
一些不太可靠的解决方案
If you’re in a position where you don’t control the software that builds HTML from your source documents, and, for some reason, it’s not possible to insert a variation selector character where you want it, there are some other things you can try. (At least for applications that use CSS for document presentation, like web browsers.) 如果你无法控制将源文档构建为 HTML 的软件,且由于某种原因无法在需要的地方插入变体选择符,你可以尝试其他方法。(至少对于使用 CSS 进行文档呈现的应用程序,如网页浏览器,是可行的。)
font-variant-emoji
The font-variant-emoji CSS property is not currently supported in Safari. Hopefully it will be soon. It allows you to specify the preferred presentation of unicode characters for which ever DOM elements you like:
font-variant-emoji CSS 属性目前在 Safari 中尚不支持。希望很快能得到支持。它允许你为任意 DOM 元素指定 Unicode 字符的首选呈现方式:
<article style="font-variant-emoji: text;"> <span>Umbrella ⛱</span>, or <span style="font-variant-emoji: emoji;">umbrella ⛱</span>. </article>
But I don’t think this can ever be a foolproof solution. Even wide web browser support doesn’t fully account for web content being presented by non–web browser applications like feed readers, and so on. 但我认为这永远无法成为万无一失的方案。即使网页浏览器得到广泛支持,也无法完全覆盖那些由非浏览器应用程序(如 RSS 阅读器等)呈现的网页内容。
font-family: monospace
If you want an even less reliable solution, setting the font-family CSS property to the value monospace sometimes works:
如果你想要一个更不可靠的方案,将 font-family CSS 属性设置为 monospace 有时也能奏效:
<article> <span style="font-family: monospace;">Umbrella ⛱</span>, or <span>umbrella ⛱</span>. </article>