The GraphicalEmoji hack

Published on , 453 words, 2 minutes to read

Today, I tried to write a JSX component that included an emoji in it. Specifically this emoji: ⚠️.

This emoji is special because there's actually two forms of it:

EDIT: Apparently this difference isn't showing up on every browser engine the same way. Please trust me that there is a difference, one of them on my MacBook running Microsoft Edge is a text-only emoji that has no color in it. This is why I was so confused, scared, and on the verge of tears after being gaslit by my browser. God is dead because font rendering killed him.

When I was making this component, I wanted the graphical form of it. The following things did not work:


Turns out, this is actually a fairly widespread problem with fonts that have the textual form of emoji defined but not the graphical form of it defined. The font my blog uses is one of them, so to get the graphical ⚠️ I've been using above, I had to paste this HTML snippet:

<span style="font-family: Papyrus">⚠️</span>
Aoi is facepalm

Oh god. Really? That is so, so cursed.

Yes, really. In order to make the emoji render correctly, I had to instruct the browser to render it in

Papyrus because that does not have the emoji defined. It will then fall back to the system font, giving us the ⚠️ that we truly desire.

Here is the JSX component I had to write:

export interface GraphicalEmojiProps {
  emoji: string;

/** Listen to me for my tale of woe:
 * Fonts are complicated. Fun fact: fonts are actually Turing-complete programs
 * that run in browsers. Yes, font rendering is really that complicated. This
 * component is a dirty, ugly, disgusting HACK that works around font
 * rendering in order to forcibly display the graphical form of an emoji.
 * This works because Papyrus always displays the graphical forms of
 * emoji. No, I don't know why either. It slightly scares me.
 * Either way, this works and I'm not brave enough to question why.
export default function GraphicalEmoji({ emoji }: GraphicalEmojiProps) {
  return <span style={{ fontFamily: "Papyrus" }}>{emoji}</span>;

This code is free as in mattress. If you decide to use it, it's your problem.

Cadey is coffee

I hate fonts.

Facts and circumstances may have changed since publication. Please contact me before jumping to conclusions if something seems wrong or unclear.

Tags: cursed, JavaScript, JSX, fontRendering, dearGodHelpMe