---
title: The GraphicalEmoji hack
date: 2023-03-08
tags:
- cursed
- JavaScript
- JSX
- fontRendering
- dearGodHelpMe
---
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:
- ⚠︎ (the textual form)
- ⚠️ (the graphical
form)
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:
- Adding the explicit "make this graphical" Unicode instruction:
`\u{FE0F}`
- Declaring the emoji as the string `"\u{26A0}\u{FE0F}"` and then
using it as a variable: `{warningEmoji}`
- Using the variable in a format string:
<span>{`${warningEmoji}`}</span>
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:
```html
⚠️
```
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
Times New Roman
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:
```js
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 times new roman 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 {emoji};
}
```
This code is free as in mattress. If you decide to use it, it's your
problem.
I hate fonts.