Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

Does UTF-8 include emoji?

Emojis look like images, or icons, but they are not. They are letters (characters) from the UTF-8 (Unicode) character set.

Can Unicode represent Emojis?

Unicode provides a number of emoji resources which provides more information about emoji. In particular, Unicode Emoji TR #51 outlines many details of the entire emoji set. For questions about new emoji proposals or why a certain emoji does not exist, please see the Emoji Submission FAQ.

Can HTML render Unicode?

You can enter any Unicode character in an HTML file by taking its decimal numeric character reference and adding an ampersand and a hash at the front and a semi-colon at the end, for example — should display as an em dash (—). This is the method used in the Unicode test pages.


Append the Unicode variation selector character for forcing text, VS15, ︎.
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


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". But Chrome used "Segoe UI Emoji" as the font to render it.

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.


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.


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.

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. (I use them to grayscale PNG-format "link type" icons on hyperlinks that have been modified to point to the Wayback Machine.)

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

If you're putting a user-provided string into a <title> element, filter out the emoji along with any bold/italic/underline/etc. 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.)

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

None of the other solutions worked for me but I eventually found something that did courtesy of 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. 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.

.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. Font files don't have these exotic glyph and Android has a hack for few characters without glyph. They are replaced with icons.

So solution is to integrate the site with a web font (woff). Create new font file with FontForge and pick required glyph from free serif TTF for example. Every glyph takes 1k. Generate woff file.

Prepare simple CSS to import the custom font family.

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

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