简体   繁体   English

如何防止 Unicode 字符在 JavaScript 中呈现为 HTML 中的表情符号?

[英]How to prevent Unicode characters from rendering as emoji in HTML from JavaScript?

["

I'm finding Unicode for special characters from FileFormat.Info's search<\/a> .<\/i>我正在从FileFormat.Info 的 search<\/a>中找到特殊字符的 Unicode。<\/b><\/p>

Some characters are rendering as the classic black-and-white glyphs, such as ⚠ (warning sign, \⚠<\/code> or &#x26a0;<\/code> ).<\/i>一些字符呈现为经典的黑白字形,例如 ⚠(警告标志, \⚠<\/code>或&#x26a0;<\/code> )。<\/b> These are preferable, since I can apply CSS styles (such as color) to them.<\/i>这些更可取,因为我可以将 CSS 样式(例如颜色)应用于它们。<\/b><\/p>

\"警告字形的图像\"<\/a><\/p>

Others are rendering as newer cartoony emoji, such as ⌛ (hourglass, \⌛<\/code> or &#x231b;<\/code> ).<\/i>其他人则呈现为更新的卡通表情符号,例如⌛(沙漏, \⌛<\/code>或&#x231b;<\/code> )。<\/b> These are not preferable, since I cannot fully style them.<\/i>这些不是可取的,因为我无法完全设置它们的样式。<\/b><\/p>

\"沙漏表情符号的图像\"<\/a><\/p>

It appears that the browser is making this change, since I'm able to see the hourglass glyph on Mac Firefox, just not Mac Chrome nor Mac Safari.<\/i>看来浏览器正在做出这种改变,因为我能够在 Mac Firefox 上看到沙漏字形,而不是 Mac Chrome 或 Mac Safari。<\/b><\/p>

Is there a way to force browsers to display the older (flat monotone) versions to display?<\/i>有没有办法强制浏览器显示较旧的(平面单调)版本来显示?<\/b><\/p>

Update<\/strong> : It seems (from comments below) there is a text presentation selector<\/a> , FE0E<\/code> , available to enforce text-vs-emoji.<\/i>更新<\/strong>:似乎(从下面的评论中)有一个文本呈现选择器<\/a>FE0E<\/code>可用于强制执行 text-vs-emoji。<\/b> The selector is concatenated as a suffix without space onto the character's code, such as &#x231b;&#xFE0E;<\/code><\/i>选择器作为不带空格的后缀连接到字符的代码上,例如&#x231b;&#xFE0E;<\/code><\/b> for HTML hex or \⌛\︎<\/code> for JS.<\/i>用于 HTML 十六进制或\⌛\︎<\/code>用于 JS。<\/b> However, it is simply not honored by all browsers<\/em> (eg Chrome and Edge).<\/i>但是,并非所有浏览器<\/em>(例如 Chrome 和 Edge)都支持它。<\/b><\/p>"]

Append the Unicode variation selector character for forcing text, VS15, &#xFE0E;附加Unicode 变体选择符以强制文本、VS15、 &#xFE0E; . .
This forces the previous character to be rendered as text rather than as an Emoji Symbol.这会强制将前一个字符呈现为文本而不是表情符号。

<p>🔒&#xFE0E;</p>

Result: 🔒︎结果:🔒︎

Learn more at: Unicode symbol as text or emoji了解更多信息: Unicode 符号作为文本或表情符号

I had a Unicode character in the content of a span::before , and I had the font-family of the span set to "Segoe UI Symbol".我在span::beforecontent中有一个 Unicode 字符,并且我将spanfont-family设置为“Segoe UI Symbol”。 But Chrome used "Segoe UI Emoji" as the font to render it.但是 Chrome 使用“Segoe UI Emoji”作为字体来渲染它。

However, when I set the font-family to "Segoe UI Symbol" explicitly for the span::before , rather than just for the span , then it worked.但是,当我为span::before明确地font-family设置为“Segoe UI Symbol”时,而不仅仅是为span ,它就起作用了。

For a CSS-only solution to prevent iOS displaying emojis, you can use font-family: monospace which defaults to the text variant of the glyph rather than the emoji variant:对于阻止 iOS 显示表情符号的纯 CSS 解决方案,您可以使用font-family: monospace ,它默认为字形的文本变体而不是表情符号变体:

 <p>Normal character: ↩</p> <p>Monospace character: <span style="font-family: monospace">↩</span></p>

If your primary concern is forcing monochromatic display so the emoji don't stand out from the text too much, CSS filters, either alone or in combination with the Unicode variation selector, may be something you want.如果您主要关心的是强制单色显示以使表情符号不会从文本中脱颖而出,那么 CSS 过滤器(单独或与 Unicode 变体选择器结合使用)可能是您想要的。

 p.gscale { -webkit-filter: grayscale(100%); filter: grayscale(100%); } a { color: #999; -webkit-filter: grayscale(100%) sepia(100%) saturate(400%) hue-rotate(170deg); filter: grayscale(100%) sepia(100%) saturate(400%) hue-rotate(170deg); }
 <p class="gscale">You've now got emoji display on 🔒lockdown🔒.</p> <p>External Link: <a href="https://knowyourmeme.com/memes/party-hard">celebrate 🎉</a></p>

Unlike the variation selector, it shouldn't matter how the emoji are rendered, because CSS filters apply to everything.与变体选择器不同,表情符号的呈现方式无关紧要,因为 CSS 过滤器适用于所有内容。 (I use them to grayscale PNG-format "link type" icons on hyperlinks that have been modified to point to the Wayback Machine.) (我使用它们对已修改为指向 Wayback Machine 的超链接上的 PNG 格式的“链接类型”图标进行灰度化。)

Just mind the caveat .请注意警告 You can't override a parent element's filter in a child, so this technique can't be used to grayscale a paragraph, then re-colorize the links within it.您不能在子元素中覆盖父元素的过滤器,因此不能使用此技术对段落进行灰度化,然后重新着色其中的链接。 😢 😢

...still, it's useful for situations where you're either going to be making the whole thing a hyperlink or disallowing rich markup within it. ...不过,它对于您将整个事物设为超链接或不允许其中包含丰富标记的情况很有用。 (eg. titles and descriptions) (例如标题和描述)

However, this won't work unless CSS actually gets applied, so I'll give a second option which is more reliable in <title> elements than the Unicode variation selector (I'm looking at you GitHub. I don't like fake icons in my browser tabs):但是,除非实际应用了 CSS,否则这将不起作用,因此我将提供第二个选项,它在<title>元素中比 Unicode 变体选择器更可靠(我在看你的 GitHub。我不喜欢假我的浏览器标签中的图标):

If you're putting a user-provided string into a <title> element, filter out the emoji along with any bold/italic/underline/etc.如果您将用户提供的字符串放入<title>元素中,请过滤掉表情符号以及任何粗体/斜体/下划线/等。 markup.标记。 (Yes, for those who missed it, the standard does call for the contents of <title> to be plain text aside from the ampersand escapes and the browsers I tested all interpret tags within as literal text.) (是的,对于那些错过它的人,标准确实要求<title>的内容是纯文本,除了 & 符转义和我测试的浏览器将所有标签解释为文字文本。)

The two ways I can think of are:我能想到的两种方法是:

  1. Directly use a manually-maintained regex which matches the blocks where the newest version of Unicode puts its emoji and their modifiers.直接使用手动维护的正则表达式,它与最新版本的 Unicode 放置其表情符号及其修饰符的块相匹配。
  2. Iterate through the grapheme clusters and discard any which contain recognized emoji codepoints.遍历字素簇并丢弃任何包含已识别的表情符号代码点的内容。 (A grapheme cluster is a base glyph plus all the diacritics and other modifiers which make up the visible character. The example I link to uses Python's regex engine to tokenize and then the emoji package for the database, but Rust is a good example of a language where iterating grapheme clusters is quick and easy via a crate like unicode-segmentation .) (字素簇是一个基本字形加上构成可见字符的所有变音符号和其他修饰符。我链接到的示例使用 Python 的正则表达式引擎进行标记,然后使用数据库的emoji包,但 Rust 是一个很好的例子通过像unicode-segmentation这样的 crate 可以快速轻松地迭代字素簇的语言。)

None of the other solutions worked for me but I eventually found something that did courtesy of css-tricks .其他解决方案都不适合我,但我最终发现了一些由css-tricks提供的东西。 In my use case, I was adding a link symbol at the end of each markdown header for direct linking to sections within articles but the emoji symbol looked a bit distracting.在我的用例中,我在每个 Markdown 标题的末尾添加了一个链接符号,用于直接链接到文章中的部分,但表情符号看起来有点分散注意力。 The following code allowed me to make the emoji look like a plain symbol and then switch back to looking like an emoji when hovered over which was perfect for my use case.下面的代码让我可以让表情符号看起来像一个普通的符号,然后在悬停在上面时切换回看起来像一个表情符号,这非常适合我的用例。 If you just want to make the icon look more like a symbol just change the text-shadow hexadecimal color to #000 as shown in the second example.如果您只是想让图标看起来更像一个符号,只需将 text-shadow 十六进制颜色更改为 #000,如第二个示例所示。

 .direct-link { color: transparent; text-shadow: 0 0 #dbe2ec; } .direct-link:hover { color: inherit; }
 <h3>Blog Subheading<a href='#' class="direct-link">🔗</a></h3>

 .direct-link { color: transparent; text-shadow: 0 0 #000; }
 <h3>Blog Subheading<a href='#' class="direct-link">🔗</a></h3>

Android fonts are not rich as you may expect. Android 字体并不像你想象的那样丰富。 Font files don't have these exotic glyph and Android has a hack for few characters without glyph.字体文件没有这些奇异的字形,Android 对没有字形的少数字符进行了破解。 They are replaced with icons.它们被图标替换。

So solution is to integrate the site with a web font (woff).所以解决方案是将网站与网络字体(woff)集成。 Create new font file with FontForge and pick required glyph from free serif TTF for example.例如,使用 FontForge 创建新字体文件并从免费衬线 TTF 中选择所需的字形。 Every glyph takes 1k.每个字形需要 1k。 Generate woff file.生成 woff 文件。

Prepare simple CSS to import the custom font family.准备简单的 CSS 以导入自定义字体系列。

style.css:样式.css:

@font-face {
  font-family: 'Exotic Icons';
  src: url('exotic-icons.woff') format('woff');
}

.exotic-symbol-font {
    position: relative;
    top: 1px;
    display: inline-block;
    font-family: 'Exotic Icons';
    font-style: normal;
    font-weight: normal;
    line-height: 1;

    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

index.html file: index.html 文件:

<html>
  <head>
    <meta charset="utf-8">
    <link href="style.css" rel="stylesheet"></head>
    <title>Test custom glyphs</title>
  </head>
  <body>
    <table>
      <tr>
        <td class="exotic-symbol-font">
            😭 ☠ &#x2660; a  g
        </td>       
      </tr>
    </table>
  </body>
</html>

Google Chrome, desktop version 75, seems to disambiguate its approach to rendering Unicode characters based on the first Unicode escape it encounters while loading a page. Google Chrome 桌面版 75 似乎根据加载页面时遇到的第一个 Unicode 转义来消除其呈现 Unicode 字符的方法。 For instance, when parsed as the first HTML Unicode escape in a page source, and having no emoji equivalent, &#9207;例如,当被解析为页面源中的第一个 HTML Unicode 转义,并且没有等效的表情符号时,&#9207; seems to clarify to Chrome that the page contains escapes not to be rendered as emoji.似乎向 Chrome 澄清该页面包含不被呈现为表情符号的转义。

Expanding upon ssokolow's answer , using a filter is nice and at least makes the contours visible instead of using a simple font, but converting an RGB color into a sequence of CSS filters is very hard when you want to use a specific color.扩展ssokolow 的答案,使用过滤器很好,至少使轮廓可见,而不是使用简单的字体,但是当您想使用特定颜色时,将 RGB 颜色转换为一系列 CSS 过滤器非常困难。

A better (although quite wordy) option is to use the <feColorMatrix> SVG filter.一个更好的(虽然很冗长)选项是使用<feColorMatrix> SVG 过滤器。 Combined with the grayscale filter and the data URI scheme, you can represent the color via RGB and in-line CSS:结合灰度过滤器和数据 URI 方案,您可以通过 RGB 和内联 CSS 来表示颜色:

.violet {
  color: white;
  filter: grayscale(100%) url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='0.78 0 0 0 0  0 0.082 0 0 0  0 0 0.522 0 0  0 0 0 1 0'/></filter></svg>#f");
}

Unfortunately, you cannot interpolate the URL with data (taken from attributes or variables), but at least you don't have to calculate CSS filters from RGB.不幸的是,您不能使用数据(取自属性或变量)对 URL 进行插值,但至少您不必根据 RGB 计算 CSS 过滤器。

If none of the other answers work for you, it's possible you have one or more of these fonts in your font stack (as was the case for us):如果其他答案都不适合您,则您的字体堆栈中可能有一种或多种这些字体(就像我们的情况一样):

  • Segoe UI Emoji Segoe UI 表情符号
  • Apple Color Emoji苹果色表情符号

These are included in a number of commonly used font stacks, like the Github font stack if I'm not mistaken.这些包含在许多常用字体堆栈中,如果我没记错的话,比如 Github 字体堆栈。

My specific version of the problem我的问题的具体版本

My site is using the ◀︎ (BLACK RIGHT-POINTING TRIANGLE) and similar characters in CSS pseudo-elements ( ::after and ::before ) to indicate the current item in a list.我的网站在 CSS伪元素::after::before )中使用 ◀︎(黑色右指向三角形)和类似字符来指示列表中的当前项目。

In my tests, I always used the triangle character and the variation selector 15 together .在我的测试中,我总是将三角形字符和变体选择器 15 一起使用。 First I was using both a webfont from Google Fonts and a font installed on the device that should both have contained the glyphs for those characters, but for some reason, this assumption must have been wrong.首先,我使用了来自Google Fontswebfont安装在设备上的字体,它们都应该包含这些字符的字形,但由于某种原因,这个假设一定是错误的。 I also tried different subsets on Google Fonts, to no avail: Two of my android devices with Google Chrome and Samsung Internet (Chromium) always rendered the emoji instead of the text glyph.我还在 Google Fonts 上尝试了不同的子集,但无济于事:我的两台带有 Google Chrome 和 Samsung Internet (Chromium) 的 android 设备总是呈现表情符号而不是文本字形。

My solution我的解决方案

My solution was to download the latest WOFF of the Gnu Free Font (which I knew to contain glyphs for those characters), include it in my project, and define it using @font-face :我的解决方案是下载Gnu Free Font的最新 WOFF(我知道其中包含这些字符的字形),将其包含在我的项目中,并使用@font-face定义它:

@font-face {
  font-family: "Free Sans";
  src: url("/site/static/fonts/FreeFont/FreeSans.woff") format("woff");
}

Then, to set the styles for my pseudo elements:然后,为我的伪元素设置样式:

span.current::after {
  font-family: "Free Sans", $universal-font-family ! important;
}

Discussion讨论

I'm not yet sure about the performance impact of using that 786K extra font just for those few characters.我还不确定仅对这几个字符使用 786K 额外字体对性能的影响。 If that becomes a problem, it should be possible to use a stripped-down custom font with just those characters instead.如果这成为问题,则应该可以使用仅包含这些字符的精简自定义字体。

I dont know of a way to turn off the emoji type rendering.我不知道关闭表情符号类型渲染的方法。 Usually I use an icon font such as font awesome or glyphicons (comes with Bootstrap 3).通常我使用图标字体,例如font awesomeglyphicons (Bootstrap 3 附带)。

The benefit of using these over the unicode characters is that使用这些而不是 unicode 字符的好处是

  1. you can choose from many different styles so it fits the design of your site;您可以从许多不同的样式中进行选择,使其适合您的网站设计;
  2. they are consistent across browsers (if you ever tried doing a unicode star character, you'll notice it's different in IE vs other browser);它们在浏览器中是一致的(如果你曾经尝试过使用 unicode 星号,你会发现它在 IE 和其他浏览器中是不同的);
  3. also, they are fully stylable, like the unicode characters you're trying to use.此外,它们是完全可样式化的,就像您尝试使用的 unicode 字符一样。

The only downside is that its one more thing for the browser to download when they view your page.唯一的缺点是浏览器在查看您的页面时要下载另一件事。

对于我在 OSX 上的解决方案是将 font-family 设置为EmojiSymbols

None of the solutions above worked for the "Emoji for Google Chrome" Extension.上述解决方案均不适用于“谷歌 Chrome 表情符号”扩展程序。

So as a workaround I made a screenshot of the Unicode Character 'BALLOT BOX WITH CHECK' (U+2611) and added it as image with php:因此,作为一种解决方法,我制作了 Unicode 字符 'BALLOT BOX WITH CHECK' (U+2611) 的屏幕截图,并使用 php 将其添加为图像:

 $ballotBoxWithCheck='<img src="pics/U2611.png" style="height:11px;margin-bottom:-1px">'; # &#9745; or /U2611

在此处输入图像描述

See: https://spacetrace.org/man_card.php?tec_id=21&techname=multi-emp-vessel见: https ://spacetrace.org/man_card.php?tec_id=21&techname=multi-emp-vessel

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM