【问题标题】:How to prevent Unicode characters from rendering as emoji in HTML from JavaScript?如何防止 Unicode 字符在 JavaScript 中呈现为 HTML 中的表情符号?
【发布时间】:2015-12-31 03:43:01
【问题描述】:

我正在为来自FileFormat.Info's search 的特殊字符查找 Unicode。

某些字符呈现为经典的黑白字形,例如 ⚠(警告标志,\u26A0⚠)。这些更可取,因为我可以将 CSS 样式(例如颜色)应用于它们。

其他人正在呈现为更新的卡通表情符号,例如⌛(沙漏,\u231B⌛)。这些不是可取的,因为我无法完全设置它们的样式。

浏览器似乎正在进行此更改,因为我可以在 Mac Firefox 上看到沙漏字形,但在 Mac Chrome 和 Mac Safari 上看不到。

有没有办法强制浏览器显示较旧的(单调)版本?

更新:似乎(来自下面的 cmets)有一个 text presentation selectorFE0E,可用于强制执行 text-vs-emoji。选择器作为不带空格的后缀连接到字符的代码上,例如⌛︎ 用于 HTML 十六进制或\u231B\uFE0E 用于 JS。但是,并非所有浏览器都支持它(例如 Chrome 和 Edge)。

【问题讨论】:

  • 您是否在 CSS 规则中设置了字体系列?
  • @janaspage ︎\uFE0E 是正确的(2 和 8)并且在 Safari(8 和 9)中工作正常,但就像答案所说:浏览器支持参差不齐,Chrome(46 ) 完全坏了。
  • 没有标准的方法来控制表情符号的呈现。
  • 您所要做的就是强制使用包含此字符字形的字体,并且其字形看起来符合您的要求(没有颜色、没有形状或任何您喜欢的东西)。

标签: javascript html css unicode emoji


【解决方案1】:

附加 Unicode variation selector 字符以强制文本,VS15,︎
这会强制将前一个字符呈现为文本而不是表情符号。

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

结果:?︎

了解更多信息:Unicode symbol as text or emoji

【讨论】:

  • 这非常有用,这就是我前几天投赞成票的原因。我想知道如何将表情符号粘贴到我正在撰写的 Facebook 广告中?附言这也很有趣:apple.stackexchange.com/a/240450/53510
  • 我刚刚意识到这个&amp;#xFE0E; 技巧不适用于某些字体。我很难找到一种我可以合理期望安装在所有机器(Windows、iOS、Mac、Android 等)上的字体。
  • 这种解决方案对于甚至可能出现在输入字段中的符号来说确实是不可接受的。我在逻辑中使用的符号 ↔ 遇到了这个问题,我一生都无法理解为什么有人认为这应该是一个表情符号!
  • 以下页面有助于在表情符号之后立即复制和粘贴该特殊字符,使其看起来扁平而不是风格化。例如。您可能会看到 ?︎ 而不是 ? 和 ?︎ 而不是 ? 和 ⌛︎ 而不是 ⌛ 和 ?︎ 而不是 ?(取决于您的设备)unicode-symbol.com/u/FE0E.html
  • 这在我的示例中呈现为表情符号,mac 10.11.6 上的 chrome 71。
【解决方案2】:

我在span::beforecontent 中有一个Unicode 字符,并且我将spanfont-family 设置为“Segoe UI 符号”。但是 Chrome 使用“Segoe UI Emoji”作为字体来渲染它。

但是,当我将font-family 设置为“Segoe UI 符号”明确span::before 而不仅仅是span,然后它就起作用了。

【讨论】:

  • 这应该是正确的答案,尤其是旧的不可见字符方法不受大多数​​主流浏览器的支持。
【解决方案3】:

对于阻止 iOS 显示表情符号的纯 CSS 解决方案,您可以使用 font-family: monospace,它默认为字形的文本变体,而不是表情符号变体。

【讨论】:

【解决方案4】:

如果您主要关心的是强制单色显示以使表情符号不会从文本中脱颖而出,那么 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>

与变体选择器不同,表情符号的呈现方式无关紧要,因为 CSS 过滤器适用于所有内容。 (我使用它们对已修改为指向 Wayback Machine 的超链接上的 PNG 格式的“链接类型”图标进行灰度化处理。)

请注意警告。您不能在子元素中覆盖父元素的过滤器,因此不能使用此技术对段落进行灰度化,然后重新着色其中的链接。 ?

...不过,它对于您要将整个内容设为超链接或不允许其中包含丰富标记的情况很有用。 (例如标题和描述)

但是,除非实际应用了 CSS,否则这将不起作用,所以我将提供第二个选项,它在 &lt;title&gt; 元素中比 Unicode 变体选择器更可靠(我在看你的 GitHub。我不知道) t 喜欢我的浏览器标签中的假图标):

如果您将用户提供的字符串放入 &lt;title&gt; 元素中,请过滤掉表情符号以及任何粗体/斜体/下划线/等。标记。 (是的,对于那些错过它的人,标准确实要求 &lt;title&gt; 的内容是纯文本,除了 & 符转义和我测试的浏览器将所有标签解释为文字文本。)

我能想到的两种方式是:

  1. 直接使用手动维护的regex 匹配最新版本的Unicode 放置其表情符号及其修饰符的块。
  2. 遍历字素簇和discard任何包含可识别的表情符号代码点。 (字素簇是基本字形加上构成可见字符的所有变音符号和其他修饰符。我链接到的示例使用 Python 的正则表达式引擎进行标记,然后使用数据库的 emoji 包,但 Rust 是一个很好的例子通过像 unicode-segmentation 这样的 crate 可以快速轻松地迭代字素簇的语言。)

