← All articles

Killing the Tofu Box for Good: Grafting a Star into Noto Color Emoji

June 8, 2026 · Trent Tompkins

That empty box isn't a broken character - it's a missing glyph. Here's how I stopped patching tofu with SVGs and built a font that physically can't tofu.

You've seen it: a little empty rectangle where a symbol should be. Designers call it tofu. The text is fine - the font just doesn't contain a shape for that codepoint, so the browser draws a box and moves on.

It bit me on a tiny "★ wildcard" badge in an admin panel. Instead of a star, I got □ wildcard.

The one insight that explains every tofu box

A font-family stack is resolved per character. For each codepoint the browser walks your stack until a font has a glyph for it. If none do - tofu.

The trap is subtle: emoji fonts don't contain text dingbats.

  • is U+2605 BLACK STAR - a text symbol.
  • is U+2B50 - an emoji.

My stack ended in Noto Color Emoji (self-hosted, so symbols render the same on every OS). Noto has the emoji star but not the text star - so the browser routed to the emoji font, found nothing, and boxed it. I confirmed it with a 20-line glyph viewer:

DelaGothicOne-Regular:  U+2605 PRESENT
NotoColorEmoji.v2:      U+2605 MISSING

Fix #1: inline SVG (fine for one icon)

Swap the character for an inline <svg> star. Zero font dependency, renders everywhere. But you can't SVG every ★, →, ✓ across a dozen sites. It doesn't scale.

Fix #2: just add the glyph to the font

Here's the move almost no one reaches for: a font is editable. If Noto is missing , graft it in - borrowed from a font that has it (Dela Gothic One) - using fontTools. The only wrinkle is unit scaling: Dela is 1000 units/em, Noto is 1024.

scale = noto['head'].unitsPerEm / dela['head'].unitsPerEm   # 1024/1000
pen   = TTGlyphPen(None)
DecomposingRecordingPen(dela.getGlyphSet())[star].replay(
    TransformPen(pen, (scale, 0, 0, scale, 0, 0)))          # scaled outline

glyf.glyphs[name] = pen.glyph()
glyf.glyphOrder.append(name)                                # keep glyphs + order in sync
for t in noto['cmap'].tables:
    if t.isUnicode():
        t.cmap[0x2605] = name                               # U+2605 now resolves
noto.save('TrioEmojiStar.woff2')

The best part: the star lands in the glyf table with no COLR color layer, so it renders in currentColor - a clean, themeable black star - while all 1,485 real emoji keep their color. One font, every emoji plus the star, and it physically cannot tofu that codepoint.

The payoff

Tofu is never a mystery. It's a missing glyph - and a glyph is just data you can add.


Originally posted on trentontompkins.com. Grab the kit (both fonts + the glyph viewer + the font forge): never-tofu-font-kit.zip.

Subscribe via RSS