【讨论】:

    【解决方案5】:

    其他解决方案都不适合我,但我最终找到了由css-tricks 提供的东西。在我的用例中,我在每个 Markdown 标题的末尾添加了一个链接符号,用于直接链接到文章中的部分,但表情符号看起来有点分散注意力。下面的代码让我可以让表情符号看起来像一个普通的符号,然后在悬停在上面时切换回看起来像一个表情符号,这非常适合我的用例。如果您只是想让图标看起来更像一个符号,只需将 text-shadow 十六进制颜色更改为 #000,如第二个示例所示。

    .direct-link {
      color: transparent;
      text-shadow: 0 0 #dbe2ec;
    }
    
    .direct-link:hover {
      color: inherit;
    }
    &lt;h3&gt;Blog Subheading&lt;a href='#' class="direct-link"&gt;?&lt;/a&gt;&lt;/h3&gt;

       .direct-link {
          color: transparent;
          text-shadow: 0 0 #000;
        }
        &lt;h3&gt;Blog Subheading&lt;a href='#' class="direct-link"&gt;?&lt;/a&gt;&lt;/h3&gt;

    【讨论】:

    • 短语“没有其他”是模棱两可的。在您写这篇文章之前,我们不知道存在哪些答案。 (是的,我们可以查看日期,但是……)
    【解决方案6】:

    Android 字体并不像您想象的那样丰富。 字体文件没有这些奇异的字形,Android 对没有字形的少数字符进行了破解。它们被图标替换。

    因此,解决方案是将网站与网络字体 (woff) 集成。 例如,使用 FontForge 创建新字体文件并从免费衬线 TTF 中选择所需的字形。每个字形需要 1k。生成 woff 文件。

    准备简单的 CSS 以导入自定义字体系列。

    style.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 文件:

    <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>
    

    【讨论】:

      【解决方案7】:

      Google Chrome,桌面版本 75,似乎根据加载页面时遇到的第一个 Unicode 转义来消除其呈现 Unicode 字符的方法。例如,当被解析为页面源中的第一个 HTML Unicode 转义,并且没有等效的表情符号时,⏷似乎向 Chrome 澄清了该页面包含不被呈现为表情符号的转义。

      【讨论】:

        【解决方案8】:

        ssokolow's answer 的基础上扩展,使用过滤器很好,至少可以使轮廓可见,而不是使用简单的字体,但是当您想使用特定颜色时,将 RGB 颜色转换为一系列 CSS 过滤器非常困难.

        一个更好的(虽然很冗长)选项是使用&lt;feColorMatrix&gt; SVG 过滤器。结合灰度过滤器和数据 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");
        }
        

        不幸的是,您不能在 URL 中插入数据(取自属性或变量),但至少您不必根据 RGB 计算 CSS 过滤器。

        【讨论】:

          【解决方案9】:

          我的具体版本问题

          我的网站在 CSS 伪元素::after::before)中使用 ◀︎(黑色右指向三角形)和类似字符来指示列表中的当前项目。

          在我的测试中,我总是使用the triangle character and the variation selector 15 together。首先,我使用了来自Google Fontswebfont安装在设备上的字体,它们都应该包含这些字符的字形,但出于某种原因,这个假设一定是错的。我还在 Google Fonts 上尝试了不同的子集,但无济于事:我的两台带有 Google Chrome 和 Samsung Internet (Chromium) 的 Android 设备总是呈现表情符号而不是文本字形。

          我的解决方案

          我的解决方案是下载 Gnu Free Font 的最新 WOFF(我知道其中包含这些字符的字形),将其包含在我的项目中,并使用 @font-face 定义它:

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

          然后,为我的伪元素设置样式:

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

          讨论

          我还不确定仅对这几个字符使用 786K 额外字体对性能的影响。如果这成为问题,应该可以使用仅包含这些字符的精简自定义字体。

          【讨论】:

            【解决方案10】:

            我不知道关闭表情符号类型渲染的方法。通常我使用font awesomeglyphicons等图标字体(Bootstrap 3自带)。

            使用这些而不是 unicode 字符的好处是

            1. 您可以从许多不同的样式中进行选择,使其适合您的网站设计;
            2. 它们在浏览器中是一致的(如果您尝试过使用 unicode 星号,您会发现它在 IE 和其他浏览器中有所不同);
            3. 此外,它们是完全可设置样式的,就像您尝试使用的 unicode 字符一样。

            唯一的缺点是浏览器在查看您的页面时要下载另一件事。

            【讨论】:

              【解决方案11】:

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

              【讨论】:

                【解决方案12】:

                上述解决方案均不适用于“谷歌 Chrome 表情符号”扩展程序。

                所以作为一种解决方法我制作了 Unicode 字符“BALLOT BOX WITH CHECK”(U+2611) 的屏幕截图,并使用 php 将其添加为图像:

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

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

                【讨论】:

                • 几乎可以肯定,最好使用文本工具将其粘贴到 Inkscape 中(使用选择了合适许可证的字体),然后运行自动跟踪,这样您就可以从中获取 SVG将缩放到您需要的任何大小。 (为了使其尽可能小,请将 SVG 缩小器与一些手动编辑配对,以减少自动跟踪出错的路径中的节点数量。)
                猜你喜欢
                • 2023-03-22
                • 1970-01-01
                • 1970-01-01
                • 2016-10-22
                • 1970-01-01
                • 2015-05-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多